<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0"><channel><title>Glance Specs</title><link>http://specs.openstack.org/openstack/glance-specs</link><description /><language>en</language><copyright>2026, OpenStack Glance Team</copyright><item><title>2026.2 Project Priorities</title><link>http://specs.openstack.org/openstack/glance-specs/priorities/2026.2-priorities.html</link><description>
&lt;span id="priorities"/&gt;
&lt;p&gt;TODO(glance-ptl): fill this in after the PTG&lt;/p&gt;
</description><pubDate>Mon, 09 Mar 2026 00:00:00 </pubDate></item><item><title>Example Spec - The title of your blueprint</title><link>http://specs.openstack.org/openstack/glance-specs/specs/juno/example.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/glance/+spec/example"&gt;https://blueprints.launchpad.net/glance/+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.&lt;/p&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/glance/+spec/awesome-thing"&gt;https://blueprints.launchpad.net/glance/+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, or see:
&lt;a class="reference external" href="https://www.siafoo.net/reST.xml"&gt;https://www.siafoo.net/reST.xml&lt;/a&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 Glance 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/glance-specs+message:apiimpact,n,z"&gt;https://review.openstack.org/#/q/status:open+project:openstack/glance-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:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;For a new feature this might be use cases. Ensure you are clear about the
actors in each use case: End User vs Deployer&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For a major reworking of something existing it would describe the
problems in that feature that are being addressed.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&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;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;Glance is committed to zero-downtime database migrations and has adopted an
&lt;a class="reference external" href="https://docs.openstack.org/developer/glance/database_migrations.html"&gt;E-M-C migration strategy&lt;/a&gt;
to achieve this.  Address the following in sufficient detail to make it clear
that the intended database change will be achieved.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Will this change require database triggers?  If yes, describe them.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Explain what your expand migrations will look like.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Explain what your data migrations will look like.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Explain what your contract migrations will look like.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Finally, do these changes have the potential to interfere with the
database migrations for other specs that have been approved for this
cycle?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&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 images, 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;An /api directory is now included for REST API updates. 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/PATCH)&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;/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 body data if allowed&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;JSON schema definition for the response data if any&lt;/p&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 Glance tree
&lt;a class="reference external" href="https://opendev.org/openstack/glance/src/branch/master/glance/api/v2/tasks.py#L342"&gt;https://opendev.org/openstack/glance/src/branch/master/glance/api/v2/tasks.py#L342&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 (i.e.
additionalProperties 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. This includes introduction of a
new notification, changes to an existing notification, or removing a
notification.&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;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-glanceclient? 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. How often will new
code be called? 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 small change in a utility function or a commonly used decorator can have a
large impact on performance.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Calls which result in database queries 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;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 widgets are stored in, how do we handle
widget 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 widgets 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 store API, discussion of how
stores would implement the feature is required.&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="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 glance, 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 Glance: 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 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;What is the impact on the docs team of this change? Some changes might require
donating resources to the docs team to have the documentation updated. Don’t
repeat details discussed above, but please reference them here.&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;
</description><pubDate>Wed, 14 Jan 2026 00:00:00 </pubDate></item><item><title>Example Spec - The title of your blueprint</title><link>http://specs.openstack.org/openstack/glance-specs/specs/kilo/example.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/glance/+spec/example"&gt;https://blueprints.launchpad.net/glance/+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.&lt;/p&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/glance/+spec/awesome-thing"&gt;https://blueprints.launchpad.net/glance/+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, or see:
&lt;a class="reference external" href="https://www.siafoo.net/reST.xml"&gt;https://www.siafoo.net/reST.xml&lt;/a&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 Glance 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/glance-specs+message:apiimpact,n,z"&gt;https://review.openstack.org/#/q/status:open+project:openstack/glance-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:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;For a new feature this might be use cases. Ensure you are clear about the
actors in each use case: End User vs Deployer&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For a major reworking of something existing it would describe the
problems in that feature that are being addressed.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&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;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;Glance is committed to zero-downtime database migrations and has adopted an
&lt;a class="reference external" href="https://docs.openstack.org/developer/glance/database_migrations.html"&gt;E-M-C migration strategy&lt;/a&gt;
to achieve this.  Address the following in sufficient detail to make it clear
that the intended database change will be achieved.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Will this change require database triggers?  If yes, describe them.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Explain what your expand migrations will look like.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Explain what your data migrations will look like.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Explain what your contract migrations will look like.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Finally, do these changes have the potential to interfere with the
database migrations for other specs that have been approved for this
cycle?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&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 images, 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;An /api directory is now included for REST API updates. 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/PATCH)&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;/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 body data if allowed&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;JSON schema definition for the response data if any&lt;/p&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 Glance tree
&lt;a class="reference external" href="https://opendev.org/openstack/glance/src/branch/master/glance/api/v2/tasks.py#L342"&gt;https://opendev.org/openstack/glance/src/branch/master/glance/api/v2/tasks.py#L342&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 (i.e.
additionalProperties 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. This includes introduction of a
new notification, changes to an existing notification, or removing a
notification.&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;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-glanceclient? 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. How often will new
code be called? 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 small change in a utility function or a commonly used decorator can have a
large impact on performance.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Calls which result in database queries 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;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 widgets are stored in, how do we handle
widget 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 widgets 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 store API, discussion of how
stores would implement the feature is required.&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="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 glance, 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 Glance: 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 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;What is the impact on the docs team of this change? Some changes might require
donating resources to the docs team to have the documentation updated. Don’t
repeat details discussed above, but please reference them here.&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;
</description><pubDate>Wed, 14 Jan 2026 00:00:00 </pubDate></item><item><title>Add support to configure weight for each store</title><link>http://specs.openstack.org/openstack/glance-specs/specs/2023.2/approved/glance_store/store-weight.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/glance-store/+spec/store-weight"&gt;https://blueprints.launchpad.net/glance-store/+spec/store-weight&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Add support to configure weight to each store. The store with highest
weight will be given preference to download the image.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Since introduction of importing single image into multiple stores or copying
existing image into multiple stores, single image can be stored at multiple
locations or different stores configured by glance.  Current download image
is based on the default &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;location_strategy&lt;/span&gt;&lt;/code&gt; which is &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;location_order&lt;/span&gt;&lt;/code&gt;,
traverse through the image locations one by one if there are multiple
locations (in this case it will return the image stored at the first
location). If user prefers to download the image from a specific store then
they can use &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;store_type&lt;/span&gt;&lt;/code&gt; as location strategy to give preference to
download the image from that store only. For example if &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;location_strategy&lt;/span&gt;&lt;/code&gt;
is set as &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;store_type&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;store_type&lt;/span&gt;&lt;/code&gt; has &lt;cite&gt;rbd&lt;/cite&gt; as preference then
the image will be downloaded from the &lt;cite&gt;rbd&lt;/cite&gt; store only. Now the problem with
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;store_type&lt;/span&gt;&lt;/code&gt; location strategy is that there can be multiple stores of same
type (multiple rbd or file stores). So again user will not able to download
the image from the specific store even if &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;location_strategy&lt;/span&gt;&lt;/code&gt; is set to
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;store_type&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Consider the following use cases for providing download from specific
store support:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;I have a large image and want to download it from the SSD store
since it’s fast.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I do multiple concurrent downloads on a particular image so
want to download it from the RELIABLE store since the i/o
handling is better.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;This proposal requires changes in glance_store as well as in glance.&lt;/p&gt;
&lt;p&gt;Glance store side change:&lt;/p&gt;
&lt;p&gt;Add new configuration option &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;weight&lt;/span&gt;&lt;/code&gt; default to zero for each store.
Operator can change it for each store if they wish. The store with highest
weight will be given preference to download the image from.&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;[default]&lt;/span&gt;
&lt;span class="na"&gt;enabled_backends&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;robust:rbd,cheap:file&lt;/span&gt;

&lt;span class="k"&gt;[robust]&lt;/span&gt;
&lt;span class="na"&gt;rbd_store_pool&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;images&lt;/span&gt;
&lt;span class="na"&gt;weight&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;10&lt;/span&gt;

&lt;span class="k"&gt;[cheap]&lt;/span&gt;
&lt;span class="na"&gt;filesystem_store_datadir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/opt/stack/data/glance/images/&lt;/span&gt;
&lt;span class="na"&gt;weight&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;5&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;In above example, &lt;cite&gt;robust&lt;/cite&gt; store will always be a preferred store to download
the image from. If image is not available in &lt;cite&gt;robust&lt;/cite&gt; store then it will be
searched in &lt;cite&gt;cheap&lt;/cite&gt; store which is next inline.&lt;/p&gt;
&lt;p&gt;If no weight is provided for stores (i.e. all stores have default weight &lt;cite&gt;0&lt;/cite&gt;)
then the image will be searched based on image creation order (similar as
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;location_order&lt;/span&gt;&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;Glance side change:&lt;/p&gt;
&lt;p&gt;Once glance_store side changes are implemented then we need to modify
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt;&lt;/code&gt; API of image to sort the image locations based on the &lt;cite&gt;wegith&lt;/cite&gt;
assigned to each store. If &lt;cite&gt;weight&lt;/cite&gt; is default then the location
order will not be changed.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Add new location strategy ‘store_identifier’ to existing default two
strategies. This will add comma separated list of store identifiers which
will be given preference to download the image from. New configuration
option &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;store_identifier_preference&lt;/span&gt;&lt;/code&gt; under group
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;store_identifier_location_strategy&lt;/span&gt;&lt;/code&gt; will be added where user/deployer
can reference their preferences based on store identifiers.&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/Operator need to configure &lt;cite&gt;weight&lt;/cite&gt; for each glance-store.&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;dansmith&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&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="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Add new configuration option &lt;cite&gt;weight&lt;/cite&gt; for each store&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET API change to sort locations based on store &lt;cite&gt;weight&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;p&gt;Tempest coverage&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;Sufficient unit/functional and tempest 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;p&gt;Need to document how location order will be changed based on weight
assigned to each store.&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>Sun, 11 Jan 2026 00:00:00 </pubDate></item><item><title>Glance as first-line defense for image format attacks</title><link>http://specs.openstack.org/openstack/glance-specs/specs/2025.1/approved/glance/glance-as-defender.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/glance/+spec/glance-as-defender"&gt;https://blueprints.launchpad.net/glance/+spec/glance-as-defender&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Glance is the point of entry for images into the cloud. It is the orifice
through which an untrusted (but authenticated) user brings an image into the
system, after which it will be processed by backend routines either for format
conversion or preparation for boot.&lt;/p&gt;
&lt;p&gt;It is at this stage in the pipeline where we are best positioned to do sanity
checking about the images we accept, and the point at which we can validate
some of the metadata provided by the user to ensure that downstream services
(such as nova, glance, ironic and others) can reasonably assume that metadata
to be correct.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Glance will (for the most part) allow a user to upload literally content and
declare its format to be any of the valid values we have for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;disk_format&lt;/span&gt;&lt;/code&gt; and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;container_format&lt;/span&gt;&lt;/code&gt;. This is certainly surprising to downstream services,
external consumers, and humans which expect the format stated on the image to
be in line with the actual content.&lt;/p&gt;
&lt;p&gt;A further problem is in the use of the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;raw&lt;/span&gt;&lt;/code&gt; value for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;disk_format&lt;/span&gt;&lt;/code&gt;. In
general, we use &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;raw&lt;/span&gt;&lt;/code&gt; to mean “a byte-for-byte image of a block device”,
usually with a partition table and often a bootloader (in the case of a root
disk). However, in reality &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;raw&lt;/span&gt;&lt;/code&gt; has come to mean “anything in a format for
which we do not have another name”. This catch-all behavior means that if we
want to support images of full-disk formats, we also need to support
“anything else we don’t know about” to some degree.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;This spec proposes two major changes to glance:&lt;/p&gt;
&lt;p&gt;First, we will start enforcing that the format of the uploaded content matches
the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;disk_format&lt;/span&gt;&lt;/code&gt; declared on the image. Since our &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;format_inspector&lt;/span&gt;&lt;/code&gt; module
is already in the data pipeline for both &lt;em&gt;upload&lt;/em&gt; and &lt;em&gt;import&lt;/em&gt; we simply need
to remove the “never fail” behavior we currently have and abort the process
if we determine that the format does not match what was claimed. Consider the
following two examples:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;An image is declared to be of format &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;qcow2&lt;/span&gt;&lt;/code&gt; but the content uploaded is
something else (either another complex format such as &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;vmdk&lt;/span&gt;&lt;/code&gt; or something
we do not recognize).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;An image is declared to be of format &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;raw&lt;/span&gt;&lt;/code&gt; but the content uploaded is
detected as a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;qcow2&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Ideally, we would reject both of these cases. However, the second is more
complex because there are situations where a service handling a disk image
that it does not assume any particular format may be stopped from storing it
in glance if the user of that image has given it a specific format. Thus, for
the first iteration of this work, we will only enforce the first case, which
means that &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;raw&lt;/span&gt;&lt;/code&gt; could contain a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;qcow2&lt;/span&gt;&lt;/code&gt;, but a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;vmdk&lt;/span&gt;&lt;/code&gt; could not.&lt;/p&gt;
&lt;p&gt;The use of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[image_format]/disk_formats&lt;/span&gt;&lt;/code&gt; will effectively
allow an admin to limit the types of disks they accept. Today, that only
limits “honest” users, but this change will make it enforced on content as
well.&lt;/p&gt;
&lt;p&gt;The second major change is significant in terms of the model and behavior
of existing users, but is small in absolute terms and impact to glance itself.
A new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;disk_format&lt;/span&gt;&lt;/code&gt; option of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;gpt&lt;/span&gt;&lt;/code&gt; will be added, which will henceforth
serve to signify that “this is an image of a raw block device with a partition
table” thus removing our need to overlap that definition with “this is
something we do not recognize” for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;raw&lt;/span&gt;&lt;/code&gt;. The definition of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;gpt&lt;/span&gt;&lt;/code&gt; is
actually a superset of the legacy PC MBR (Master Boot Record) format, which
means an inspector for this format should have no problem detecting and
allowing images of very old (read: Windows XP/2003 vintage) disk images. Thus,
many of the images we now legitimately use &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;raw&lt;/span&gt;&lt;/code&gt; for will be (and need to be
converted to be) a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;disk_format&lt;/span&gt;&lt;/code&gt; of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;gpt&lt;/span&gt;&lt;/code&gt; going forward.&lt;/p&gt;
&lt;p&gt;We will add a configuration option to disable this behavior as a relief valve
to support migration to this stricter model and/or to account for false
positive detections.&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;require_image_format_match&lt;/span&gt;&lt;/code&gt;: Default to true, but allow setting to false
to avoid aborting the upload/import if the format does not match the content.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Glance could continue to be ambivalent about the content uploaded and the
mismatch between that and the metadata it stores. Services like nova and
cinder will have to continue treating glance as untrustworthy and remain
highly suspicious of its metadata.&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 only data model change that should be required here is one to allow the
new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;disk_format&lt;/span&gt;&lt;/code&gt; value of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;gpt&lt;/span&gt;&lt;/code&gt; to be specified in the API and stored in
the database.&lt;/p&gt;
&lt;p&gt;There will, of course, be a need to convert existing &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;raw&lt;/span&gt;&lt;/code&gt; images in the
database to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;gpt&lt;/span&gt;&lt;/code&gt;, and thus some tooling will be required. Options for that
could be a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance-manage&lt;/span&gt;&lt;/code&gt; command to automatically (or manually) do this,
or allow it to be done through the API. Alternately, we could also annotate
existing images and have the API report them as &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;gpt&lt;/span&gt;&lt;/code&gt; if the client is
determined to be new enough.&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 main REST API impact comes from allowing &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;gpt&lt;/span&gt;&lt;/code&gt; as one of the valid
options for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;disk_format&lt;/span&gt;&lt;/code&gt;. Additional impact could come if we decide to
provide format conversion (or reporting) through 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;In general, this will improve security for the entire cloud by allowing nova,
cinder, and other users of glance some amount of trust in the image content
and associated metadata. It is important to avoid the other services
thinking they no longer need to inspect image content entirely. Security for
this sort of thing is best provided in layers and services need to continue
to be vigilant about images they download from glance, certainly applying
context-specific checks before using them.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None (aside from the new format).&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 defintitely be impacted as the muscle memory of (over) using raw as
both a catch-all and as meaning “an image of a whole disk” will take some
time to un-learn.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;We are already using &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;format_inspector&lt;/span&gt;&lt;/code&gt; in the data pipeline. We will need to
run all the inspectors in parallel instead of just the declared-format one
we are currently using. However, these are designed to be as memory-efficient
as possible, and thus the overhead should be minimal. Actual performance of
the upload itself should not be impacted.&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 work to do here for sure, specifically as existing disks
marked as &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;raw&lt;/span&gt;&lt;/code&gt; will (mostly) need to be converted to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;gpt&lt;/span&gt;&lt;/code&gt;. We can not
just convert any &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;raw&lt;/span&gt;&lt;/code&gt;, as many of those may be kernel images, or other
formats that we do not (but probably need to) support identifying.&lt;/p&gt;
&lt;p&gt;Options for that would be:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Tell operators to just do it themselves and provide some way to change the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;disk_format&lt;/span&gt;&lt;/code&gt; of an image in the database.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Provide a tool to detect and convert the images based on content. We can,
in many cases, do this without seeing the whole image, as things that
should be &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;gpt&lt;/span&gt;&lt;/code&gt; will be identified within the first sector or two of
the content. This could be used only for converting &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;raw&lt;/span&gt;&lt;/code&gt; to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;gpt&lt;/span&gt;&lt;/code&gt;, but
could be written generically in a way that allows operators to audit all
their images to make sure they are in the format they claim to be.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;No specific impact, although as more formats need to be supported, additional
inspector modules will need to be written.&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;Make the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;format_inspector&lt;/span&gt;&lt;/code&gt; in the data pipeline detect all formats and
abort the upload if the format is determined and does not match&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Make glance depend on &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo.utils&lt;/span&gt;&lt;/code&gt; for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;format_inspector&lt;/span&gt;&lt;/code&gt;&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;gpt&lt;/span&gt;&lt;/code&gt; as a valid &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;disk_format&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Write tooling for converting &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;raw&lt;/span&gt;&lt;/code&gt; disks to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;gpt&lt;/span&gt;&lt;/code&gt; in the database&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add config options for new/fallback behaviors&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;cite&gt;gpt&lt;/cite&gt; part of this depends on the &lt;a class="reference external" href="https://review.opendev.org/q/topic:%22add-format-inspector%22"&gt;oslo port of the inspector&lt;/a&gt; code.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;We will need negative tempest tests for format mismatches, which can be written
without much drama. Most of the formats require just a few 512-byte sectors of
data to be detected and we can generate those inline in tempest tests to make
sure that glance rejects mismatches.&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 definitely need documentation about the raw-to-gpt behavior change,
and we could definitely use better documentation about when to use &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;raw&lt;/span&gt;&lt;/code&gt;,
which will be easier to explain in the context of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;gpt&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;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://bugs.launchpad.net/nova/+bug/2059809"&gt;QCOW data-file security bug&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/1996188"&gt;VMDK safety security bug&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://uefi.org/specs/UEFI/2.10/05_GUID_Partition_Table_Format.html#id5"&gt;GPT format specification&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
</description><pubDate>Sun, 11 Jan 2026 00:00:00 </pubDate></item><item><title>S3 Store Boto3 Checksum Behavior Configuration</title><link>http://specs.openstack.org/openstack/glance-specs/specs/2026.1/approved/glance_store/s3-boto3-checksum-improvements.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/glance-store/+spec/s3-boto3-checksum-improvements"&gt;https://blueprints.launchpad.net/glance-store/+spec/s3-boto3-checksum-improvements&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Add config options to control boto3 S3 checksum behavior. This fix problems
with S3-compatible storage that came with boto3 1.36.x. Operators can now keep
using old S3-compatible storage and also use new AWS S3 data integrity features.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Boto3 1.36.0 added new S3 “data integrity” protections that run by default.
This means boto3 now calculates checksums for requests and validates checksums
in responses. This is good for data integrity but many S3-compatible storage
systems do not support this yet. For example, Ceph RGW does not work with
these new features.&lt;/p&gt;
&lt;p&gt;This breaks Glance image uploads to S3-compatible storage. Users see errors
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;botocore&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exceptions&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ClientError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;An&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="n"&gt;occurred&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MissingContentLength&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;when&lt;/span&gt; &lt;span class="n"&gt;calling&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;PutObject&lt;/span&gt; &lt;span class="n"&gt;operation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;The&lt;/span&gt; &lt;span class="n"&gt;internal&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;2011&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;This problem is in Launchpad bug #2121144. Users who upgrade from Dalmatian
to Epoxy see this problem because boto3 upgraded from 1.35.x to 1.36.x.&lt;/p&gt;
&lt;p&gt;Current workaround is to set environment variables:&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;export&lt;/span&gt; &lt;span class="n"&gt;AWS_REQUEST_CHECKSUM_CALCULATION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;WHEN_REQUIRED&lt;/span&gt;
&lt;span class="n"&gt;export&lt;/span&gt; &lt;span class="n"&gt;AWS_RESPONSE_CHECKSUM_VALIDATION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;WHEN_REQUIRED&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;But this is not good because it affects all boto3 usage in the system, not
only Glance. This is not good for production with different storage backends.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Add three new config options to S3 store driver to control boto3 checksum
behavior:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;s3_store_enable_data_integrity_protection (boolean, default: false)
- Turn on/off boto3 data integrity features
- When false: Use ‘when_required’ behavior for compatibility
- When true: Use the configured checksum settings&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;s3_store_request_checksum_calculation (string, default: ‘when_required’)
- Control when boto3 calculates request checksums
- Options: ‘when_required’, ‘always’, ‘never’&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;s3_store_response_checksum_validation (string, default: ‘when_required’)
- Control when boto3 validates response checksums
- Options: ‘when_required’, ‘always’, ‘never’&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;We will change the _create_s3_client method in S3 store driver to use these
config options when creating boto3 S3 client.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Environment Variables: Current workaround with environment variables is
not good for production because it affects all boto3 usage globally.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Boto3 Version Pinning: Downgrade boto3 version will lose other improvements
and security fixes in newer versions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Storage Backend Detection: Automatically detect S3-compatible vs AWS S3
is not reliable and has many errors.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Config-based approach gives most flexibility and control. It also keeps
backward compatibility.&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 is good for security. Operators can enable better data integrity
protection for AWS S3 deployments. At same time, they can keep compatibility
with S3-compatible storage backends. Default behavior keeps current security
for existing deployments.&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;Change has very small performance impact:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;When data integrity protection is disabled (default), performance is same
as current behavior&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When enabled, there is small overhead from checksum calculation and
validation, but this gives better data integrity&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;This change works immediately after merge. For existing deployments:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;No changes required - Default behavior works with existing S3-compatible
storage backends&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For AWS S3 deployments wanting better data integrity: Set
s3_store_enable_data_integrity_protection = true and configure checksum
behavior&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For mixed environments: Use different backends with different configs&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 change adds new config options to S3 store driver and changes client
creation logic. Other developers working on Glance store drivers should know
about this new config pattern for handling boto3 compatibility problems.&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;abhishekk&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 new config options to S3 store driver and use them in client creation
logic&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add unit tests for all configuration scenarios&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add multistore tests for different backend configurations&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update s3 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 change needs boto3 1.36.x or later for the new checksum config options&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;No new library dependencies needed&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;Add unit and tempest tests to cover all configuration scenarios.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Update configuration reference documentation to explain the new S3 store
config options. Add configuration examples and migration guidance to help
operators understand how to configure these options for their use cases.&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;Launchpad Bug #2121144: Image uploads to S3-compatible storage fail with
Epoxy version&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;boto3 Issue #4392: S3 data integrity protections enabled by default&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;boto3 Issue #4398: Guidance on checksum behavior configuration&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
</description><pubDate>Sun, 11 Jan 2026 00:00:00 </pubDate></item><item><title>Add bash completion for command line</title><link>http://specs.openstack.org/openstack/glance-specs/specs/juno/add-bash-completion.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/python-glanceclient/+spec/add-bash-completion"&gt;https://blueprints.launchpad.net/python-glanceclient/+spec/add-bash-completion&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Currently glance client does not support command completion.
The intention is to add this functionality to the client.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Nowadays glance client does not have bash completion for the command line.
This feature will improve the client usability.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Incorporation of bash completion feature.
This feature uses the linux script called bash_completion.d to
request all the commands and parameters to Glance through
bash_completion command. After obtaining them, they are filtered
and shown.&lt;/p&gt;
&lt;p&gt;Example of use:&lt;/p&gt;
&lt;p&gt;glance &amp;lt;tab&amp;gt;&amp;lt;tab&amp;gt; —&amp;gt;shows all the commands&lt;/p&gt;
&lt;p&gt;glance image- &amp;lt;tab&amp;gt;&amp;lt;tab&amp;gt; —&amp;gt;shows all the commands starting with the
word ‘image’: image-list, image-show, image-create…&lt;/p&gt;
&lt;p&gt;If there is only one, it will be completed.&lt;/p&gt;
&lt;p&gt;glance image-create &amp;lt;tab&amp;gt;&amp;lt;tab&amp;gt; —&amp;gt; shows all optional arguments&lt;/p&gt;
&lt;p&gt;To complete this feature, it is needed to modify devstack and the packaging
tool in order to include this script in the installer (deb, rpm).&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;This change needs copying of the glance.bash_completion to specific
system path:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;This will affect devstack&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;This will affect specific packaging (deb, rpm)&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;Commands and Parameters are extracted directly from argparse.
Developers won’t need to maintain a separate list when they add new
commands or parameters.&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;juan-m-olle&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;This feature needs:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;To add glance.bash_completion script&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;To add bash_completion command to glance client. This new command
returns all available commands the client has and it is used by
glance.bash_completion.&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 test will check new shell command functionality.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;New feature needs to be mentioned.&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>Sun, 11 Jan 2026 00:00:00 </pubDate></item><item><title>Metadata Definitions Catalog</title><link>http://specs.openstack.org/openstack/glance-specs/specs/juno/metadata-schema-catalog.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/glance/+spec/metadata-schema-catalog"&gt;https://blueprints.launchpad.net/glance/+spec/metadata-schema-catalog&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;A common API hosted by the Glance service for vendors, admins, services, and
users to meaningfully define available key / value pair and tag metadata.
The intent is to enable better metadata collaboration across artifacts,
services, and projects for OpenStack users.&lt;/p&gt;
&lt;p&gt;This is about the definition of the available metadata that can be used on
different types of resources (images, artifacts, volumes, flavors, aggregates,
etc). A definition includes the properties type, its key, it’s description,
and it’s constraints. This catalog will not store the values for specific
instance properties.&lt;/p&gt;
&lt;p&gt;For example, a definition of a virtual CPU topology property for number of
cores will include the key to use, a description, and value constraints like
requiring it to be an integer. So, a user, potentially through Horizon, would
be able to search this catalog to list the available properties they can add to
a flavor or image. They will see the virtual CPU topology property in the list
and know that it must be an integer. In the Horizon example, when the user adds
the property, its key and value will be stored in the service that owns that
resource (Nova for flavors and in Glance for images).&lt;/p&gt;
&lt;p&gt;Diagram: &lt;a class="reference external" href="https://wiki.openstack.org/w/images/b/bb/Glance-Metadata-API.png"&gt;https://wiki.openstack.org/w/images/b/bb/Glance-Metadata-API.png&lt;/a&gt;&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;A challenge we’ve experienced with using OpenStack is discovering, sharing,
and correlating metadata across services and different types of resources. We
believe this affects both end users and administrators.&lt;/p&gt;
&lt;p&gt;Various OpenStack services provide techniques to abstract low level resource
selection to one level higher, such as flavors, volume types, or artifact
types. These resource abstractions often allow “metadata” in terms of tags or
key-value pairs to further specialize and describe instances of each resource
type. However, collaborating and understanding what metadata to use on each
type of resource can be a disconnected and difficult process. This often
involves searching wikis and opening the source code. There is no common way
for vendors or operators to publish their metadata definitions. It becomes more
difficult as a cloud’s scale grows and the number of resources being managed
increases.&lt;/p&gt;
&lt;p&gt;In addition, cloud operators should be able to selectively control the
property metadata that they want to be visible in the CLI or horizon UI.
Just because an enabled driver or scheduler filter supports a certain property
doesn’t mean that the cloud operator wants that property to be readily visible
for selection in the UI.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Background and Examples&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;At the Juno Atlanta summit, the Graffiti team demonstrated the concepts
running under a POC. The following video is a recap of what was demo’d at
the summit and helps to set context:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://www.youtube.com/watch?v=Dhrthnq1bnw"&gt;https://www.youtube.com/watch?v=Dhrthnq1bnw&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We received very positive feedback from members of multiple dev projects
as well as numerous operators.  We were specifically asked multiple times
about getting the metadata definition catalog concepts into Glance so that we
can start to officially support the ideas we demonstrated in Horizon.&lt;/p&gt;
&lt;p&gt;Additional examples are at the end of this document.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Terminology&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The term metadata can become very overloaded and confusing.  This proposed
catalog is about the additional metadata that is passed as either arbitrary
key / value pairs or assigned as “tags” (name only) across various artifacts
and OpenStack services.&lt;/p&gt;
&lt;p&gt;Different APIs may use tags and key / value pairs differently. Tags often
are not used to drive runtime behavior.  However, key / value pairs are
often used by the system to potentially drive runtime behavior, such as
scheduling, quality of service, or driver behavior.  Other times, key / value
pairs are only intended for end user use and are not directly used to drive
runtime behavior. The metadata may also be used by an external entity such
as a 3rd party policy engine. Some service APIs mix the metadata into a single
bucket and don’t differentiate between the two uses of the metadata.&lt;/p&gt;
&lt;p&gt;The terminology for key / value pairs varies across services.&lt;/p&gt;
&lt;p&gt;A few examples of metadata today:&lt;/p&gt;
&lt;table class="docutils align-default"&gt;
&lt;tbody&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Nova&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Cinder&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Glance&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;dl class="simple"&gt;
&lt;dt&gt;Flavor&lt;/dt&gt;&lt;dd&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;extra specs&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/dd&gt;
&lt;dt&gt;Host Aggregate&lt;/dt&gt;&lt;dd&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;metadata&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/dd&gt;
&lt;dt&gt;Instances&lt;/dt&gt;&lt;dd&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;metadata&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;tags&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/td&gt;
&lt;td&gt;&lt;dl class="simple"&gt;
&lt;dt&gt;Volume &amp;amp; Snapshot&lt;/dt&gt;&lt;dd&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;image metadata&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;metadata&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/dd&gt;
&lt;dt&gt;VolumeType&lt;/dt&gt;&lt;dd&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;extra specs&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;qos specs&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/td&gt;
&lt;td&gt;&lt;dl class="simple"&gt;
&lt;dt&gt;Image &amp;amp; Snapshot&lt;/dt&gt;&lt;dd&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;properties&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;tags&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;In this proposal, we use the term “object” to describe a group of 1…* key /
value pairs that may be applied to different kinds of resources for different
purposes.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Relationship to proposed artifacts API&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;This is not about artifact storage, such as Heat templates or various
application packages. This API is about the additional metadata that is beyond
the syntax of the base artifact. Once defined, the metadata can often be
applied to different types of artifacts and resources. For example,
application category tags like “Big Data” may apply to an image or volume that
provides Hadoop or may apply to a Host Aggregate or Flavor that is suitable
for “Big Data” applications.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;We are proposing a new Metadata Definitions Catalog.  The following subsections
detail the concepts managed by the catalog.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Properties (Juno release)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;A property describes a single property and its primitive constraints. Each
property can ONLY be a primitive type:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;string, integer, number, boolean, array&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Each primitive type is described using simple JSON schema notation. This
means NO nested objects and no definition referencing.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Objects (Juno release)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;An object describes a group of one to many properties and their primitive
constraints. Each property in the group can ONLY be a primitive type:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;string, integer, number, boolean, array&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Each primitive type is described using simple JSON schema notation. This
means NO nested objects.&lt;/p&gt;
&lt;p&gt;The object may optionally define required properties under the semantic
understanding that a user who uses the object should provide all required
properties.&lt;/p&gt;
&lt;p&gt;Object derivation with property inheritance was considered, but we will defer
this complexity until it is proven to be necessary.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Namespaces (Juno release)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Metadata definitions are contained in namespaces.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Specify the access controls (CRUD) for everything defined in it. Allows for
admin only, different projects, or the entire cloud to define and use the
definitions in the namespace&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Associates the contained definitions to different types of resources&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Tags (Future release)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;A catalog of possible tags that can be used to help ensure tag name consistency
across users, resource types, and services. So, when a user goes to apply a tag
on a resource, they will be able to either create new tags or choose from tags
that have been used elsewhere in the system on different types of resources.
For example, the same tag could be used for Images, Volumes, and Instances.
Tags are case insensitive (BigData is equivalent to bigdata but is different
from Big-Data).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Tag Hierarchy (Future release)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The notion of hierarchy has come up in various application related
discussions. It is very simple to support hierarchy. For example, tags of
“MySQL” and “Postgres” could be created and set as having a parent of the
“Database” tag. A user could then tag just “MySQL” on something like an image
or software template. Subsequent searches for resources could be performed for
all “Databases” by simply retrieving the list of tags that are children of the
“Database” tag.&lt;/p&gt;
&lt;p&gt;Diagram:&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://wiki.openstack.org/w/images/6/61/Glance-Metadata-Namespace.png"&gt;https://wiki.openstack.org/w/images/6/61/Glance-Metadata-Namespace.png&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;If needed in the future, it may make sense for there to be a default public
namespace visible to all cloud users for all resource types. Having a
default public namespace will make it very easy to manage general metadata
without the overhead of a full multi-tenant environment.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Resource Type Association (Juno release)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Resource type association specifies the relationship between resource
types and the namespaces that are applicable to them. This information can be
used to drive UI and CLI views. For example, the same namespace of
objects, properties, and tags may be used for images, snapshots, volumes, and
flavors. Or a namespace may only apply to images.&lt;/p&gt;
&lt;p&gt;Resource types should be aligned with Heat resource types.
&lt;a class="reference external" href="http://docs.openstack.org/developer/heat/template_guide/openstack.html"&gt;http://docs.openstack.org/developer/heat/template_guide/openstack.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;It is important to note that the same base property key can require different
prefixes depending on the target resource type. Below are a few examples:&lt;/p&gt;
&lt;p&gt;The desired virtual CPU topology can be set on both images and flavors
via metadata. The keys have different prefixes on images than on flavors.
On flavors keys are prefixed with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw:&lt;/span&gt;&lt;/code&gt;, but on images the keys are prefixed
with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hw_&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;For more: &lt;a class="reference external" href="http://git.openstack.org/cgit/openstack/nova-specs/tree/specs/juno/virt-driver-vcpu-topology.rst"&gt;http://git.openstack.org/cgit/openstack/nova-specs/tree/specs/juno/virt-driver-vcpu-topology.rst&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Another example is the AggregateInstanceExtraSpecsFilter and scoped properties
(e.g. properties with something:something=value). For scoped / namespaced
properties, the AggregateInstanceExtraSpecsFilter requires a prefix of
“aggregate_instance_extra_specs:” to be used on flavors but not on the
aggregate itself. Otherwise, the filter will not evaluate the property during
scheduling.&lt;/p&gt;
&lt;p&gt;So, on a host aggregate, you may see:&lt;/p&gt;
&lt;p&gt;companyx:fastio=true&lt;/p&gt;
&lt;p&gt;But then when used on the flavor, the AggregateInstanceExtraSpecsFilter needs:&lt;/p&gt;
&lt;p&gt;aggregate_instance_extra_specs:companyx:fastio=true&lt;/p&gt;
&lt;p&gt;In some cases, there may be multiple different filters that may use
the same property with different prefixes. In this case, the correct prefix
needs to be set based on which filter is enabled.&lt;/p&gt;
&lt;p&gt;This spec handles the above cases.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;This could be done as a completely separate service. However, it was suggested
by numerous community members at the Juno summit that it made sense to be part
of the expanded Glance mission, since many of the primary targets of the
metadata would be artifacts hosted in Glance. In addition, this also allows
the associated UI components to be built out in Horizon natively rather
than as plug-ins.&lt;/p&gt;
&lt;p&gt;We also discussed a Horizon only solution with the Horizon PTL and found some
technical reasons why that wouldn’t make sense:&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Horizon is a stateless server by design at this point. The only place any
persistent data can exist is if you choose to store session information
on the server in a database. The default setup for Horizon now uses
signed cookies to maintain session data and avoids a DB requirement.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;There is no privileged account running on the Horizon server and thus no
way to build a persistent datastore only the admin can obtain. A persistent
privileged session as this creates many security issues.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Horizon can be set up in an HA manner, which would require either duplicate
DB on multiple Horizon servers or another server dedicated to the DB backend
for Horizon.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;Services may always support a way to discover their available metadata. This
API does not prevent that from occurring. However, this does provide a single
central API to publish and discover metadata without every service having to
implement such a facility. In addition, cloud operators should be able to
selectively control the property metadata that they want to be visible in the
CLI or horizon UI. Just because an enabled driver or scheduler filter supports
a certain property doesn’t mean that the cloud operator wants that property to
be readily visible for selection in the UI. This API allows for cloud operators
to have full control over what is made visible.&lt;/p&gt;
&lt;p&gt;A key use case is the collaboration on metadata using a common catalog. This
is complementary to tags and key / value pairs being added ad-hoc across all
services. We think in the future the metadata API could also be backed by
a search indexer across services to include ad-hoc metadata as well as defined
metadata. However, that is not the focus of this blueprint.&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;This will use a relational database and exist in the same database as the
existing Glance relational data, but there is not anticipated impact to
existing Glance data models. This is all new functionality.&lt;/p&gt;
&lt;p&gt;This is about the definition of the available metadata that can be used on
different types of resources (images, artifacts, volumes, flavors, aggregates,
etc). A definition is not just a key and value, so we will not be using a
key / value store database. The definition includes the properties type, its
key, it’s description, and it’s constraints.  When metadata is used on a
resource, a key with user supplied value will be stored on whatever service
owns that resource and is out of the scope of this spec. For example, an
instance of a key / value pair would be in the Cinder database or the
Glance registry.&lt;/p&gt;
&lt;p&gt;Support will be added to:
* glance/db/sqlalchemy/api.py
* registry/api.py
* simple/api.py&lt;/p&gt;
&lt;p&gt;A new package will be added at glance/db/sqlalchemy/metadata_defs_api&lt;/p&gt;
&lt;p&gt;The table classes will be in glance/db/sqlalchemy/models_metadata_defs.py&lt;/p&gt;
&lt;p&gt;The following DB schema is the initial suggested schema. We will improve and
take comments during code review. Constraints not shown for readability.&lt;/p&gt;
&lt;p&gt;Suggested Basic Schema:&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;Table&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;metadef_namespaces&lt;/span&gt;

&lt;span class="o"&gt;+--------------+--------------+------+-----+----------------+&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Field&lt;/span&gt;        &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Type&lt;/span&gt;         &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Null&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Key&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Extra&lt;/span&gt;          &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;+--------------+--------------+------+-----+----------------+&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nb"&gt;id&lt;/span&gt;           &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;      &lt;span class="o"&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;PRI&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;auto_increment&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;namespace&lt;/span&gt;    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;varchar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="o"&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;UNI&lt;/span&gt; &lt;span class="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;display_name&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;varchar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;YES&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt;     &lt;span class="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;description&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;         &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;YES&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt;     &lt;span class="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;visibility&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;varchar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;YES&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt;     &lt;span class="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;protected&lt;/span&gt;    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;tinyint&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="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;YES&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt;     &lt;span class="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;owner&lt;/span&gt;        &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;varchar&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="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;NO&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt;     &lt;span class="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;created_at&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;     &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;NO&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt;     &lt;span class="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;updated_at&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;     &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;YES&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt;     &lt;span class="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;Table&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;metadef_objects&lt;/span&gt;

&lt;span class="o"&gt;+--------------+-------------+------+-----+----------------+&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Field&lt;/span&gt;        &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Type&lt;/span&gt;        &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Null&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Key&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Extra&lt;/span&gt;          &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;+--------------+-------------+------+-----+----------------+&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nb"&gt;id&lt;/span&gt;           &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;     &lt;span class="o"&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;PRI&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;auto_increment&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;namespace_id&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;     &lt;span class="o"&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;MUL&lt;/span&gt; &lt;span class="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;name&lt;/span&gt;         &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;varchar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;NO&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt;     &lt;span class="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;description&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;        &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;YES&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt;     &lt;span class="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;required&lt;/span&gt;     &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;        &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;YES&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt;     &lt;span class="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;json_schema&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;        &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;YES&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt;     &lt;span class="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;created_at&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;NO&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt;     &lt;span class="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;updated_at&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;YES&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt;     &lt;span class="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;Table&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;metadef_properties&lt;/span&gt;

&lt;span class="o"&gt;+--------------+-------------+------+-----+----------------+&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Field&lt;/span&gt;        &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Type&lt;/span&gt;        &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Null&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Key&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Extra&lt;/span&gt;          &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;+--------------+-------------+------+-----+----------------+&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nb"&gt;id&lt;/span&gt;           &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;     &lt;span class="o"&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;PRI&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;auto_increment&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;namespace_id&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;     &lt;span class="o"&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;MUL&lt;/span&gt; &lt;span class="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;name&lt;/span&gt;         &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;varchar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;NO&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt;     &lt;span class="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;json_schema&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;        &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;YES&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt;     &lt;span class="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;created_at&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;NO&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt;     &lt;span class="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;updated_at&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;YES&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt;     &lt;span class="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;Table&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;metadef_resource_types&lt;/span&gt;

&lt;span class="o"&gt;+------------+-------------+------+-----+----------------+&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Field&lt;/span&gt;      &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Type&lt;/span&gt;        &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Null&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Key&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Extra&lt;/span&gt;          &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;+------------+-------------+------+-----+----------------+&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nb"&gt;id&lt;/span&gt;         &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;     &lt;span class="o"&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;PRI&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;auto_increment&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;       &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;varchar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&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;UNI&lt;/span&gt; &lt;span class="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;protected&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;tinyint&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="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;NO&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt;     &lt;span class="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;created_at&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;NO&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt;     &lt;span class="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;updated_at&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;YES&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt;     &lt;span class="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;Table&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;metadef_namespace_resource_types&lt;/span&gt;

&lt;span class="o"&gt;+-------------------+-------------+------+-----+-------+&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Field&lt;/span&gt;             &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Type&lt;/span&gt;        &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Null&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Key&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Extra&lt;/span&gt; &lt;span class="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;resource_type_id&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;     &lt;span class="o"&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;PRI&lt;/span&gt; &lt;span class="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;namespace_id&lt;/span&gt;      &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;     &lt;span class="o"&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;PRI&lt;/span&gt; &lt;span class="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;properties_target&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;varchar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;YES&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt;     &lt;span class="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;prefix&lt;/span&gt;            &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;varchar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;YES&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt;     &lt;span class="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;created_at&lt;/span&gt;        &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;NO&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt;     &lt;span class="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;updated_at&lt;/span&gt;        &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;YES&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt;     &lt;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="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;In the REST API everything is referred by namespace and name rather than
synthetic IDs. This helps to achieve portability (import / export using JSON).&lt;/p&gt;
&lt;p&gt;APIs should allow coarse grain and fine grain access to information in order
to control data transfer bandwidth requirements.&lt;/p&gt;
&lt;p&gt;Working with Namespaces
Basic interaction is:&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Get list of namespaces with overview info based on the desired filters.
(e.g. key / values for images).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Get objects&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;Common Response Codes&lt;/strong&gt;&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Create Success: &lt;cite&gt;201 Created&lt;/cite&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Modify Success: &lt;cite&gt;200 OK&lt;/cite&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Delete Success: &lt;cite&gt;204 No Content&lt;/cite&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Failure: &lt;cite&gt;400 Bad Request&lt;/cite&gt; with details.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Forbidden: &lt;cite&gt;403 Forbidden&lt;/cite&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Not found: &lt;cite&gt;404 Not found&lt;/cite&gt;       e.g. if specific entity not found&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Not found: &lt;cite&gt;405 Not allowed&lt;/cite&gt;     e.g. if trying to delete on a list resource&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Not found: &lt;cite&gt;501 Not Implemented&lt;/cite&gt; e.g. HEAD not implemented&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;API Version&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;All URLS will be under the v2 Glance API.  If it is not explicitly specified
assume /v2/&amp;lt;url&amp;gt;&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Create a namespace:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;POST /metadefs/namespaces/&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;Namespace may optionally contain the following in addition to basic fields.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;resource_type_associations&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;properties&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;objects&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;tags (future release)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Example Body (with no resource types, properties, objects, or tags):&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;"namespace"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"MyNamespace"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;"display_name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"My User Friendly Namespace"&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;"My description"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;"visibility"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"public"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;"protected"&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;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Replace a namespace definition (not including properties, objects, or tags):&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;PUT /metadefs/namespaces/{namespace}&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;List Namespaces: Returns just the list of namespaces without any objects&lt;/dt&gt;&lt;dd&gt;&lt;dl class="simple"&gt;
&lt;dt&gt;properties, or tags.&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;GET /metadefs/namespaces/&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;Example Body:&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;"namespaces"&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;namespace1Here&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;namespace2Here&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="s2"&gt;"first"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"/v2/metadefs/namespaces?limit=2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"next"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"/v2/metadefs/namespaces?marker=namespace2Here&amp;amp;limit=2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"schema"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"/v2/schemas/metadefs/namespaces"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;With&lt;/span&gt; &lt;span class="n"&gt;example&lt;/span&gt; &lt;span class="n"&gt;namespace&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;

&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;"first"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"/v2/metadefs/namespaces?sort_key=created_at&amp;amp;sort_dir=asc"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"namespaces"&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;"namespace"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"OS::Compute::Quota"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"display_name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"Flavor Quota"&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;"Compute drivers may enable quotas on..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"visibility"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"public"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"protected"&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;"owner"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"admin"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"resource_type_associations"&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;"OS::Nova::Flavor"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="s2"&gt;"created_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"2014-08-28T17:13:06Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="s2"&gt;"updated_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"2014-08-28T17:13:06Z"&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="s2"&gt;"created_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"2014-08-28T17:13:06Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"updated_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"2014-08-28T17:13:06Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"self"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"/v2/metadefs/namespaces/OS::Compute::Quota"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"schema"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"/v2/schemas/metadefs/namespace"&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="s2"&gt;"namespace"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"OS::Compute::VirtCPUTopology"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"display_name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"Virtual CPU Topology"&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;"This provides the preferred..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"visibility"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"public"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"protected"&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;"owner"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"admin"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"resource_type_associations"&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;"OS::Glance::Image"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="s2"&gt;"prefix"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"hw_"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="s2"&gt;"created_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"2014-08-28T17:13:06Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="s2"&gt;"updated_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"2014-08-28T17:13:06Z"&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;"OS::Cinder::Volume"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="s2"&gt;"prefix"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"hw_"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="s2"&gt;"properties_target"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"image"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="s2"&gt;"created_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"2014-08-28T17:13:06Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="s2"&gt;"updated_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"2014-08-28T17:13:06Z"&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;"OS::Nova::Flavor"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="s2"&gt;"prefix"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"hw:"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="s2"&gt;"created_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"2014-08-28T17:13:06Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="s2"&gt;"updated_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"2014-08-28T17:13:06Z"&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="s2"&gt;"created_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"2014-08-28T17:13:06Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"updated_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"2014-08-28T17:13:06Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"self"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"/v2/metadefs/namespaces/OS::Compute::VirtCPUTopology"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"schema"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"/v2/schemas/metadefs/namespace"&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="s2"&gt;"schema"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"/v2/schemas/metadefs/namespaces"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Filter by adding query parameters:&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;resource_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;comma&lt;/span&gt; &lt;span class="n"&gt;separated&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="o"&gt;&amp;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;g&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="n"&gt;OS&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Glance&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Image&lt;/span&gt;
&lt;span class="n"&gt;visibility&lt;/span&gt;     &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Valid&lt;/span&gt; &lt;span class="n"&gt;values&lt;/span&gt; &lt;span class="n"&gt;are&lt;/span&gt; &lt;span class="n"&gt;public&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;private&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
                 &lt;span class="n"&gt;Default&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;both&lt;/span&gt; &lt;span class="n"&gt;public&lt;/span&gt; &lt;span class="n"&gt;namespaces&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;private&lt;/span&gt;
                 &lt;span class="n"&gt;namespaces&lt;/span&gt; &lt;span class="n"&gt;visible&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;user&lt;/span&gt; &lt;span class="n"&gt;making&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
&lt;span class="n"&gt;limit&lt;/span&gt;          &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Use&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;specific&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="n"&gt;Expect&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;
                 &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;limited&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;between&lt;/span&gt; &lt;span class="n"&gt;zero&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;limit&lt;/span&gt; &lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
&lt;span class="n"&gt;marker&lt;/span&gt;         &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Specifies&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;namespace&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;last&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;seen&lt;/span&gt; &lt;span class="n"&gt;namespace&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;typical&lt;/span&gt; &lt;span class="n"&gt;pattern&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="n"&gt;limit&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;marker&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;make&lt;/span&gt; &lt;span class="n"&gt;an&lt;/span&gt; &lt;span class="n"&gt;initial&lt;/span&gt;
                 &lt;span class="n"&gt;limited&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;then&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;use&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;last&lt;/span&gt; &lt;span class="n"&gt;namespace&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;response&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;marker&lt;/span&gt; &lt;span class="n"&gt;parameter&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;subsequent&lt;/span&gt; &lt;span class="n"&gt;limited&lt;/span&gt;
                 &lt;span class="n"&gt;request&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;Returns specific namespace including metadata definitions (properties,&lt;/dt&gt;&lt;dd&gt;&lt;dl class="simple"&gt;
&lt;dt&gt;objects or tags).&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;GET /metadefs/namespaces/{namespace}&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;Query parameters:&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;resource_type&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;When&lt;/span&gt; &lt;span class="n"&gt;specified&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;API&lt;/span&gt; &lt;span class="n"&gt;will&lt;/span&gt; &lt;span class="n"&gt;look&lt;/span&gt; &lt;span class="n"&gt;up&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;prefix&lt;/span&gt; &lt;span class="n"&gt;associated&lt;/span&gt;
                 &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;specified&lt;/span&gt; &lt;span class="n"&gt;resource&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;will&lt;/span&gt; &lt;span class="n"&gt;apply&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;prefix&lt;/span&gt;
                 &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="nb"&gt;all&lt;/span&gt; &lt;span class="n"&gt;properties&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;including&lt;/span&gt; &lt;span class="nb"&gt;object&lt;/span&gt; &lt;span class="n"&gt;properties&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;prior&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt;
                 &lt;span class="n"&gt;returning&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;namespace&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="n"&gt;For&lt;/span&gt; &lt;span class="n"&gt;example&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;a&lt;/span&gt;
                 &lt;span class="n"&gt;resource_type_association&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;namespace&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt;
                 &lt;span class="n"&gt;OS&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Nova&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Flavor&lt;/span&gt; &lt;span class="n"&gt;specifies&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;prefix&lt;/span&gt; &lt;span class="n"&gt;of&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;then&lt;/span&gt; &lt;span class="nb"&gt;all&lt;/span&gt;
                 &lt;span class="n"&gt;properties&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;namespace&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;returned&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt;
                 &lt;span class="n"&gt;hw&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;prop_name&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;.&lt;/span&gt; &lt;span class="n"&gt;However&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;OS&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Glance&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Image&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;specified&lt;/span&gt;
                 &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;prefix&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="n"&gt;to&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;then&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="nb"&gt;property&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;returned&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;hw_&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;prop_name&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 Body:&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;"namespace"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"MyNamespace"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"display_name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"My User Friendly Namespace"&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;"My description"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"resource_type_associations"&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;"OS::Nova::Aggregate"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
           &lt;span class="s2"&gt;"created_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"2014-08-28T17:13:06Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
           &lt;span class="s2"&gt;"updated_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"2014-08-28T17:13:06Z"&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;"OS::Nova::Flavor"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
           &lt;span class="s2"&gt;"prefix"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"aggregate_instance_extra_specs:"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
           &lt;span class="s2"&gt;"created_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"2014-08-28T17:13:06Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
           &lt;span class="s2"&gt;"updated_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"2014-08-28T17:13:06Z"&lt;/span&gt;
        &lt;span class="p"&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;"nsprop1"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="s2"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"My namespace property1"&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;"More info here"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"boolean"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"default"&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="p"&gt;},&lt;/span&gt;
    &lt;span class="s2"&gt;"visibility"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"public"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"protected"&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;"owner"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"The Test Owner"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Delete a namespace including all content (properties, objects and tags(future release))&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;DELETE /v2/metadefs/namespaces/{namespace}&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;List resource types associated with a namespace&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;GET /v2/metadefs/namespaces/{namespace}/resource_types&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;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;"resource_type_associations"&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;"OS::Glance::Image"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="s2"&gt;"prefix"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"hw_"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="s2"&gt;"created_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"2014-08-28T17:13:06Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="s2"&gt;"updated_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"2014-08-28T17:13:06Z"&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;"OS::Cinder::Volume"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="s2"&gt;"prefix"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"hw_"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="s2"&gt;"properties_target"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"image_metadata"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="s2"&gt;"created_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"2014-08-28T17:13:06Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="s2"&gt;"updated_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"2014-08-28T17:13:06Z"&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;"OS::Nova::Flavor"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="s2"&gt;"prefix"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"hw:"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="s2"&gt;"created_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"2014-08-28T17:13:06Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="s2"&gt;"updated_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"2014-08-28T17:13:06Z"&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;Field descriptions:&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;name&lt;/span&gt;               &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;required&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Resource&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt; &lt;span class="n"&gt;names&lt;/span&gt; &lt;span class="n"&gt;should&lt;/span&gt; &lt;span class="n"&gt;be&lt;/span&gt; &lt;span class="n"&gt;aligned&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt;
                                &lt;span class="n"&gt;Heat&lt;/span&gt; &lt;span class="n"&gt;resource&lt;/span&gt; &lt;span class="n"&gt;types&lt;/span&gt; &lt;span class="n"&gt;whenever&lt;/span&gt; &lt;span class="n"&gt;possible&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                                &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="n"&gt;docs&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;org&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;developer&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;heat&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;template_guide&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;html&lt;/span&gt;
&lt;span class="n"&gt;prefix&lt;/span&gt;             &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;optional&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Specifies&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;prefix&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;use&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;given&lt;/span&gt;
                                &lt;span class="n"&gt;resource&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="n"&gt;Any&lt;/span&gt; &lt;span class="n"&gt;properties&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;namespace&lt;/span&gt; &lt;span class="n"&gt;should&lt;/span&gt; &lt;span class="n"&gt;be&lt;/span&gt; &lt;span class="n"&gt;prefixed&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;this&lt;/span&gt;
                                &lt;span class="n"&gt;prefix&lt;/span&gt; &lt;span class="n"&gt;when&lt;/span&gt; &lt;span class="n"&gt;being&lt;/span&gt; &lt;span class="n"&gt;applied&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;specified&lt;/span&gt;
                                &lt;span class="n"&gt;resource&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="n"&gt;Must&lt;/span&gt; &lt;span class="n"&gt;include&lt;/span&gt; &lt;span class="n"&gt;prefix&lt;/span&gt; &lt;span class="n"&gt;separator&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;g&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;colon&lt;/span&gt; &lt;span class="p"&gt;:)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
                                &lt;span class="n"&gt;Must&lt;/span&gt; &lt;span class="n"&gt;include&lt;/span&gt; &lt;span class="n"&gt;prefix&lt;/span&gt; &lt;span class="n"&gt;separator&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;g&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;colon&lt;/span&gt; &lt;span class="p"&gt;:)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
&lt;span class="n"&gt;properties_target&lt;/span&gt;  &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;optional&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Some&lt;/span&gt; &lt;span class="n"&gt;resource&lt;/span&gt; &lt;span class="n"&gt;types&lt;/span&gt; &lt;span class="n"&gt;allow&lt;/span&gt; &lt;span class="n"&gt;more&lt;/span&gt; &lt;span class="n"&gt;than&lt;/span&gt; &lt;span class="n"&gt;one&lt;/span&gt;
                                &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="n"&gt;pair&lt;/span&gt; &lt;span class="n"&gt;per&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;For&lt;/span&gt; &lt;span class="n"&gt;example&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                &lt;span class="n"&gt;Cinder&lt;/span&gt; &lt;span class="n"&gt;allows&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;image&lt;/span&gt; &lt;span class="n"&gt;metadata&lt;/span&gt; &lt;span class="n"&gt;on&lt;/span&gt;
                                &lt;span class="n"&gt;volumes&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="n"&gt;Only&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;image&lt;/span&gt; &lt;span class="n"&gt;properties&lt;/span&gt; &lt;span class="n"&gt;metadata&lt;/span&gt;
                                &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;evaluated&lt;/span&gt; &lt;span class="n"&gt;by&lt;/span&gt; &lt;span class="n"&gt;Nova&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;scheduling&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;drivers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
                                &lt;span class="n"&gt;This&lt;/span&gt; &lt;span class="nb"&gt;property&lt;/span&gt; &lt;span class="n"&gt;allows&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;namespace&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt;
                                &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;remove&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;ambiguity&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;Associate Namespace to resource type&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;POST /metadefs/namespaces/{namespace}/resource_types&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;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;"name"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"OS::Cinder::Volume"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;"properties_target"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"image_metadata"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;"prefix"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"hw_"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;"created_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"2014-08-28T17:13:06Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;"updated_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"2014-08-28T17:13:06Z"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;De-associate Namespace from resource type&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;DELETE /metadefs/namespaces/{namespace}/resource_types/{resource_type}&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Get list of all possible resource types&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;GET /metadefs/resource_types&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;&lt;strong&gt;Objects&lt;/strong&gt;&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Add Object in a specific namespace:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;POST /metadefs/namespaces/{namespace}/objects&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;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;POST&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;metadefs&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;namespaces&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;CompanyXNamespace&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;objects&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;"StorageQOS"&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;"Our available storage QOS."&lt;/span&gt;&lt;span class="p"&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="s2"&gt;"minIOPS"&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;"minIOPS"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"integer"&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;"The minimum IOPs required"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="s2"&gt;"default"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="s2"&gt;"minimum"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="s2"&gt;"maximum"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;30000&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="s2"&gt;"burstIOPS"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"integer"&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;"The expected burst IOPs"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="s2"&gt;"default"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="s2"&gt;"minimum"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="s2"&gt;"maximum"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;30000&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;dl class="simple"&gt;
&lt;dt&gt;Replace an object definition in a namespace:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;PUT /metadefs/namespaces/{namespace}/objects/{object_name}&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Delete all objects in specific namespace:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;DELETE /metadefs/namespaces/{namespace}/objects&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Delete specific object in specific namespace:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;DELETE /metadefs/namespaces/{namespace}/objects/{object_name}&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Get a specific object in a namespace:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;GET /metadefs/namespaces/{namespace}/objects/{object_name}&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;List objects in a specific namespace:&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Return all objects including its schema properties&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;GET /metadefs/namespaces/{namespace}/objects&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;Filters by adding query parameters:&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;limit&lt;/span&gt;          &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Use&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;specific&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="n"&gt;Expect&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;
                 &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;limited&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;between&lt;/span&gt; &lt;span class="n"&gt;zero&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;limit&lt;/span&gt; &lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
&lt;span class="n"&gt;marker&lt;/span&gt;         &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Specifies&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;namespace&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;last&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;seen&lt;/span&gt; &lt;span class="n"&gt;namespace&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;typical&lt;/span&gt; &lt;span class="n"&gt;pattern&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="n"&gt;limit&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;marker&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;make&lt;/span&gt; &lt;span class="n"&gt;an&lt;/span&gt; &lt;span class="n"&gt;initial&lt;/span&gt;
                 &lt;span class="n"&gt;limited&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;then&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;use&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;last&lt;/span&gt; &lt;span class="n"&gt;namespace&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;response&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;marker&lt;/span&gt; &lt;span class="n"&gt;parameter&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;subsequent&lt;/span&gt; &lt;span class="n"&gt;limited&lt;/span&gt;
                 &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Example Body:&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;"objects"&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;"object1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="s2"&gt;"namespace"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"my-namespace"&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;"my-description"&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;"prop1"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                  &lt;span class="s2"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"My Property"&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;"More info here"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                  &lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"boolean"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                  &lt;span class="s2"&gt;"default"&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="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;"first"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"/v2/metadefs/objects?limit=1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;"next"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"/v2/metadefs/objects?marker=object1&amp;amp;limit=1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;"schema"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"/v2/schema/metadefs/objects"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Properties (not in an object)&lt;/strong&gt;&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Add Property in a specific namespace:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;POST /metadefs/namespaces/{namespace}/properties&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;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;POST&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;metadefs&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;namespaces&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;OS&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;Hypervisor&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;properties&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;"hypervisor_type"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"array"&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;"The type of hypervisor required"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s2"&gt;"items"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="s2"&gt;"enum"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"hyperv"&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="s2"&gt;"kvm"&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;dl class="simple"&gt;
&lt;dt&gt;Replace a property definition in a namespace:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;PUT /metadefs/namespaces/{namespace}/properties/{property_name}&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Delete all properties in specific namespace:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;DELETE /metadefs/namespaces/{namespace}/properties&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Delete Property in specific namespace:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;DELETE /metadefs/namespaces/{namespace}/properties/{property_name}&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Get a specific property in a namespace:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;GET /metadefs/namespaces/{namespace}/properties/{property_name}&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;List properties in a specific namespace:&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Returns details of all properties in a namespace including property schema:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;GET /metadefs/namespaces/{namespace}/properties&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;Filters by adding query parameters:&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;limit&lt;/span&gt;          &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Use&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;specific&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="n"&gt;Expect&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;
                 &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;limited&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;between&lt;/span&gt; &lt;span class="n"&gt;zero&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;limit&lt;/span&gt; &lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
&lt;span class="n"&gt;marker&lt;/span&gt;         &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Specifies&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;namespace&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;last&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;seen&lt;/span&gt; &lt;span class="n"&gt;namespace&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;typical&lt;/span&gt; &lt;span class="n"&gt;pattern&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="n"&gt;limit&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;marker&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;make&lt;/span&gt; &lt;span class="n"&gt;an&lt;/span&gt; &lt;span class="n"&gt;initial&lt;/span&gt;
                 &lt;span class="n"&gt;limited&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;then&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;use&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;last&lt;/span&gt; &lt;span class="n"&gt;namespace&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;response&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;marker&lt;/span&gt; &lt;span class="n"&gt;parameter&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;subsequent&lt;/span&gt; &lt;span class="n"&gt;limited&lt;/span&gt;
                 &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Namespace membership management (Deferred to Future Release)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Allows different projects to have visibility to a non-public namespace.&lt;/p&gt;
&lt;p&gt;For example, a cloud operator may have special hardware that is capable of
running cloud and weather simulations. Images that have a certain property
on it will get scheduled for that hardware and the operator only wants certain
projects to see that property and hide it from other projects so that the
cloud hardware isn’t misused.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Schema&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;JSON Schema for Namespace:&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;"required"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="s2"&gt;"namespace"&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;"namespace"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"string"&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;"The unique namespace text."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="s2"&gt;"maxLength"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;80&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="p"&gt;{&lt;/span&gt;
          &lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"string"&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;"Provides a user friendly description of the namespace."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="s2"&gt;"maxLength"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="s2"&gt;"display_name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"string"&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;"The user friendly name for the namespace. Used by UI if available."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="s2"&gt;"maxLength"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="s2"&gt;"owner"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"string"&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;"Owner of the namespace."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="s2"&gt;"maxLength"&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="s2"&gt;"visibility"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="s2"&gt;"enum"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
              &lt;span class="s2"&gt;"public"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
              &lt;span class="s2"&gt;"private"&lt;/span&gt;
          &lt;span class="p"&gt;],&lt;/span&gt;
          &lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"string"&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;"Scope of namespace accessibility."&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="s2"&gt;"protected"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"boolean"&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;"If true, namespace will not be deletable."&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="s2"&gt;"created_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"string"&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;"Date and time of namespace creation (READ-ONLY)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="s2"&gt;"format"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"date-time"&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="s2"&gt;"updated_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"string"&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;"Date and time of the last namespace modification (READ-ONLY)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="s2"&gt;"format"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"date-time"&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;"$ref"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"#/definitions/property"&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="s2"&gt;"objects"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="s2"&gt;"items"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
              &lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"object"&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;"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;"$ref"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"#/definitions/property"&lt;/span&gt;
                  &lt;span class="p"&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="s2"&gt;"$ref"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"#/definitions/stringArray"&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="p"&gt;{&lt;/span&gt;
                      &lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"string"&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="p"&gt;{&lt;/span&gt;
                      &lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"string"&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;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"array"&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="s2"&gt;"resource_type_associations"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="s2"&gt;"items"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
              &lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"object"&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;"prefix"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                      &lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"string"&lt;/span&gt;
                  &lt;span class="p"&gt;},&lt;/span&gt;
                  &lt;span class="s2"&gt;"properties_target"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                      &lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"string"&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="p"&gt;{&lt;/span&gt;
                      &lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"string"&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;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"array"&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="s2"&gt;"schema"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"string"&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="s2"&gt;"self"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"string"&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="s2"&gt;"additionalProperties"&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="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;See Schema Definitions below for $ref.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Variations on Namespace schema:&lt;/p&gt;
&lt;p&gt;Namespace can also contain the following:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;resource_type_associations&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;properties&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;objects&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;tags (future release)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;JSON Schema for Resource Types:&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;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"resource_type_associations"&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="p"&gt;{&lt;/span&gt;
          &lt;span class="s2"&gt;"href"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{first}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="s2"&gt;"rel"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"first"&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="s2"&gt;"href"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{next}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="s2"&gt;"rel"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"next"&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="s2"&gt;"href"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{schema}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="s2"&gt;"rel"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"describedby"&lt;/span&gt;
      &lt;span class="p"&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;"schema"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"string"&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="s2"&gt;"next"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"string"&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="s2"&gt;"resource_type_associations"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="s2"&gt;"items"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
              &lt;span class="s2"&gt;"additionalProperties"&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;"required"&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;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"resource_type_association"&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;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                      &lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"string"&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;"Resource type names should be aligned with Heat resource types whenever possible: http://docs.openstack.org/developer/heat/template_guide/openstack.html"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                      &lt;span class="s2"&gt;"maxLength"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;
                  &lt;span class="p"&gt;},&lt;/span&gt;
                  &lt;span class="s2"&gt;"prefix"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                      &lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"string"&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;"Specifies the prefix to use for the given resource type. Any properties in the namespace should be prefixed with this prefix when being applied to the specified resource type. Must include prefix separator (e.g. a colon :)."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                      &lt;span class="s2"&gt;"maxLength"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;
                  &lt;span class="p"&gt;},&lt;/span&gt;
                  &lt;span class="s2"&gt;"properties_target"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                      &lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"string"&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;"Some resource types allow more than one key / value pair per instance.  For example, Cinder allows user and image metadata on volumes. Only the image properties metadata is evaluated by Nova (scheduling or drivers). This property allows a namespace target to remove the ambiguity."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                      &lt;span class="s2"&gt;"maxLength"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;
                  &lt;span class="p"&gt;},&lt;/span&gt;
                  &lt;span class="s2"&gt;"created_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                      &lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"string"&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;"Date and time of resource type association (READ-ONLY)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                      &lt;span class="s2"&gt;"format"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"date-time"&lt;/span&gt;
                  &lt;span class="p"&gt;},&lt;/span&gt;
                  &lt;span class="s2"&gt;"updated_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                      &lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"string"&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;"Date and time of the last resource type association modification (READ-ONLY)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                      &lt;span class="s2"&gt;"format"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"date-time"&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;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"array"&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="s2"&gt;"first"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"string"&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;JSON Schema for Properties&lt;/p&gt;
&lt;p&gt;Namespaces and Objects also contain “properties”.  Properties conform to
JSON schema v4 syntax.  But are limited to the following types:
* string
* integer
* number
* boolean
* array&lt;/p&gt;
&lt;p&gt;Each primitive type is described using simple JSON schema notation. This
means NO nested objects and no definition referencing.
.. note:: See Schema Definitions below for property definition.&lt;/p&gt;
&lt;p&gt;JSON Schema for Objects:&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;"required"&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;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"object"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;"additionalProperties"&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;"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;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"string"&lt;/span&gt;
      &lt;span class="p"&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="s2"&gt;"$ref"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"#/definitions/stringArray"&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;"$ref"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"#/definitions/property"&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="p"&gt;{&lt;/span&gt;
          &lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"string"&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="s2"&gt;"created_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"string"&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;"Date and time of object creation (READ-ONLY)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="s2"&gt;"format"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"date-time"&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="s2"&gt;"updated_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"string"&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;"Date and time of the last object modification (READ-ONLY)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="s2"&gt;"format"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"date-time"&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="s2"&gt;"schema"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"string"&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="s2"&gt;"self"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"string"&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;Objects also contain “properties” as mentioned above.
.. note:: See Schema Definitions below for $ref.&lt;/p&gt;
&lt;p&gt;JSON Schema common definitions:&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;"definitions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="s2"&gt;"property"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="s2"&gt;"additionalProperties"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&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="s2"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                  &lt;span class="s2"&gt;"type"&lt;/span&gt;
              &lt;span class="p"&gt;],&lt;/span&gt;
              &lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"object"&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;"additionalItems"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                      &lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"boolean"&lt;/span&gt;
                  &lt;span class="p"&gt;},&lt;/span&gt;
                  &lt;span class="s2"&gt;"enum"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                      &lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"array"&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="p"&gt;{&lt;/span&gt;
                      &lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"string"&lt;/span&gt;
                  &lt;span class="p"&gt;},&lt;/span&gt;
                  &lt;span class="s2"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                      &lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"string"&lt;/span&gt;
                  &lt;span class="p"&gt;},&lt;/span&gt;
                  &lt;span class="s2"&gt;"default"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt;
                  &lt;span class="s2"&gt;"minLength"&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;"#/definitions/positiveIntegerDefault0"&lt;/span&gt;
                  &lt;span class="p"&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="s2"&gt;"$ref"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"#/definitions/stringArray"&lt;/span&gt;
                  &lt;span class="p"&gt;},&lt;/span&gt;
                  &lt;span class="s2"&gt;"maximum"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                      &lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"number"&lt;/span&gt;
                  &lt;span class="p"&gt;},&lt;/span&gt;
                  &lt;span class="s2"&gt;"minItems"&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;"#/definitions/positiveIntegerDefault0"&lt;/span&gt;
                  &lt;span class="p"&gt;},&lt;/span&gt;
                  &lt;span class="s2"&gt;"readonly"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                      &lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"boolean"&lt;/span&gt;
                  &lt;span class="p"&gt;},&lt;/span&gt;
                  &lt;span class="s2"&gt;"minimum"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                      &lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"number"&lt;/span&gt;
                  &lt;span class="p"&gt;},&lt;/span&gt;
                  &lt;span class="s2"&gt;"maxItems"&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;"#/definitions/positiveInteger"&lt;/span&gt;
                  &lt;span class="p"&gt;},&lt;/span&gt;
                  &lt;span class="s2"&gt;"maxLength"&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;"#/definitions/positiveInteger"&lt;/span&gt;
                  &lt;span class="p"&gt;},&lt;/span&gt;
                  &lt;span class="s2"&gt;"uniqueItems"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                      &lt;span class="s2"&gt;"default"&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;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"boolean"&lt;/span&gt;
                  &lt;span class="p"&gt;},&lt;/span&gt;
                  &lt;span class="s2"&gt;"pattern"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                      &lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                      &lt;span class="s2"&gt;"format"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"regex"&lt;/span&gt;
                  &lt;span class="p"&gt;},&lt;/span&gt;
                  &lt;span class="s2"&gt;"items"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                      &lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"object"&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;"enum"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                              &lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"array"&lt;/span&gt;
                          &lt;span class="p"&gt;},&lt;/span&gt;
                          &lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                              &lt;span class="s2"&gt;"enum"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
                                  &lt;span class="s2"&gt;"array"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                  &lt;span class="s2"&gt;"boolean"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                  &lt;span class="s2"&gt;"integer"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                  &lt;span class="s2"&gt;"number"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                  &lt;span class="s2"&gt;"object"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                  &lt;span class="s2"&gt;"string"&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;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"string"&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;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                      &lt;span class="s2"&gt;"enum"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
                          &lt;span class="s2"&gt;"array"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                          &lt;span class="s2"&gt;"boolean"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                          &lt;span class="s2"&gt;"integer"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                          &lt;span class="s2"&gt;"number"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                          &lt;span class="s2"&gt;"object"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                          &lt;span class="s2"&gt;"string"&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;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"string"&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="p"&gt;{&lt;/span&gt;
                      &lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"string"&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;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"object"&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="s2"&gt;"positiveIntegerDefault0"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="s2"&gt;"allOf"&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;"$ref"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"#/definitions/positiveInteger"&lt;/span&gt;
              &lt;span class="p"&gt;},&lt;/span&gt;
              &lt;span class="p"&gt;{&lt;/span&gt;
                  &lt;span class="s2"&gt;"default"&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="p"&gt;]&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="s2"&gt;"stringArray"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="s2"&gt;"uniqueItems"&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;"items"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
              &lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"string"&lt;/span&gt;
          &lt;span class="p"&gt;},&lt;/span&gt;
          &lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"array"&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="s2"&gt;"positiveInteger"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="s2"&gt;"minimum"&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;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"integer"&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;We intend to expose this via Horizon and are working on related blueprints.&lt;/p&gt;
&lt;p&gt;Update python-glanceclient as needed.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;No changes to existing APIs or code.&lt;/p&gt;
&lt;p&gt;This is expected to be called from Horizon when an admin wants to annotate
tags (future) or key / value pairs onto things likes images and volumes.
This API would be hit for them to get available metadata.&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;DB Schema Creation for new API will now be a newer version&lt;/p&gt;
&lt;p&gt;Default resource types will be hardcoded:
* OS::Glance::Image
* OS::Cinder::Volume
* OS::Nova::Flavor
* OS::Nova::Aggregate
* OS::Nova::Instance&lt;/p&gt;
&lt;p&gt;glance-manage will have new commands for loading, unloading, and exporting
metadata definitions:
* db_load_metadefs - Loads metadata definitions from a specified directory
* db_unload_metadefs - Unloads all metadata definitions in the database
* db_export_metadefs - Exports metadata definitions to s a specified directory&lt;/p&gt;
&lt;p&gt;The python-glanceclient will also support a new set of API and CLI commands
for fine grained management of the metadata definitions in the catalog.&lt;/p&gt;
&lt;p&gt;Default definition files will be checked into glance under etc/metadefs&lt;/p&gt;
&lt;p&gt;Please note, the default definitions are only suggestions based on potential
metadata in a given OpenStack deployment. The configuration of the actual
deployment environment will likely require the cloud operator to limit
what metadata should be made available in this catalog. They may limit it
based on enabled drivers and filters or may choose to only offer a subset
of the options offered by those drivers and filters. Just because an enabled
driver or scheduler filter supports certain properties doesn’t mean that
the cloud operator wants all the properties to be readily visible for selection
in the UI.&lt;/p&gt;
&lt;p&gt;Deployers can customize the definitions to be suitable to their cloud
deployment by deleting namespaces, modifying namespaces, creating new
namespaces, and changing namespace to resource type associations.&lt;/p&gt;
&lt;p&gt;devstack will be modified to call this command to load in all the default
metadata definitions.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None (New API)&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;lakshmi-sampath&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;wayne-okuma
michal-dulko-f
pawel-skowron
pawel-koniszewski
facundo-n-maldonado
santiago-b-baldassin
travis-tripp&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;blockquote&gt;
&lt;div&gt;&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Investigate Pecan / WSME (Pecan ruled out, WSME chosen)&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;Changes would be made to:&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;The database API layer to add support for CRUD operations on namespaces&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The database API layer to add support for CRUD operations on properties&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The database API layer to add support for CRUD operations on objects&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The database API layer to add support for CRUD operations on resource type associations&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The REST API for CRUD operations on the namespaces&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The REST API for CRUD operations on the objects&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The REST API for CRUD operations on the properties&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The REST API for CRUD operations on the resource type associations&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The python-glanceClient to support operations&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;Same dependencies as Glance, except for WSME.&lt;/p&gt;
&lt;p&gt;The implementation will be adding WSME object marshalling.&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 for all possible code with a goal of being able to
isolate functionality as much as possible.&lt;/p&gt;
&lt;p&gt;Tempest tests will be added wherever possible.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Docs needed for new API extension and usage&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://www.youtube.com/watch?v=Dhrthnq1bnw"&gt;Youtube summit recap of Graffiti POC demo.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://www.mail-archive.com/openstack-dev@lists.openstack.org/msg25556.html"&gt;Mailing list thread after Juno summit.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="http://eavesdrop.openstack.org/meetings/glance/2014/glance.2014-05-29-20.00.log.html"&gt;Meeting log where markwash discussed graffiti after summit.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Current glance metadata properties in documentation:&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="http://docs.openstack.org/cli-reference/content/chapter_cli-glance-property.html"&gt;Current documented Glance metadata properties.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Hierarchical tagging concepts were partially inspired by AWS marketplace. In
the marketplace, you can filter by a hierarchy of categories. It made sense to
us that this would be easy to achieve across various kinds of artifacts and
resources through tags (future release).&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://aws.amazon.com/marketplace/help/200901100#step1"&gt;AWS Categories&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Additional Examples&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Libvirt Driver Options&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Images / Snapshots / Volumes (image metadata)&lt;/p&gt;
&lt;p&gt;Today you can provide options to various drivers by putting metadata on
images, snapshots, and volumes.  The drivers read this information and use
them. Currently this is only documented on the wiki.&lt;/p&gt;
&lt;p&gt;Driving it from the metadata catalog using the common format we can expose
them for easy use in the UI or CLI.  This kind of metadata ideally could be
published to the catalog programmatically.  It would be associated with
images, snapshots, and volumes.&lt;/p&gt;
&lt;p&gt;UI Concept:&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://wiki.openstack.org/w/images/f/f7/Libvirtdriveroptions-objects.PNG"&gt;https://wiki.openstack.org/w/images/f/f7/Libvirtdriveroptions-objects.PNG&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Example Data (subset):&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;"objects"&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;"LibVirtDriverOptions"&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_video_model"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
              &lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"array"&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;"The video image driver used."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
              &lt;span class="s2"&gt;"items"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                  &lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                  &lt;span class="s2"&gt;"enum"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
                      &lt;span class="s2"&gt;"vga"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                      &lt;span class="s2"&gt;"cirrus"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                      &lt;span class="s2"&gt;"vmvga"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                      &lt;span class="s2"&gt;"xen"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                      &lt;span class="s2"&gt;"gxl"&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;"hw_machine_type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
              &lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"string"&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;"Enables booting an ARM system using the&lt;/span&gt;
                              &lt;span class="n"&gt;specified&lt;/span&gt; &lt;span class="n"&gt;machine&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="n"&gt;etc&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
          &lt;span class="p"&gt;},&lt;/span&gt;
          &lt;span class="s2"&gt;"hw_rng_model"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
              &lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"string"&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;"Adds a random-number generator device to&lt;/span&gt;
                              &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="s1"&gt;'s instances. etc",&lt;/span&gt;
              &lt;span class="s2"&gt;"defaultValue"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"virtio"&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;&lt;em&gt;Basic Host Aggregate / Flavor pairing of properties&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Today you can ensure that flavors are launched on specific hosts using host
aggregates.  The basic way to do that is to put the same key / value pair on
both the flavor and the host aggregate.  With a metadata catalog, an admin
could easily describe in detail the key / value pairs and their meaning in an
exportable format for use in a single cloud / region or to import for reuse in
another cloud deployment. As a very trivial example, you could use a property
to collaborate on hosts and flavors that provide SSD. A more advanced
object would be one that has different properties for things like min
IOPS, burst IOPS, etc.&lt;/p&gt;
&lt;p&gt;/metadefs/namespace/MyHostGroups/detail&lt;/p&gt;
&lt;p&gt;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="n"&gt;MyHostGroups&lt;/span&gt;          &lt;span class="o"&gt;|&lt;/span&gt;    &lt;span class="o"&gt;+-----------------+&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;Flavor&lt;/span&gt;          &lt;span class="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;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="o"&gt;|&lt;/span&gt;  &lt;span class="o"&gt;+------------------+&lt;/span&gt;  &lt;span class="o"&gt;|&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;Host&lt;/span&gt; &lt;span class="n"&gt;Aggregate&lt;/span&gt;  &lt;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;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;"namespace"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"MyHostGroups"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"My Host Groups"&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;"Different ways that we like to group our private cloud"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;"resource_type_associations"&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;"OS::Nova::Aggregate"&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;"OS::Nova::Flavor"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
         &lt;span class="s2"&gt;"prefix"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"aggregate_instance_extra_specs:"&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="s2"&gt;"objects"&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;"SSD"&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;"MyHostGroups:SSD"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
              &lt;span class="s2"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"SSD"&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;"Describe instances with SSD storage."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
              &lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"boolean"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
              &lt;span class="s2"&gt;"default"&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="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="s2"&gt;"visibility"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"public"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;"protected"&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;"owner"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"The Test Owner"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;em&gt;Sample Namespace with properties and objects&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;/metadefs/namespace/MyNamespace/detail&lt;/p&gt;
&lt;p&gt;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;"namespace"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"MyNamespace"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;"display_name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"My User Friendly Namespace"&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;"My description"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;"resource_type_associations"&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;"OS::Glance::Image"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="s2"&gt;"prefix"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"hw_"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="s2"&gt;"created_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"2014-08-28T17:13:06Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="s2"&gt;"updated_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"2014-08-28T17:13:06Z"&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;"OS::Cinder::Volume"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="s2"&gt;"prefix"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"hw_"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="s2"&gt;"properties_target"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"image_metadata"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="s2"&gt;"created_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"2014-08-28T17:13:06Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="s2"&gt;"updated_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"2014-08-28T17:13:06Z"&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;"OS::Nova::Flavor"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="s2"&gt;"prefix"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"filter1:"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="s2"&gt;"created_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"2014-08-28T17:13:06Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="s2"&gt;"updated_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"2014-08-28T17:13:06Z"&lt;/span&gt;
      &lt;span class="p"&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;"nsprop1"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="s2"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"My namespace property1"&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;"More info here"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"boolean"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="s2"&gt;"default"&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;"nsprop2"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="s2"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"My namespace property2"&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;"More info here"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="s2"&gt;"default"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"value1"&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="s2"&gt;"objects"&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;"object1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="s2"&gt;"namespace"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"MyNamespace"&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;"My object1 description"&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;"prop1"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                  &lt;span class="s2"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"My object1 property1"&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;"More info here"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                  &lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"array"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                  &lt;span class="s2"&gt;"items"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                      &lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"string"&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;span class="s2"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"object2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="s2"&gt;"namespace"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"MyNamespace"&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;"My object2 description"&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;"prop1"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                  &lt;span class="s2"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"My object2 property1"&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;"More info here"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                  &lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"integer"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                  &lt;span class="s2"&gt;"default"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;20&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="s2"&gt;"visibility"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"public"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;"protected"&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;"owner"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"The Test Owner"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
</description><pubDate>Sun, 11 Jan 2026 00:00:00 </pubDate></item><item><title>Provide the ability to temporarily deactivate an image</title><link>http://specs.openstack.org/openstack/glance-specs/specs/kilo/deactivate-image.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/glance/+spec/deactivate-image"&gt;https://blueprints.launchpad.net/glance/+spec/deactivate-image&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This blueprint provides for a method to deactivate an image temporarily
to prevent download of image data (including booting a new instance from
the image). A method for reactivation is also described.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;As the ability for users to import images from outside the cloud becomes
commonly available, a concern is the possibility for a user to import
a malicious or otherwise problematic image (e.g. an image containing a
trojan horse). If an image is deemed suspicious, an admin should be able to
put the image “on hold” preventing instances from being built with it until
it has be properly examined and determined to be safe or found dangerous and
deleted. All image properties will remain accessible and editable, but the
image will not be downloadable by non-admin users.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;To expose this ability, a new image state ‘deactivated’ will be introduced.
In order to transition into and out of this state, two new functional API
calls will be added to the REST interface (detailed below).&lt;/p&gt;
&lt;p&gt;When an image is placed in the deactivated state, image data may not be
downloaded by a non-admin user. This will include all other operations (such
as export and cloning) which may need access to image data. Admins may continue
to download the data to facilitate testing and examination of the image.
Operations which do not access image data (e.g. update, delete, or image-list)
continue to operate as usual for deactivated images.&lt;/p&gt;
&lt;p&gt;Only ‘active’ images may be deactivated. Images in the ‘deactivated’ state
may only transition to ‘active’ or ‘deleted’. Deactivating a ‘deactivated’
image or reactivating an ‘active’ image will succeed as no-ops.&lt;/p&gt;
&lt;p&gt;Restrictions to the deactivate and reactivate functions can be handled through
the current policy mechanisms and thus the responsibility falls to the deployer
to implement / update the applicable policies per their specific requirements.
By default, only administrators will have permissions sufficient to deactivate
and reactivate an image.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;No alternatives seem to be readily available. Policy changes were considered
but this is an action which needs to function on an image-by-image basis
regardless of role (other than admin) and across accounts (in the case of
shared images).&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 design for the deactivate and reactivate calls specified below follows the
controller pattern from Subbu Allamaraju, RESTful Web Services Cookbook
(O’Reilly, 2010), section 2.6. It was discussed by the OpenStack API Working
Group on the mailing list and at a series of meetings in February 2015. The
consensus was that this design is an appropriate pragmatic RESTful interface.&lt;/p&gt;
&lt;p&gt;Using Glance tasks for deactivate/reactivate was discussed by the API WG, but
the consensus was that since Glance tasks are specifically designed for
asynchronous operations, their use was not appropriate here. The recommendation
is that any new asynchronous operations should be implemented in the tasks API,
but the controller pattern is appropriate for synchronous actions like
deactivate and reactivate.&lt;/p&gt;
&lt;p&gt;The API WG concluded that this API design proposal was acceptable at its
meeting on 19 February 2015.&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="http://eavesdrop.openstack.org/meetings/api_wg/2015/api_wg.2015-02-19-00.00.log.html#l-146"&gt;http://eavesdrop.openstack.org/meetings/api_wg/2015/api_wg.2015-02-19-00.00.log.html#l-146&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;POST:/v2/images/{image_id}/actions/deactivate
* Description: Deactivate an image
* Method: POST
* Normal response code(s): 204
* Expected error http response code(s): 403&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;When calling deactivate on an image which is not currently in the
‘active’ or ‘deactivated’ state.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;URL for the resource: /v2/images/{image_id}/actions/deactivate&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Parameters which can be passed via the url
{image_id}, String, The ID for the image.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;POST:/v2/images/{image_id}/actions/reactivate
* Description: Reactivate an image
* Method: POST
* Normal response code(s): 204
* Expected error http response code(s): 403&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;When calling reactivate on an image which is not currently
in the ‘deactivated’ or ‘active’ state.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;URL for the resource: /v2/images/{image_id}/actions/reactivate&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Parameters which can be passed via the url
{image_id}, String, The ID for the image.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET:/v2/images/{image_id}/file
* Description: Downloads binary image data.
* Method: GET
* Normal response code(s): 200, 204
* Expected error http response code(s): 403&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;When attempting to download a deactivated image&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;URL for the resource: /v2/images/{image_id}/file&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Parameters which can be passed via the url
{image_id}, String, The ID for the image.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET:/v2/images/{image_id}
* Description: Retrieve the image metadata
* Method: GET
* Normal response code(s): 200&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Retrieving image metadata for a deactivated image will continue
to function normally&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Expected error http response code(s): None&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;URL for the resource: /v2/images/{image_id}&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Parameters which can be passed via the url
{image_id}, String, The ID for the image.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET:/v1/images/{image_id}
* Description: Returns the image details as headers and the image binary in the body of the response.
* Method: GET
* Normal response code(s): 200
* Expected error http response code(s): 403&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;When attempting to download a deactivated image&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;URL for the resource: /v1/images/{image_id}&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Parameters which can be passed via the url
{image_id}, String, The ID for the image.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;HEAD:/v1/images/{image_id}
* Description: Retrieve the image metadata
* Method: HEAD
* Normal response code(s): 204&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Retrieving image metadata for a deactivated image will continue
to function normally&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Expected error http response code(s): None&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;URL for the resource: /v1/images/{image_id}&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Parameters which can be passed via the url
{image_id}, String, The ID for the image.&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;This change enhances security of the overall system by giving administrators
the ability to suspend usage of potentially malicious images while they are
being audited.&lt;/p&gt;
&lt;p&gt;There are no negative security impacts.&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;Support for the new API operations should be added to python-glanceclient.&lt;/p&gt;
&lt;p&gt;End users will be unable to perform any operations on a deactivated image which
requires access to the image data. This would include downloading, booting, and
exporting the image.&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 to restrict access to these operations, deployers will need to
configure the ‘deactivate’ and ‘reactivate’ policies 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&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;eddie-sheffield&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="reviewers"&gt;
&lt;h3&gt;Reviewers&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Core reviewer(s):&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;nikhil-komawar&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other reviewer(s):&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;hemanth-makkapati&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 allowed state transistions&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add image actions controller to v2 api&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add ‘deactivate’ action to controller and router&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add ‘activate’ action to controller and router&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add policy checks for ‘deactivate’ and ‘reactivate’&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add check for deactivated image on download to v2 api&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add check for deactivated image on download to v1 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;Tempest tests for the new operations and verifying download restrictions on
deactivated images need to be added.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Documentation is required for:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;The new API functions&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The new policies (as described in Other Deployer Impact)&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;Earlier version of this spec from the wiki:
* &lt;a class="reference external" href="https://wiki.openstack.org/wiki/Glance-deactivate-image"&gt;https://wiki.openstack.org/wiki/Glance-deactivate-image&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Discussions concerning the “Function API” approach used here:
* &lt;a class="reference external" href="https://etherpad.openstack.org/p/glance-adding-functional-operations-to-api"&gt;https://etherpad.openstack.org/p/glance-adding-functional-operations-to-api&lt;/a&gt;
* &lt;a class="reference external" href="http://lists.openstack.org/pipermail/openstack-dev/2014-May/036416.html"&gt;http://lists.openstack.org/pipermail/openstack-dev/2014-May/036416.html&lt;/a&gt;
* &lt;a class="reference external" href="http://osdir.com/ml/openstack-dev/2015-02/msg01563.html"&gt;http://osdir.com/ml/openstack-dev/2015-02/msg01563.html&lt;/a&gt;
* “RESTful Web Services Cookbook, Section 2.6” - &lt;a class="reference external" href="http://it-ebooks.info/book/392/"&gt;http://it-ebooks.info/book/392/&lt;/a&gt;&lt;/p&gt;
&lt;/section&gt;
</description><pubDate>Sun, 11 Jan 2026 00:00:00 </pubDate></item><item><title>Software Metadata Definitions</title><link>http://specs.openstack.org/openstack/glance-specs/specs/kilo/software-metadefs.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/glance/+spec/software-metadefs"&gt;https://blueprints.launchpad.net/glance/+spec/software-metadefs&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The spec will provide a base library of metadata definitions for various
common software products, components, and libraries that may exist on
particular image (or volume or instance). These metadata definitions will
make it easier for end users and admins to easily describe the software and
its properties. This information will enable an improved and faster user
experience for applying software metadata, searching based on software
metadata, and viewing the software information about an image.&lt;/p&gt;
&lt;p&gt;Various improvements in horizon are underway to take advantage of this
metadata. For example, a user launching an instance will be able to expand
the image row to see addition information about the image.  This will include
providing the metadata definition for properties on the image.  This same
information will also be visible from the image and instance details page.&lt;/p&gt;
&lt;p&gt;The following blueprint is for launch instance:&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/horizon/+spec/launch-instance-redesign"&gt;https://blueprints.launchpad.net/horizon/+spec/launch-instance-redesign&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The following screenshot mockup provides an example from the instance details:&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://wiki.openstack.org/w/images/3/37/Instance-details-mock-january-2015.png"&gt;https://wiki.openstack.org/w/images/3/37/Instance-details-mock-january-2015.png&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The following blueprint is for instance details (see source tab):&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/horizon/+spec/instance-details-redesign"&gt;https://blueprints.launchpad.net/horizon/+spec/instance-details-redesign&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Additional horizon blueprints are being prepared that will display metadata,
but are still undergoing collaborative UX design first.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;In Juno, the metadata definitions catalog was introduced with a primary
intent to improve collaboration on the metadata that can be applied to
different resources such as images, flavors, host aggregates,
and volumes. The primary development focus in Juno was on what is currently
system metadata in OpenStack (properties that affect scheduling and driver
behavior).&lt;/p&gt;
&lt;p&gt;The metadata fields on these same resources can also be used to provide
additional, rich information that describes the resource for user
understanding and search. This information can be leveraged to improve
instance launching, application catalogs, and a variety of other user
interaction points.&lt;/p&gt;
&lt;p&gt;Current methodologies present and proposed in OpenStack require repetitive
descriptions, categorization, imagery, and attributes to be applied on each
instance of a resource.&lt;/p&gt;
&lt;p&gt;For example, if multiple images contain Apache then each image will require
the user to type in information about Apache, will require them to provide
some sort of categorization tag, and will not have any common “template” like
fields for the software which can be used for faceted search.&lt;/p&gt;
&lt;p&gt;This leads to redundancy, spelling mistakes, inconsistency as well as a
general lack of ability to present a rich UI experience. In addition,
there is no common set of base definitions for software that can be shared
across deployments.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;The implementation of this spec will provide a base library of metadata
definitions for various common software products, components,
and libraries that may exist on particular image (or volume or instance).&lt;/p&gt;
&lt;p&gt;The following are examples of the type of commonly used software that will
be included:
* Databases such as MySQL, PostgreSQL, Oracle, MongoDB, etc.
* Web servers such as Apache, nginx, IIS
* Runtimes like php, java, python, etc.&lt;/p&gt;
&lt;p&gt;The review process of the actual proposed definitions will allow for the
community to suggest additional software to include or to suggest removing
certain definitions.&lt;/p&gt;
&lt;p&gt;These metadata definitions will make it easier for end users and admins to
easily describe the software and its properties. This information will
enable an improved and faster user experience for applying software
metadata, searching based on software metadata, and viewing the software
information about an image.&lt;/p&gt;
&lt;p&gt;Users of the glance client / cli will be able to lookup the available
definitions just like they do today. So the below methodology that can be
done to look up something like virtual CPU topology properties will work for
the software definitions:&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;glance&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;image&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="n"&gt;version&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="n"&gt;md&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;namespace&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nb"&gt;list&lt;/span&gt;

&lt;span class="n"&gt;glance&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;image&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="n"&gt;version&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="n"&gt;md&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;namespace&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;show&lt;/span&gt; &lt;span class="n"&gt;OS&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;VirtCPUTopology&lt;/span&gt;

&lt;span class="n"&gt;glance&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;image&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="n"&gt;version&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="n"&gt;md&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nb"&gt;property&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;show&lt;/span&gt; &lt;span class="n"&gt;OS&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;VirtCPUTopology&lt;/span&gt; &lt;span class="n"&gt;cpu_maxsockets&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The metadata definitions will be included as additional json files in the
etc/metadefs directory just like the existing example system metadata
definitions.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;As every single image, artifact, or other type of resource is added to the
system, the admin and users could be responsible for putting a good description
that is consistent with other descriptions, could try to remember all the
right tags to add, or could try to remember all the same properties to
upload to it. This leads to redundancy, spelling mistakes,
inconsistency as well as a general lack of ability to present a rich UI
experience. It also doesn’t enable predictable search facets for rich search
experience.&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;No impacts glance client.&lt;/p&gt;
&lt;p&gt;Work is being done in horizon to take better advantage of these definitions.&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;This spec will provide deployers with a base set of metadata definitions for
software similar to what they are provided for system metadata definitions.
They can choose to either use or not use the base definitions provided in this
spec.&lt;/p&gt;
&lt;p&gt;In Juno, example software definitions were not provided.  To upgrade,
they will need to deploy these files to etc/glance/metadefs and then call
glance-manage db_load_metadefs. This call automatically loads new namespaces
that aren’t already loaded.&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;travis-tripp&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;lakshmi-sampath
murali-sundar&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="reviewers"&gt;
&lt;h3&gt;Reviewers&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Core reviewer(s):&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;nikhil-komawar
&amp;lt;launchpad-id or None&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other reviewer(s):&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;wayne-okuma
murali-sundar&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;dl class="simple"&gt;
&lt;dt&gt;Provide definition files for different categories of software.&lt;/dt&gt;&lt;dd&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Databases&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Web servers&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Runtime environments&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;More&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/dd&gt;
&lt;/dl&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 code ensures that metadata definitions are loaded properly.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Possibly update docs to talk about the base software definitions provided.&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://docs.openstack.org/developer/glance/metadefs-concepts.html"&gt;http://docs.openstack.org/developer/glance/metadefs-concepts.html&lt;/a&gt;&lt;/p&gt;
&lt;/section&gt;
</description><pubDate>Sun, 11 Jan 2026 00:00:00 </pubDate></item><item><title>Glance Image Signing and Verification</title><link>http://specs.openstack.org/openstack/glance-specs/specs/mitaka/implemented/image-signing-and-verification-support.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/glance/+spec/image-signing-and-verification-support"&gt;https://blueprints.launchpad.net/glance/+spec/image-signing-and-verification-support&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Before Liberty, OpenStack did not support the following feature:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Signature validation of uploaded signed images&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Deploying authentication protects image integrity by verifying that an
image has not been modified after the upload by the user.  This feature
improves the enterprise-ready posture of OpenStack.&lt;/p&gt;
&lt;p&gt;Although an initial implementation was merged into Glance for the Liberty
release, adding functionality for this feature to Nova requires modifications
to this implementation [1].&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Before Liberty, there was no method for users to verify that a previously
uploaded image had not been modified.  An image could potentially be modified
in transit (such as when it is uploaded to Glance or transferred to Nova) or
Glance itself could be untrusted and modify images without a user’s knowledge.
An image that is modified could include malicious code.  Providing support for
image signatures and signature verification would allow the user to verify
that an image has not been modified prior to booting the image.&lt;/p&gt;
&lt;p&gt;There are several use cases that this feature supports:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;An image is signed by an End User, using the user’s private key.  The user
then uploads the image to Glance, along with the signature created and a
reference to the user’s public key certificate.  Glance uses this
information to verify that the signature is valid, and notifies the user
if the signature is invalid.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;An image is created in Nova, and Nova signs the image at the request of the
End User.  When the image is uploaded to Glance, the signature and public
key certificate reference are also provided.  Glance verifies the signature
before storing the image, and notifies Nova if the signature verification
fails.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A signed image is requested by Nova, and Glance provides the signature and
a reference to the public key certificate to Nova along with the image so
that Nova can verify the signature before booting the image.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;For the initial implementation in Liberty, this change used the property
feature of Glance to store the metadata items needed for image signing and
verification. These include a public key certificate reference, and the
signature.  These are provided when the image is created, and are accessible
when the image is uploaded.  Note that the feature only supports image uploads
with the Glance API v2 (and does not support using the Glance API v1).  Also
note that multiple formats for the key (such as SubjectPublicKeyInfo) and for
the signature (such as PSS) are supported.  The format of the signature is
stored as one of the properties.&lt;/p&gt;
&lt;p&gt;The certificate reference is used to access the certificate from a key
manager, where the certificate is stored.  This certificate is added to
the key manager by the end user before uploading the image.  Note that the
signature is done offline.&lt;/p&gt;
&lt;p&gt;Glance supports computing a checksum of an image when an image is uploaded,
and this checksum is stored with the image.  In the Liberty implementation,
this same hash (which is hardcoded to be MD5) was used for the signature
verification.   The checksum hash is computed in glance_store (when the image
data is uploaded), and is then used to verify the signature in Liberty.  The
Glance frontend uses the reference to the public key certificate to retrieve
the certificate from the key manager, and then uses this public key along with
the signature, the computed checksum, and the rest of the signature metadata
to verify the signature.  If the signature verification fails, the image is
transition to a killed state, and the user is notified that the upload failed
and given a reason why.&lt;/p&gt;
&lt;p&gt;However, in Mitaka, this approach will be modified to instead validate a
signature of the image data, rather than validating an image signature of a
hash of the image data.  To explain this further, consider the following two
options using ‘RSA-PSS’ as the signature type, and ‘SHA-256’ as the signature
hash method:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;A signature of the Glance checksum of the image data (hardcoded to MD5)&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;signature = RSA-PSS(SHA-256(MD5(IMAGE-CONTENT)))&lt;/p&gt;
&lt;ol class="arabic simple" start="2"&gt;
&lt;li&gt;&lt;p&gt;A signature of the image data directly&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;signature = RSA-PSS(SHA-256(IMAGE-CONTENT))&lt;/p&gt;
&lt;p&gt;The first approach (‘sign-the-hash’) was implemented in Liberty, but the
second approach (‘sign-the-data’) will be used instead in Mitaka.  Although
the sign-the-hash approach will still be supported in Mitaka, it will be
deprecated, and removed in a later release.  Note that, as seen above, the
‘sign-the-data’ approach still involves creating a hash of the image. However,
this is done as part of the signature verification process, and is internal to
the signature verifier.  This is in contrast to the ‘sign-the-hash’ approach,
where the verifier does a hash of the hash of the image data as part of the
verification process.&lt;/p&gt;
&lt;p&gt;To support the ‘sign-the-data’ approach, a few modifications will have to be
made. Currently, the ‘checksum’ is computed in each of the
glance_store/_drivers/*.py ‘add’ methods.  When ‘checksum.update()’ is called
for the image data chunk, this data chunk will also be passed to a
signature_utils module (through an optional callback method), provided that
the necessary signature properties are present.  These data chunks will then
be used to update the signature verifier, and when the image data is done
being read the verifier will be finalized and the verification will occur.  As
in Liberty, if the signature verification fails, the image is transition to a
killed state, and the user is notified that the upload failed and given a
reason why.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;An alternative to replacing the sign-the-hash approach with the sign-the-data
approach would be to leave the Liberty implementation as-is.  However, there
has been pushback from the Nova community with this approach [2], since it
requires initially using MD5 (which is not cryptographically secure) as the
basis, and then querying Glance for the hash method used, assuming the hash
was made configurable. In the interest of using an implementation that is
accepted by both Glance and Nova, as well as removing any attachment to MD5,
it is necessary to modify the initial approach.&lt;/p&gt;
&lt;p&gt;An alternative to the sign-the-data approach is to create a
separate configurable hash for use with verifying/creating the signature.
However, creating a separate hash is no different performance-wise to signing
the image data directly, since part of the signature verification process is
computing a hash of the image for use with verification.  Also, the use of
this separate hash, though stronger than MD5, would be limited, since having
a signature makes the need for a hash obsolete.&lt;/p&gt;
&lt;p&gt;An alternative to storing a reference to the public key certificate in Glance
would be to store the actual public key certificate in Glance.  However, this
approach would be insecure, since Glance, unlike a dedicated key manager, has
not been created with storing keys or certificates in mind.&lt;/p&gt;
&lt;p&gt;An alternative to using asymmetric keys for integrity and confidentiality is
to use symmetric keys.  However, in order for Glance to be able to verify the
image, it would need to have access to the key used to create the signature.
This access would enable Glance to modify the image and create a new signature
without the user’s knowledge.  Using asymmetric keys enables Glance to verify
the signature without giving Glance the power to modify the image and
signature.&lt;/p&gt;
&lt;p&gt;An alternative to using the Glance properties to store and retrieve the
signature metadata would be to create an API extension that support
signatures. Then, instead of the user setting the metadata using the property
key value pairs, the API extension would be used. Currently, if a user were to
use the metadata keys (for the certificate and signature) for other purposes,
the image uploads would fail.  Another item of note is that an API extension
would allow for the management of multiple signatures per image in a clean
manner, which is not possible with the properties approach. However, the
Images API does not support extensions, so this is not a valid approach.&lt;/p&gt;
&lt;p&gt;Another alternative to using the Glance properties to store and retrieve the
signature metadata would be to use the CMS (cryptographic message syntax)
format as defined in RFC 5652 Section 5.  However, the size for this would be
variable, and could not use the existing Glance properties, which would
require API modifications.  For the initial implementation, Glance properties
will be used, with the plan to migrate to using CMS in a future implementation
as the need for increased flexibility arises.&lt;/p&gt;
&lt;p&gt;An alternative to requiring the user to provide the signature separate from
the image is to support images that already have an embedded signature.
Although this could be included as a future improvement, the initial
implementation will not provide embedded signature support, since it is
advantageous to keep the initial effort focused and small.&lt;/p&gt;
&lt;p&gt;An alternative to focusing on a single-cloud implementation would be to
include support for multi-clouds in the initial implementation.  If images are
exchanged between different clouds, signature verification could be used to
confirm that images have not be modified.  However, in the interest of a more
simplistic initial implementation, explicit support for multi-clouds will be
saved for future iterations.&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 API changes will be needed for the initial implementation, provided that
other services are able to retrieve all of the properties of a given image.&lt;/p&gt;
&lt;p&gt;Note that the existing API allows for providing the signature metadata as
Glance properties, and returning an error message if verification fails.&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 improves the enterprise-ready posture of OpenStack by enabling
signature signing and verification.&lt;/p&gt;
&lt;p&gt;Although keys are used in this change, the keys themselves are assumed to be
stored in a key manager, and only a reference to the certificate is stored in
Glance.&lt;/p&gt;
&lt;p&gt;This change involves hashing the image data for use in verifying and creating
signatures for the image.&lt;/p&gt;
&lt;p&gt;Note that the signature length is currently limited to 255 bytes, since this
is the maximum size supported for Glance properties.  In turn, this limits
the size of the keys that can be used for signature creation.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;This change will involve adding log messages to indicate the success or
failure of signature verification and creation.&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 user will be required to provide the appropriate information needed for
the signing and verification in order to use this feature.&lt;/p&gt;
&lt;p&gt;There are no changes that need to be made to python-glanceclient.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;The feature will only be used if a user has provided the appropriate
properties during the image upload.  Otherwise, no signature verification or
creation will occur.&lt;/p&gt;
&lt;p&gt;When signature verification and creation do occur, there will be some latency
associated with retrieving the certificate from the key manager.  Also, as a
part of the signature verification or creation, a hash of the image data
is computed by the ‘verifier’ or ‘signer’ which will have a small impact
on 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;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;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;brianna-poulos&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;dane-fichter&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="reviewers"&gt;
&lt;h3&gt;Reviewers&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Core reviewer(s):&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;flaper87
nikhil_k&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other reviewer(s):&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;joel-coffman&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 feature will be tackled in the following stages:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Add signature verification on upload to verify a signature of
the image data directly, rather than a signature of the MD5 hash of the
image data, when the new signature metadata property names are present.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add a log entry to mark the sign-the-hash verification path as deprecated
in Mitaka, when the old signature metadata property names are present.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Remove the sign-the-hash verification steps in the release after Mitaka.&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;In order to take advantage of the signatures in Glance, Nova will need to
be updated to retrieve the signatures from Glance and verify them.  However,
Glance does not depend on Nova to have this support in order to have the
feature added.  The spec for this in Nova [2] has been approved.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Before Nova support for this feature is added, unit tests will be sufficient.
Once Nova support is added, Tempest tests should ensure that the interaction
between Nova and Glance works 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;Instructions for how to use the change will need to be documented.  These
include instructions for the user on how to create keys and signatures
offline before providing this information during the creation of an image.&lt;/p&gt;
&lt;p&gt;This documentation will also include descriptions for each of the following
signature metadata properties (note that “img_” has been included at Nova’s
request):&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;img_signature: the signature of the “checksum hash” encoded in base64 format&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;img_signature_hash_method: the hash method used to create the signature&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;img_signature_key_type: the key type used in creating the signature&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;valid values are: “RSA-PSS”&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;img_signature_certificate_uuid: the uuid used to retrieve the certificate
from castellan&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;cryptography: &lt;a class="reference external" href="https://cryptography.io/en/latest/"&gt;https://cryptography.io/en/latest/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;[1] &lt;a class="reference external" href="http://bit.ly/1Q0M0C7"&gt;http://bit.ly/1Q0M0C7&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;[2] &lt;a class="reference external" href="https://review.openstack.org/#/c/188874/"&gt;https://review.openstack.org/#/c/188874/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;[3] &lt;a class="reference external" href="http://git.openstack.org/cgit/openstack/castellan"&gt;http://git.openstack.org/cgit/openstack/castellan&lt;/a&gt;&lt;/p&gt;
&lt;/section&gt;
</description><pubDate>Sun, 11 Jan 2026 00:00:00 </pubDate></item><item><title>Deprecate Glance Registry</title><link>http://specs.openstack.org/openstack/glance-specs/specs/newton/approved/glance/deprecate-registry.html</link><description>

&lt;p&gt;Launchpad blueprint:&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/glance/+spec/deprecate-registry"&gt;https://blueprints.launchpad.net/glance/+spec/deprecate-registry&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Glance registry has, historically, helped to scale Glance by allowing for
centralizing the database access (glance-registry) while distributing the data
access (glance-api). In addition, it’s helped as a safe-guard for the database
access credentials as it shouldn’t be deployed as a public endpoint.&lt;/p&gt;
&lt;p&gt;With the release and support of Glance’s V2, the Glance Registry service has
become redundant, hence this proposal to deprecate it.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Glance Registry serves a very specific use case, which is to serve as a proxy
for the database operations in a Glance deployment. This use case came as part
of older Glance API versions and a certainly older architecture.&lt;/p&gt;
&lt;p&gt;Unfortunately, it’s becoming more of a burden to maintain it - development,
operations and documentation wise - than a benefit for the project itself.&lt;/p&gt;
&lt;p&gt;From a development perspective, the team has to maintain the API updated for
every change in the database API. From an operational perspective, there’s
another set of API nodes that need to be deployed, monitored, and upgraded. From
a documentation stand point, the team needs to make sure the service docs are
up-to-date, the best practices are spelled out and configuration files updated.&lt;/p&gt;
&lt;p&gt;The benefits of this service have been discussed in a recent thread &lt;a class="footnote-reference brackets" href="#id3" 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; on both
developers and operators, mailing lists. The output of this thread is not really
conclusive, although it suggests there’s no real use case for this service
anymore and that OPs would be better off by not having it.&lt;/p&gt;
&lt;p&gt;Rolling upgrades was brought as a possible blocker for this deprecation. As it’s
been explained in the thread &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;, upgrading Glance (or even the planned work on
rolling upgrades) should not depend on the presence of this service. Anything
needed from Glance Registry should be possible to obtain from Glance API itself.&lt;/p&gt;
&lt;p&gt;Glance Glare is not going to use Glance registry, which would also leave us with
an inconsistent deployment and a bad user experience.&lt;/p&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 deprecate the glance-registry service. Mark the service as
deprecated and ready for removal in the Q release.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Keep maintaining the Glance Registry service.&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 public facing API won’t be changed. The registry API will be deprecated and
not required anymore.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;Deployers will have to put the database credentials in the glance-api config
files. This might be seen as a security issue for some deployments as this means
an attacker that gains access to the glance-api server could potentially access
glance’s database. However, this is not any different than what other services.&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 should actually improve the overall performance as it’d get rid of
an extra step glance-api needs to go through to access the image metadata.&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;Glance deployments will eventually have to move away from using the registry.
This can’t be done for glance-api nodes using v1 but it can certainly be done
for v2-only nodes.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;Less code to maintain, happier developers.&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;flaper87&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="reviewers"&gt;
&lt;h3&gt;Reviewers&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Core reviewer(s):&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;rosmaita
jokke
nikhil&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other reviewer(s):&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;&amp;lt;launchpad-id or None&amp;gt;
&amp;lt;launchpad-id or None&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 glance-api only job&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Mark the registry service as deprecated&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://review.openstack.org/#/c/315190/"&gt;https://review.openstack.org/#/c/315190/&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;Test a registry-less deployment in the OpenStack CI.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Document the motivations behind this deprecation and a recommended upgrade path
from Mitaka to Newton and on.&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;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="http://lists.openstack.org/pipermail/openstack-dev/2016-May/094773.html"&gt;http://lists.openstack.org/pipermail/openstack-dev/2016-May/094773.html&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;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://lists.openstack.org/pipermail/openstack-dev/2016-May/095144.html"&gt;http://lists.openstack.org/pipermail/openstack-dev/2016-May/095144.html&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;/aside&gt;
&lt;/section&gt;
</description><pubDate>Sun, 11 Jan 2026 00:00:00 </pubDate></item><item><title>Spec Lite: Introduce db sync check feature</title><link>http://specs.openstack.org/openstack/glance-specs/specs/queens/implemented/glance/lite-spec-db-sync-check.html</link><description>

&lt;dl class="field-list simple"&gt;
&lt;dt class="field-odd"&gt;problem&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;It is very hard for automation of deploy and upgrade operations to
know if there are db migrations pending. It requires the automation
to know what the latest version is, and compare that to the output
of a command to check the current version, then interpret the
potential difference somehow.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;solution&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;Similar to the linked feature added to Keystone’s manage command,
Glance should support an operation which enumerates any outstanding
db upgrade operations and provide user friendly message based on
that status. Each expand, migrate, and contract operation required
to upgrade the db should be listed in the proper order of execution
in the response.
This may be implemented by using a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance-manage&lt;/span&gt; &lt;span class="pre"&gt;db&lt;/span&gt; &lt;span class="pre"&gt;check&lt;/span&gt;&lt;/code&gt; option.
When this option is present no db upgrades would be performed
but potential operations would be reported, acting similar to the
pattern of a dry-run.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;impacts&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;Introduces new option to the db sync operation in glance-manage.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;timeline&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;Queens RC-1&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;link&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;&lt;a class="reference external" href="https://bugs.launchpad.net/keystone/+bug/1642212"&gt;https://bugs.launchpad.net/keystone/+bug/1642212&lt;/a&gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;reviewers&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;rosmaita, abhishekk, jokke&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;assignee&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;bhagyashris&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
</description><pubDate>Sun, 11 Jan 2026 00:00:00 </pubDate></item><item><title>Image Import Refactor</title><link>http://specs.openstack.org/openstack/glance-specs/specs/rocky/approved/glance/image-import/image-import-refactor.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/glance/+spec/image-import-refactor"&gt;https://blueprints.launchpad.net/glance/+spec/image-import-refactor&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 is a very long spec, so we’ve added a &lt;a class="reference internal" href="#faq"&gt;&lt;span class="std std-ref"&gt;FAQ&lt;/span&gt;&lt;/a&gt; to cover some
common questions so that people can make better informed comments on
the implementation patches.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;In this spec we propose a refactoring of the current Glance image import
process to meet the criteria of being discoverable, interoperable, and
flexible.  The goal is to present a uniform interface for image import that
will satisfy the requirements of public and private clouds of various sizes.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This spec is based on ideas expressed in mailing list
discussions (see &lt;a class="reference internal" href="#osm1" id="id1"&gt;&lt;span&gt;[OSM1]&lt;/span&gt;&lt;/a&gt;, &lt;a class="reference internal" href="#osm2" id="id2"&gt;&lt;span&gt;[OSM2]&lt;/span&gt;&lt;/a&gt;), a meeting in
#openstack-glance (see &lt;a class="reference internal" href="#osl1" id="id3"&gt;&lt;span&gt;[OSL1]&lt;/span&gt;&lt;/a&gt;, &lt;a class="reference internal" href="#ose2" id="id4"&gt;&lt;span&gt;[OSE2]&lt;/span&gt;&lt;/a&gt;), a video
meeting of interested people (summarized in &lt;a class="reference internal" href="#osw3" id="id5"&gt;&lt;span&gt;[OSW3]&lt;/span&gt;&lt;/a&gt;), and
a session at the Mitaka design summit &lt;a class="reference internal" href="#ose3" id="id6"&gt;&lt;span&gt;[OSE3]&lt;/span&gt;&lt;/a&gt;.  It
does not, however, reproduce all the discussion that took
place, so the interested reader may wish to glance through
those documents to gain wider context.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;As a basis for the discussion to follow, &lt;em&gt;image import&lt;/em&gt; is described by the
following use case:&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;A cloud end-user has a bunch of bits that they want to give to Glance in the
expectation that (in the absence of error conditions) Glance will produce an
Image (record, file) tuple that can subsequently be used by other OpenStack
services that consume Images.&lt;/p&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;Among the motivations for the above use case are:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;An end user creates a specialized custom image offline and wants to use it in
various OpenStack clouds.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A particular cloud may not offer a public image of some Excellent But Obscure
Operating System (EBOOS).  The EBOOS User Group could make a VM image
available on its website, and EBOOS enthusiasts could import it into the
OpenStack cloud of their choice.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;An end user finds an interesting image in the OpenStack App Catalog and wants
to boot instances from it in an OpenStack cloud.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;An end user creates a snapshot of an instance in one OpenStack cloud and
wants to boot instances from it in another OpenStack cloud.  (Obviously, this
would require image export as well.)&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;Image Creation in OpenStack Clouds&lt;/p&gt;
&lt;p&gt;It’s worth distinguishing three distinct use cases around image
creation:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;A deployer wishes to create public images that end users may use
to boot instances.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Another OpenStack service creates an image from some other
resource it manages (for example, Nova creates an image of a
server, or Cinder creates an image from a volume) at the behest
of an end user.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;An end user wishes to import an image.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Glance should support all three scenarios.&lt;/p&gt;
&lt;/div&gt;
&lt;section id="background"&gt;
&lt;h2&gt;Background&lt;/h2&gt;
&lt;p&gt;Glance contains a “tasks” API that is a result of discussions during and after
the Havana design summit (see &lt;a class="reference internal" href="#osd1" id="id7"&gt;&lt;span&gt;[OSD1]&lt;/span&gt;&lt;/a&gt;, &lt;a class="reference internal" href="#osw2" id="id8"&gt;&lt;span&gt;[OSW2]&lt;/span&gt;&lt;/a&gt;, and &lt;a class="reference internal" href="#osw1" id="id9"&gt;&lt;span&gt;[OSW1]&lt;/span&gt;&lt;/a&gt;).  This API was
designed to present a uniform interface to end-users that allowed a large
degree of customization by individual cloud providers, and currently defines an
‘import’ task.  Since the Havana design summit, however, the DefCore movement
in OpenStack has developed as a means of ensuring interoperability among
OpenStack branded clouds.  The current Glance tasks API is too customizable to
be suitable for DefCore purposes, and in fact, does not fare well when assessed
on the dimensions of interoperability and discoverability.&lt;/p&gt;
&lt;p&gt;The primary problem with tasks as defined in the current API is that they have
an “input” element, defined in the task schema as a JSON blob, whose exact
content is left up to the cloud deployer.  This allows for flexibility on the
part of a cloud deployer, but introduces a discoverability problem, as the only
mechanism currently available for determining acceptable content of the “input”
element is the deployer’s documentation.  While some flexibility is good, this
much flexibility makes it impossible for a competent end-user of one OpenStack
cloud to be sure this competence extends to a different OpenStack cloud.&lt;/p&gt;
&lt;p&gt;One goal of this spec is to implement image import in such a way that it will
be a suitable candidate for inclusion in DefCore.  (See &lt;a class="reference internal" href="#osr1" id="id10"&gt;&lt;span&gt;[OSR1]&lt;/span&gt;&lt;/a&gt; for the list of
12 criteria for being included in DefCore Guidelines.)&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;Currently, Glance is included in two DefCore programs: “OpenStack
Powered Compute” and “OpenStack Powered Platform”. (See &lt;a class="reference internal" href="#oso1" id="id11"&gt;&lt;span&gt;[OSO1]&lt;/span&gt;&lt;/a&gt; for a
definition of these terms.)&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="current-upload-workflow"&gt;
&lt;h2&gt;Current Upload Workflow&lt;/h2&gt;
&lt;p&gt;Here’s a quick reminder of the current image upload workflow.&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;POST&lt;/span&gt; &lt;span class="pre"&gt;v2/images&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;This creates an image record and returns an Image response containing (among
other things) an ‘id’ field.  (The image record can be modified by PATCH
calls, but we’ll ignore that here.)  The key thing is that a record must be
created so that the user has an image_id to work with for the purposes of
uploading the actual image bits.&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;v2/images/{image_id}/file&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;This call instructs Glance to accept the incoming image data and place it
into the storage backend.  The associated image record must have the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;container_format&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;disk_format&lt;/span&gt;&lt;/code&gt; properties set or the call will not
succeed.  This call returns no content.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This current image upload workflow will still exist for backward compatibility
and for use by Glance administrators and trusted OpenStack services.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;For reasons set out in &lt;a class="reference internal" href="#osw3" id="id12"&gt;&lt;span&gt;[OSW3]&lt;/span&gt;&lt;/a&gt; and &lt;a class="reference internal" href="#ose1" id="id13"&gt;&lt;span&gt;[OSE1]&lt;/span&gt;&lt;/a&gt;, it is desirable for deployers to
have the ability easily to separate untrusted end-user image import from the
simple upload facility used by trusted sources (typically, Nova or another
OpenStack service, or Glance administrators supplying public images for use in
a cloud).  What we aim to do in this spec is to define a suitable end-user
image import mechanism that will satisfy the requirements of all OpenStack
clouds, whether small or large, public or private.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="summary-of-the-constraints-around-this-project"&gt;
&lt;span id="constraints"/&gt;&lt;h2&gt;Summary of the Constraints Around This Project&lt;/h2&gt;
&lt;p&gt;Here are, to the best of my recollection, what was agreed upon between the
Glance community, DefCore (mostly Doug Hellman), infra (mostly Monty), and
various interested parties who showed up at the design session on image import
at the Tokyo summit.&lt;/p&gt;
&lt;p&gt;First, background, so you can see what problems needed to be addressed:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;(At least some) Public cloud operators do not want to expose the current
glance v1/v2 image upload as it is too fragile.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The TC passed a resolution in December 2015 &lt;a class="reference internal" href="#new1" id="id14"&gt;&lt;span&gt;[NEW1]&lt;/span&gt;&lt;/a&gt; saying that end user
image upload (what we – following industry parlance – are calling “image
import”) must be available in OpenStack clouds.&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;The TC resolution says that an OpenStack cloud should support import of a
vanilla linux image; no mandate about image format, size, etc.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Part of the goal of this spec is design a discoverable and interoperable
API for image import so that the TC resolution can be satisfied and image
import can be included as a DefCore requirement.  (See &lt;a class="reference internal" href="#new2" id="id15"&gt;&lt;span&gt;[NEW2]&lt;/span&gt;&lt;/a&gt; for more
about this point.)&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The “Tasks” API is a disaster from the interoperability and discoverability
standpoint.  (We know this because at least one large public cloud has
exposed image import via Glance Tasks, and the OpenStack infra team has a
lot to say about how bad it is.  Just ask them.)&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;interoperability failures: The Task object, as defined by
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;v2/schemas/task&lt;/span&gt;&lt;/code&gt; contains an “input” and “result” element which are
defined to be JSON blobs; anything could go in there, so possibly
radically different stuff for each OpenStack cloud&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;discoverability failures: You don’t have to support a particular
disk/container format, but there must be a way to find out what a
particular cloud supports (and this “way” should be the same for all
OpenStack clouds, and no, documentation doesn’t count)&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;There are three cases for “image upload” that Glance should support.&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Admin upload of “base” or “public” images&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Image upload from OpenStack services (for example, Nova or Cinder)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;End user image import&lt;/p&gt;&lt;/li&gt;
&lt;/ol&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;My view is that we are working on the image import use case, and what
we come up with there could, but doesn’t have to, be used/usable for
the other two use cases.  The key point to keep in mind here is that
the discovery of various vulnerabilities may cause operators to halt
import (temporarily), and they will want to do that while still
keeping the other 2 use cases operational.&lt;/p&gt;
&lt;p&gt;As Doug pointed out on a previous patch: “It would be nice to have
only one API, but the hole we have right now is the public-facing use
case and so that’s where the focus of this work should be. If we can
make the results work for the other cases, that’s a bonus, but not
required.”&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;OK, without further ado, here’s what was agreed upon:&lt;/p&gt;
&lt;section id="the-constraints-that-an-adequate-image-import-solution-must-meet"&gt;
&lt;h3&gt;The constraints that an adequate image import solution must meet&lt;/h3&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;There must be a well-defined image import structure/framework that should be
supportable by all OpenStack clouds.&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;“well-defined”&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;calls have request/response schemas that are discoverable&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;the values that will enable a client to have a successful image import
(e.g., supported formats) must be discoverable&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;“discoverable” == via API call (in what Flavio calls a
“follow-your-nose” fashion)&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;specific API request: this would be the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt; &lt;span class="pre"&gt;v2/info/import&lt;/span&gt;&lt;/code&gt; call&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;available in headers: the headers would be returned with the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;POST&lt;/span&gt;
&lt;span class="pre"&gt;v2/images&lt;/span&gt;&lt;/code&gt; response.  The idea is that the content of that
response is the JSON representation of the Image record (so the
import methods available and other associated import information
don’t really belong in a particular &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;image&lt;/span&gt;&lt;/code&gt; resource), and having
the info come back in the headers could allow a client to determine
the import method to use without having to make the discovery call.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;“supportable by all OpenStack clouds”&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;it’s acceptable for there to be multiple import methods as long as
each is well defined.  (See the “Proposed Change” section below for
details.  An “import method” has to do with how the image data is
delivered to Glance.  The API calls won’t change, and their body and
structure will remain the same for the various methods.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;no cloud has to support all import methods, but it’s expected that to
achieve certification as “OpenStack Powered Compute” (and hence, to
even have a shot at certification as an “OpenStack Powered Platform”),
a cloud must expose at least one of these.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Since Swift is not part of the “OpenStack Powered Compute” program,
Glance must expose at least one import method that does not rely upon the
presence of an end-user-accessible object store.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The “three step dance” import style was deemed acceptable&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;one: create image record, two: upload data, three: import call&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;steps one and two can be independent.  For example, in the ‘swift-local’
method sketched out below, an end user could upload the image data to
swift first (accomplishing step two), then do step one, followed by step
three.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The import workflow should allow for server-side operator customization, but
no operator is required to perform such customization.&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;We’re talking about customization in processing the uploaded data.  The
API request/response structure is not customizable.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;span id="id16"/&gt;&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;section id="import-workflow"&gt;
&lt;h3&gt;Import Workflow&lt;/h3&gt;
&lt;p&gt;The import workflow will respect the basic structure of the current upload
workflow described above.&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;End user creates an image record.  (We’ll refer to this as &lt;em&gt;image-create&lt;/em&gt;,
just keep in mind that what’s created is only the image &lt;em&gt;record&lt;/em&gt;.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;End user makes the data available to Glance.  (This could be via direct
upload, or via some other well-defined import method that is discoverable by
an end user.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;End user instructs Glance to process the data and create a bootable image.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;A key distinction between image upload and image import is that imported images
are not immediately available for use, that is, they are not ‘active’ at the
completion of the data PUT call.  This allows deployers optionally to process
the image data (for example, by performing a validation process) before the
image becomes ‘active’.  Additionally, deployers may need to put protected
properties on the image record at this point.  Thus the import call needs to be
asynchronous.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="discovery"&gt;
&lt;h3&gt;Discovery&lt;/h3&gt;
&lt;p&gt;An end user needs to be able to do the following:&lt;/p&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;&lt;p&gt;value discovery&lt;/p&gt;
&lt;p&gt;The end user needs to determine what container format and disk format are
accepted by this cloud, the maximum allowed image size (both actual and
virtual), what import methods are available.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;method discovery&lt;/p&gt;
&lt;p&gt;The end user wants to know what import methods this site supports.  Although
this information will be returned in the value discovery call described
above, we also propose to return it in a response header from the call used
to create the image record.  This way, a client is not required to make the
value discovery call as part of the image import workflow.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;format discovery&lt;/p&gt;
&lt;p&gt;The end user wants to know what an import request body looks like.  This
information will be provided by a JSON schema.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;We assume that the user already knows how to discover the image schema for the
purposes of creating an image and reading an image response.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="import-methods"&gt;
&lt;h3&gt;Import methods&lt;/h3&gt;
&lt;p&gt;We define one initial import method, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance-direct&lt;/span&gt;&lt;/code&gt;, but we envision more
methods such as &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;swift-local&lt;/span&gt;&lt;/code&gt;.  (We include &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;swift-local&lt;/span&gt;&lt;/code&gt; in the discussion
throughout so that it’s clear how the import scheme described in this spec can
be extended in an interoperable way to include other ways of getting the image
data into Glance).&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;We might want to use different terms here that would expose less
internals to the users. For instance, we could just use &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;direct&lt;/span&gt;&lt;/code&gt;
and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;indirect&lt;/span&gt;&lt;/code&gt; as recommended by Steve Lewis in PS8.  We can
discuss the name during development and amend this spec
appropriately.&lt;/p&gt;
&lt;/div&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance-direct&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;The end-user does a PUT of image data directly to Glance using a URL
included in a response header to the image-create request.  (The URL will
also be known by convention, namely, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;v2/images/{image_id}/stage&lt;/span&gt;&lt;/code&gt;.
After the data has been uploaded, the end-user follows with a call to Glance
to process the data and complete the import.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;swift-local&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;The end-user places the image data in the user’s object store account.  Data
placement may occur before or after the image record is created.  After the
data has been uploaded and an image record is created, the end-user makes a
call to Glance to process the data and complete the import.&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;A particular Glance installation does not have to support all methods, but
it’s expected that it will expose at least one.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;I’m trying to get by without giving the end-user any visibility into
the staging area (formerly, the “bikeshed”).  But see the discussion
initiated by Stuart at line 207 in Patch Set 7 about separation of
concerns and the example of Amazon’s s3 “multipart upload”.&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="api-changes"&gt;
&lt;h3&gt;API changes&lt;/h3&gt;
&lt;section id="value-discovery"&gt;
&lt;span id="id17"/&gt;&lt;h4&gt;value discovery&lt;/h4&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;v2/info/import&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;The response is an object in JSON notation.  This document should provide an
end-user with sufficient information to perform an image import.&lt;/p&gt;
&lt;div class="highlight-json notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="linenos"&gt; 1&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="linenos"&gt; 2&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"max_upload_bytes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="linenos"&gt; 3&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;"You may not upload more than this number of bytes when importing a virtual disk."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="linenos"&gt; 4&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;"integer"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="linenos"&gt; 5&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;10737418240&lt;/span&gt;
&lt;span class="linenos"&gt; 6&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="linenos"&gt; 7&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"max_virtual_bytes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="linenos"&gt; 8&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;"You may not upload a virtual disk whose virtual size exceeds this number of bytes."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="linenos"&gt; 9&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;"integer"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="linenos"&gt;10&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;26843545600&lt;/span&gt;
&lt;span class="linenos"&gt;11&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="linenos"&gt;12&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"max_upload_time"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="linenos"&gt;13&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;"You only have this much time to complete your data upload.  Expressed in seconds.  (Does not apply to the 'swift-local' import method.)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="linenos"&gt;14&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;"integer"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="linenos"&gt;15&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;600&lt;/span&gt;
&lt;span class="linenos"&gt;16&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="linenos"&gt;17&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"data_TTL_after_import_error"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="linenos"&gt;18&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;"If an error occurs when you issue the command to import this data, your uploaded data is subject to deletion after this amount of time.  Expressed in hours.  (Does not apply to the 'swift-local' import method.)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="linenos"&gt;19&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;"integer"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="linenos"&gt;20&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"value"&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="linenos"&gt;21&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="linenos"&gt;22&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"source_container_format"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="linenos"&gt;23&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;"Your image data must be in one of these container formats."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="linenos"&gt;24&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;"array"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="linenos"&gt;25&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"value"&lt;/span&gt;&lt;span class="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;"bare"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="linenos"&gt;26&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="linenos"&gt;27&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"source_disk_format"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="linenos"&gt;28&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;"Your image data must be in one of these disk formats."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="linenos"&gt;29&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;"array"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="linenos"&gt;30&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"value"&lt;/span&gt;&lt;span class="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;"vhd"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"vmdk"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"raw"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="linenos"&gt;31&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="linenos"&gt;32&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"target_container_format"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="linenos"&gt;33&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;"Your image will be saved in Glance in one of these container formats."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="linenos"&gt;34&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;"array"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="linenos"&gt;35&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"value"&lt;/span&gt;&lt;span class="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;"ova"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="linenos"&gt;36&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="linenos"&gt;37&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"target_disk_format"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="linenos"&gt;38&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;"Your image will be saved in Glance in one of these disk formats."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="linenos"&gt;39&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;"array"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="linenos"&gt;40&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"value"&lt;/span&gt;&lt;span class="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;"vhd"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="linenos"&gt;41&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="linenos"&gt;42&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"os_type"&lt;/span&gt;&lt;span class="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="linenos"&gt;43&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;"Operating systems allowed for import.  Some operating systems may be non-importable due to licensing constraints."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="linenos"&gt;44&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;"array"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="linenos"&gt;45&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"value"&lt;/span&gt;&lt;span class="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;"linux"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"windows"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="linenos"&gt;46&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="linenos"&gt;47&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"import-methods"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="linenos"&gt;48&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;"Import methods available at this site."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="linenos"&gt;49&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;"array"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="linenos"&gt;50&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"value"&lt;/span&gt;&lt;span class="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;"glance-direct"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"swift-local"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="linenos"&gt;51&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="linenos"&gt;52&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"import-schema-location"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="linenos"&gt;53&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;"Location of the JSON schema for the image import request/response."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="linenos"&gt;54&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="linenos"&gt;55&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"v2/schemas/import"&lt;/span&gt;
&lt;span class="linenos"&gt;56&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="linenos"&gt;57&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;Should we allow users for sending &lt;cite&gt;target_*&lt;/cite&gt; fields?&lt;/p&gt;
&lt;p&gt;Suppose the end-user needs the image to be in a different format to use a
particular flavor or availability zone. We could handle this by introducing
a conversion task (out of scope for this spec, however), where end-user
specifies an existing image and requests that an new image be created in a
specific supported format (where “supported” format depends on the
cloud). This would allow decoupling among:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;what image formats are actually in use in the cloud&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;what image formats are supported for import&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;what image formats are supported for conversion&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It would be good to have such decoupling because:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;the in-use formats depend on what kind of hypervisors you have and what
format they prefer&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;the import formats depend on what formats you are confident your screening
processes are adequate for&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;the conversion formats depend on what you’re confident will convert
correctly&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;section id="summary"&gt;
&lt;h5&gt;summary&lt;/h5&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Method type: GET&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Normal http response code(s): 200 (OK)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;dl class="simple"&gt;
&lt;dt&gt;Expected error http response code(s): 400, 401, 405&lt;/dt&gt;&lt;dd&gt;&lt;ul&gt;
&lt;li&gt;&lt;p&gt;400: request body passed&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;401: unauthorized&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;405: only GET supported for this call&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;URL for the resource: &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;v2/info/import&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;ul&gt;
&lt;li&gt;&lt;p&gt;alternative: &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;v2/info&lt;/span&gt;&lt;/code&gt; (I think we want the sub-resource, however, as
it will keep the response simpler when export, image conversion, and
possibly other functions are added.)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Parameters which can be passed via the URL: none&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;JSON schema definition for the body data: not allowed&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;JSON schema definition for the response data: none&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="format-discovery"&gt;
&lt;span id="id18"/&gt;&lt;h4&gt;format discovery&lt;/h4&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;v2/schemas/import&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;The response is the following JSON schema.&lt;/p&gt;
&lt;div class="highlight-json notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="linenos"&gt; 1&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="linenos"&gt; 2&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;"http://openstack.org/glance/import/request/schema#"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="linenos"&gt; 3&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"$schema"&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://json-schema.org/draft-04/schema#"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="linenos"&gt; 4&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;"OpenStack Glance image import request schema."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="linenos"&gt; 5&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;"object"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="linenos"&gt; 6&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"additionalProperties"&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="linenos"&gt; 7&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"required"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="linenos"&gt; 8&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="s2"&gt;"method"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="linenos"&gt; 9&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="s2"&gt;"source_disk_format"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="linenos"&gt;10&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="s2"&gt;"source_container_format"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="linenos"&gt;11&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="linenos"&gt;12&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"properties"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="linenos"&gt;13&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"method"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="linenos"&gt;14&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;"object"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="linenos"&gt;15&lt;/span&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"oneOf"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="linenos"&gt;16&lt;/span&gt;&lt;span class="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;"$ref"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"#/definitions/glance-direct"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="linenos"&gt;17&lt;/span&gt;&lt;span class="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;"$ref"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"#/definitions/swift-local"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="linenos"&gt;18&lt;/span&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="linenos"&gt;19&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="linenos"&gt;20&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"source_disk_format"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="linenos"&gt;21&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;"vhd"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"vmdk"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"raw"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="linenos"&gt;22&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 disk format of the data to be imported."&lt;/span&gt;
&lt;span class="linenos"&gt;23&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="linenos"&gt;24&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"source_container_format"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="linenos"&gt;25&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;"bare"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ovf"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="linenos"&gt;26&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 container format of the data to be imported.  If no container, use 'bare'."&lt;/span&gt;
&lt;span class="linenos"&gt;27&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="linenos"&gt;28&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"os_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="linenos"&gt;29&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;"linux"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"windows"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="linenos"&gt;30&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 type of the operating system contained in the image."&lt;/span&gt;
&lt;span class="linenos"&gt;31&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="linenos"&gt;32&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="linenos"&gt;33&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"definitions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="linenos"&gt;34&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"glance-direct"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="linenos"&gt;35&lt;/span&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"properties"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="linenos"&gt;36&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="p"&gt;{&lt;/span&gt;
&lt;span class="linenos"&gt;37&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;"glance-direct"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="linenos"&gt;38&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;"Identifier for this import-method."&lt;/span&gt;
&lt;span class="linenos"&gt;39&lt;/span&gt;&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="linenos"&gt;40&lt;/span&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="linenos"&gt;41&lt;/span&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"required"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="linenos"&gt;42&lt;/span&gt;&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="s2"&gt;"name"&lt;/span&gt;
&lt;span class="linenos"&gt;43&lt;/span&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="linenos"&gt;44&lt;/span&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"additionalProperties"&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="linenos"&gt;45&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="linenos"&gt;46&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"swift-local"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="linenos"&gt;47&lt;/span&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"properties"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="linenos"&gt;48&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="p"&gt;{&lt;/span&gt;
&lt;span class="linenos"&gt;49&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;"swift-local"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="linenos"&gt;50&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;"Identifier for this import-method."&lt;/span&gt;
&lt;span class="linenos"&gt;51&lt;/span&gt;&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="linenos"&gt;52&lt;/span&gt;&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nt"&gt;"swift-location"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="linenos"&gt;53&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="linenos"&gt;54&lt;/span&gt;&lt;span class="w"&gt;                    &lt;/span&gt;&lt;span class="nt"&gt;"maxLength"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="linenos"&gt;55&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;"Name of the Swift object to be imported in container/name format."&lt;/span&gt;
&lt;span class="linenos"&gt;56&lt;/span&gt;&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="linenos"&gt;57&lt;/span&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="linenos"&gt;58&lt;/span&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"required"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="linenos"&gt;59&lt;/span&gt;&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="s2"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="linenos"&gt;60&lt;/span&gt;&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="s2"&gt;"swift-location"&lt;/span&gt;
&lt;span class="linenos"&gt;61&lt;/span&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="linenos"&gt;62&lt;/span&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;"additionalProperties"&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="linenos"&gt;63&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="linenos"&gt;64&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="linenos"&gt;65&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 the values for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;source_disk_format&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;source_container_format&lt;/span&gt;&lt;/code&gt;
will be pulled from configuration options used to supply values for the &lt;em&gt;value
discovery&lt;/em&gt; call. This will allow an end-user to do accurate schema-validation on
the request.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;I haven’t addressed Stuart’s question “Do we need to have both
‘global’ and disk format specific parameters?”  The question appears on the
schema in Patch Set 5.  Depending on how it’s answered, a usable schema may
be more complicated than the one proposed here.&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 schema needs to allow for some provider-specific properties.  An
example is &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_type&lt;/span&gt;&lt;/code&gt;, which affects how the Xen hypervisor creates the
guest filesystem.  A cloud may protect this property because otherwise
changing its value from &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;linux&lt;/span&gt;&lt;/code&gt; to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;windows&lt;/span&gt;&lt;/code&gt; will allow end users to run
unlicensed Windows servers in a cloud, leading to violation of licensing
terms, lawsuits, and general unhappiness.&lt;/p&gt;
&lt;p&gt;I’ve included &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_type&lt;/span&gt;&lt;/code&gt; in the schema, but there may be some other such
properties, so I’ve added a work item to contact the operators group and the
product working group so that we can get a (hopefully) definitive list
before the Mitaka release and amend this spec and the schema appropriately.&lt;/p&gt;
&lt;/div&gt;
&lt;section id="id19"&gt;
&lt;h5&gt;summary&lt;/h5&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Method type: GET&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Normal http response code(s): 200 (OK)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;dl class="simple"&gt;
&lt;dt&gt;Expected error http response code(s): 400, 401, 405&lt;/dt&gt;&lt;dd&gt;&lt;ul&gt;
&lt;li&gt;&lt;p&gt;400: request body passed&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;401: unauthorized&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;405: only GET supported for this call&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;URL for the resource: &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;v2/schemas/import&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Parameters which can be passed via the URL: none&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;JSON schema definition for the body data: not allowed&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;JSON schema definition for the response data: response is a JSON schema&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="image-create"&gt;
&lt;h4&gt;image-create&lt;/h4&gt;
&lt;p&gt;This call already exists.  We propose adding additional response headers to
facilitate discovery.  (We also discuss it here because the call is integral to
the image import workflow.)&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;v2/images&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;The current request body and response body remain unchanged.  The image is
created in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;queued&lt;/span&gt;&lt;/code&gt; status (just as it is now for the v2 API).&lt;/p&gt;
&lt;p&gt;Note that &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;disk_format&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;container_format&lt;/span&gt;&lt;/code&gt; are currently optional in
this request, which works well for image import since it’s possible that the
formats of the imported data will be modified during the import process (for
example, an OVA might be unpacked, or a bare disk might be packaged).  The
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;disk_format&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;container_format&lt;/span&gt;&lt;/code&gt; will be required in the image-import
call, as will the common image property &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_type&lt;/span&gt;&lt;/code&gt;.  Values specified in the
image-import call will overwrite any existing values in the image object.&lt;/p&gt;
&lt;section id="new-response-headers"&gt;
&lt;h5&gt;New response headers&lt;/h5&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;OpenStack-image-import-methods&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;The value of this header will be a comma-separated list of import method
keywords.  For example,
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;OpenStack-image-import-methods:&lt;/span&gt; &lt;span class="pre"&gt;glance-direct,swift-local&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;OpenStack-image-glance-direct-url&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;The value of the header will be the URL to which the image data could be PUT
by a subsequent call.  This header will be included only if the site
supports the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance-direct&lt;/span&gt;&lt;/code&gt; import method.  (If the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance-direct&lt;/span&gt;&lt;/code&gt;
name is changed, this header will be renamed as well.  The method name is
included here so that if there are multiple import methods that specify URLs
to whihch data can be uploaded, the client will have a way to distinguish
them.)&lt;/p&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="data-put"&gt;
&lt;h4&gt;data-put&lt;/h4&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;v2/images/{image_id}/stage&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;This call will follow the specification for the current &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PUT&lt;/span&gt;
&lt;span class="pre"&gt;v2/images/{image_id}/file&lt;/span&gt;&lt;/code&gt; call, with the following changes:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;The call to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/file&lt;/span&gt;&lt;/code&gt; is accepted only when the disk and container format
fields have been set on an image.  That will not be required for the call to
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/stage&lt;/span&gt;&lt;/code&gt; because the user will be supplying these in the subsequent
image-import call.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The call will fail when the number of uploaded bytes exceeds the
max_upload_bytes value published in the value discovery call.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The call will fail when the upload time exceeds the
max_upload_time value published in the value discovery call.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The image will be set in status &lt;cite&gt;uploading&lt;/cite&gt; rather than
&lt;cite&gt;saving&lt;/cite&gt;. Calls to &lt;cite&gt;/file&lt;/cite&gt; shouldn’t be accepted if the image
status is &lt;cite&gt;uploading&lt;/cite&gt;. Likewise, calls to &lt;cite&gt;/stage&lt;/cite&gt; shouldn’t be
accepted if the image status is &lt;cite&gt;saving&lt;/cite&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The user indicates that the data has been staged by issuing the image-import
call (see below).  Thus multiple data-put calls are allowed.  This could allow
two users in the same tenant to issue competing data-put calls, but for this
implementation we will consider it the responsibility of the tenant to ensure
that users cooperate appropriately.&lt;/p&gt;
&lt;p&gt;If the subsequent processing on the image concludes that the image should be
rejected, the image data will be deleted and the image will go to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;killed&lt;/span&gt;&lt;/code&gt;
status.&lt;/p&gt;
&lt;p&gt;In order to propagate information to the end user, a new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;message&lt;/span&gt;&lt;/code&gt; field will
be added to the Image object.  See &lt;a class="reference internal" href="#ose4" id="id20"&gt;&lt;span&gt;[OSE4]&lt;/span&gt;&lt;/a&gt; for examples of the type of content
the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;message&lt;/span&gt;&lt;/code&gt; field will contain.&lt;/p&gt;
&lt;section id="id21"&gt;
&lt;h5&gt;summary&lt;/h5&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Method type: PUT&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;dl class="simple"&gt;
&lt;dt&gt;Normal http response code(s): 204 (No Content)&lt;/dt&gt;&lt;dd&gt;&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Alternative is 202, but that’s not quite right because nothing’s going to
happen with respect to the image data until the user makes a subsequent
import call.  In other words, I think 202 implies “your image is on the
way”, and that’s not the case here.  It made sense on the previous patch
set, where a successful PUT did trigger the import processing, but that’s
not the case anymore.&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;Expected error http response code(s): 401, 405, 409, 415&lt;/dt&gt;&lt;dd&gt;&lt;ul&gt;
&lt;li&gt;&lt;p&gt;401: unauthorized&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;405: only PUT supported for this call&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;405: the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance-direct&lt;/span&gt;&lt;/code&gt; import method is not supported at this site&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;409: associated image is not in appropriate status&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;415: unsupported media type (must be &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;application/octet-stream&lt;/span&gt;&lt;/code&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;URL for the resource: &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;v2/images/{image_id}/stage&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Parameters which can be passed via the URL: none&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;JSON schema definition for the body data: none&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;JSON schema definition for the response data: no content in response&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="implementation-issues"&gt;
&lt;h5&gt;implementation issues&lt;/h5&gt;
&lt;p&gt;The exact nature of the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;stage&lt;/span&gt;&lt;/code&gt; (formerly, “bikeshed”) needs to be
determined.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="image-detail"&gt;
&lt;h4&gt;image-detail&lt;/h4&gt;
&lt;p&gt;This call already exists, but we discuss it anyway because it’s integral to the
image import workflow.&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;v2/images/{image_id}&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;This returns an Image object formatted as defined by the JSON schema available
at &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;v2/schemas/image&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Two new image status values will be added to the Image object:&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;uploading&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Why needed: This status conveys to the user that an import data-put call has
been made.  While in this status, a call to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PUT&lt;/span&gt; &lt;span class="pre"&gt;/file&lt;/span&gt;&lt;/code&gt; is disallowed.
(Note that a call to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PUT&lt;/span&gt; &lt;span class="pre"&gt;/file&lt;/span&gt;&lt;/code&gt; on a queued image puts the image into
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;saving&lt;/span&gt;&lt;/code&gt; status.  Calls to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PUT&lt;/span&gt; &lt;span class="pre"&gt;/stage&lt;/span&gt;&lt;/code&gt; are disallowed while an image is
in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;saving&lt;/span&gt;&lt;/code&gt; status.  Thus it’s not possible to use both upload methods on
the same image.)&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;importing&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Why needed: This status conveys to the user that an import call has been
made but that the image is not yet ready for use.  Data-put calls are not
accepted when an image is in this state.&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;A new property will be added to the Image object:&lt;/p&gt;
&lt;dl&gt;
&lt;dt&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;message&lt;/span&gt;&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Why needed: If an error occurs during the import process, the image will go
to status &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;killed&lt;/span&gt;&lt;/code&gt;, but that doesn’t tell the user what happened or
provide any clue about the appropriate action to take.&lt;/p&gt;
&lt;p&gt;Additionally, the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;message&lt;/span&gt;&lt;/code&gt; element can be used for non-error
communication between Glance and the end user.  See &lt;a class="reference internal" href="#ose4" id="id22"&gt;&lt;span&gt;[OSE4]&lt;/span&gt;&lt;/a&gt; for examples of
such usage.&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="image-import"&gt;
&lt;h4&gt;image-import&lt;/h4&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;v2/images/{image_id}/import&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;The request body must conform to the JSON schema retrievable from the format
discovery call, otherwise the call will fail.  There is no response body.&lt;/p&gt;
&lt;p&gt;The status of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;{image_id}&lt;/span&gt;&lt;/code&gt; must be &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;uploading&lt;/span&gt;&lt;/code&gt; or &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;queued&lt;/span&gt;&lt;/code&gt; or the call
will fail with a 409 (Conflict).  (We need to allow image-import from
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;queued&lt;/span&gt;&lt;/code&gt; for non-upload import methods, for example, swift-local or some type
of copy-from functionality.)  If Image &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;{image_id}&lt;/span&gt;&lt;/code&gt; does not exist or is not
owned by the caller, a 404 will be returned.&lt;/p&gt;
&lt;section id="id23"&gt;
&lt;h5&gt;summary&lt;/h5&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Method type: POST&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Normal http response code(s): 202 (Accepted)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;dl class="simple"&gt;
&lt;dt&gt;Expected error http response code(s): 400, 401, 404, 405, 409, 415&lt;/dt&gt;&lt;dd&gt;&lt;ul&gt;
&lt;li&gt;&lt;p&gt;400: malformed request&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;401: unauthorized&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;404: image record doesn’t exist or is not owned by the caller&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;405: only POST supported for this call&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;409: associated image is not in appropriate status&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;415: unsupported media type (must be &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;application/json&lt;/span&gt;&lt;/code&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;URL for the resource: &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;v2/images/{image_id}/import&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Parameters which can be passed via the URL: none&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;JSON schema definition for the body data: &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;v2/schemas/import&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;JSON schema definition for the response data: no response&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="example-glance-direct-method"&gt;
&lt;h5&gt;example (&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance-direct&lt;/span&gt;&lt;/code&gt; method)&lt;/h5&gt;
&lt;div class="highlight-json notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="linenos"&gt;1&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="linenos"&gt;2&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"method"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="linenos"&gt;3&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="s2"&gt;"glance-direct"&lt;/span&gt;
&lt;span class="linenos"&gt;4&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="linenos"&gt;5&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"source_disk_format"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"raw"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="linenos"&gt;6&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"source_container_format"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"bare"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="linenos"&gt;7&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"os_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;"linux"&lt;/span&gt;
&lt;span class="linenos"&gt;8&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="example-swift-local-method"&gt;
&lt;h5&gt;example (&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;swift-local&lt;/span&gt;&lt;/code&gt; method)&lt;/h5&gt;
&lt;div class="highlight-json notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="linenos"&gt;1&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="linenos"&gt;2&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"method"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="linenos"&gt;3&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="s2"&gt;"swift-local"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="linenos"&gt;4&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"swift-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;"import-data/my_image.raw"&lt;/span&gt;
&lt;span class="linenos"&gt;5&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="linenos"&gt;6&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"source_disk_format"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"raw"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="linenos"&gt;7&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"source_container_format"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"bare"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="linenos"&gt;8&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"os_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;"linux"&lt;/span&gt;
&lt;span class="linenos"&gt;9&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&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;span id="id24"/&gt;&lt;h2&gt;Alternatives&lt;/h2&gt;
&lt;p&gt;Here we consider some alternatives for ‘native’ (non-Swift) upload.&lt;/p&gt;
&lt;section id="use-existing-native-v2-upload"&gt;
&lt;h3&gt;Use existing native v2 upload&lt;/h3&gt;
&lt;p&gt;We could use the existing synchronous v2 upload call, namely:&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;v2/images/{image_id}/file&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Advantages:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;No impact on existing API users.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Disadvantages:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Rules out long lived validation/processing.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="change-existing-native-v2-upload-to-be-asynchronous"&gt;
&lt;h3&gt;Change existing native v2 upload to be asynchronous&lt;/h3&gt;
&lt;p&gt;(This would include adding some simple discoverability call.)&lt;/p&gt;
&lt;p&gt;Advantages:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Small change from existing behaviour. May not impact all use cases.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Disadvantages:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Changes existing API behaviour. Not considered backwards compatible.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Users/libraries must change to expect non-synchronous behaviour.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="asynchronous-upload-call"&gt;
&lt;h3&gt;Asynchronous upload call&lt;/h3&gt;
&lt;p&gt;This would be a tweak to the existing v2 upload call, to make it asynchronous –
but in a backwards compatible way. Backwards compatibility could be achieved by
either using a different resource path, adding a header, or using a query parameter.
(This would include adding some simple discoverability call.)&lt;/p&gt;
&lt;p&gt;Advantages:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Very similar to existing upload mechanism.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Still just two API calls (&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;POST&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PUT&lt;/span&gt;&lt;/code&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;No new image states are required.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Disadvantages:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Initially uploaded data is not cached for retry. (Same as existing upload.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Users/libraries are expected to switch to the new method.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Slightly different work-flow than ‘non-native’ imports (ie imports from external sources)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="independent-fileids"&gt;
&lt;h3&gt;Independent fileIds&lt;/h3&gt;
&lt;p&gt;Here, the uploaded bytes are not initially part of a particular
image. This would work the same way as the import-from-Swift case,
in that fileId operations are kept separate from image operations
in a similar way that Swift object operations are kept seperate
from image operations.&lt;/p&gt;
&lt;p&gt;First you upload the bytes with a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;POST&lt;/span&gt;&lt;/code&gt;. This stores the bytes and
generates a unique fileId. At this point the bytes are not ‘part’ of
any image. You then make a call for an image to consume that fileId
(analogous to consuming a Swift object). You then (optionally) delete
the original fileId.&lt;/p&gt;
&lt;p&gt;This could be implemented in slightly different ways.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;A fileId could be completely unassociated with any image, in which
case it could be reused as source data for more than one image.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Alternatively the fileId could be restricted to a particular image by
requiring the image uuid to be specified when creating the fileId. In
both cases, the only time a fileId would impact image state is when the
image is consuming the fileId and goes through the usual &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;queued&lt;/span&gt;&lt;/code&gt;,
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;saving&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; stages.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Advantages:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Swift and Glance work in the same way. (Initial data is not considerd
‘part’ of the image.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Can be extended to uploading several fileIds sequentially or in
parallel.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;fileIds are cached for retry if the import fails&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;fileIds can each have their own size and checksum (for quota/integrity)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;seperation of concerns (less impact on existing code areas, eg image
delete would never have to handle deleting more than one data blob.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;No new image states are required.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Disadvantages:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;More code, eg to list fileIds&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;More API calls than the simple async upload case&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Users/libraries are expected to switch to the new method.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="asynchronous-upload-call-and-independent-fileids"&gt;
&lt;h3&gt;Asynchronous upload call and Independent fileIds&lt;/h3&gt;
&lt;p&gt;These two options could be combined. ‘Asynchronous upload’ would provide a
‘simple’ call for the common simple upload case, ‘independent fileIds’
would provide a more involved set of calls for parallel/segmented
upload. (There are examples elsewhere of of having a simple call for
the basic case and more advanced calls for more advanced functionality,
eg regular Swift upload versus Swift Large Object upload.)&lt;/p&gt;
&lt;p&gt;Advantages:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Simple API available for standard uploads&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;More advanced APIs available to those who need them&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Could implement the simple case first&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Disadvantages:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;More code&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Users/libraries are expected to switch to the new method.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="url-nomination"&gt;
&lt;h3&gt;URL nomination&lt;/h3&gt;
&lt;p&gt;Glance could nominate an opaque URL for the data to be PUT to.
For example, the POST request could return:&lt;/p&gt;
&lt;p&gt;put-data-to: &lt;a class="reference external" href="https://example.com/xxx"&gt;https://example.com/xxx&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;If Swift is available the URL would be a Swift TempURL, if Swift is not
available the URL would point to an appropriate Glance URL.  As far as
I know Swift’s TempURL allows range offset so parallel uploads/partial
retries should work.&lt;/p&gt;
&lt;p&gt;Advantages:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Nice and RESTFul&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Almost equivalent behaviour whether Swift is in use or not&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Disadvantages:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Swift TempURLs limit upload sizes (5GB by default). (Changes to Swift would be required.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A user may have pre-existing image data in Swift. That case would need
to be handled anyway.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In the Swift TempURL case no token header is required to be sent with
the data. In the Glance case a token header would be required (unless we
added TempURL type functionality to Glance). So the two things would not
be completely equivalent. You’d have to know whether you’re sending to
Glance or Swift – or at least whether to send a token or not. You could
potentially just send the token in both cases, but that’s a little untidy
(eg principle of least privilege).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Would require a special account for Swift imports (this would be the
upload target), even in multi-tenant store mode because it may not be
safe to nominate a URL in the user’s own account.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;While (I think) parallel uploads/partial retries are possible with
Swift’s TempURL they could only be attempted if it was known that the
target was Swift, ie if the URL isn’t opaque. So we’d be back to having
to know which service we’re sending the data to. (Unless we forfeited
some of Swift’s advantages.)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="use-existing-tasks-api"&gt;
&lt;h3&gt;Use existing tasks API&lt;/h3&gt;
&lt;p&gt;This works when Swift is present, but doesn’t provide a way
to do an asynchronous ‘native’ upload.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="out-of-scope"&gt;
&lt;h3&gt;Out of scope&lt;/h3&gt;
&lt;p&gt;As discussion on this spec has advanced, we’ve agreed that it does &lt;em&gt;not&lt;/em&gt;
encompass the following features.  At the same time, we should keep in mind
that at a later point, we may want to include such features.  Thus, whatever
design we come up with for image import should make it easy to accommodate
them.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Out of scope: Image conversion during the import process&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Out of scope: Specification of a common disk/container format that all sites
must support&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Out of scope: Equivalence of disk/container format(s) used in a particular
cloud and the disk/container format(s) supported for image import.  (In other
words, no requirement that a site must allow import of all formats in use at
that site.  See the “note” in value-discovery section, above, for more about
this.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Out of scope: Image export (though obviously we want a solution that lends
itself easily to export as well as import)&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;Two new image status values will be added: &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;importing&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;uploading&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;A new image property will be added: &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;message&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;Given that at least one new call is being added to the API, a minor version
bump should occur.&lt;/p&gt;
&lt;p&gt;Not exactly in scope for this spec, but the general consensus is that the
current “tasks” API should be deprecated in this cycle and made an admin-only
API.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;As its intent is to consume user-provided data, this feature will introduce new
security risks.  Historically, the Images v1 API was not meant to be exposed
directly to end users, as it was expected that end users would use the Compute
API for image related calls.  The Compute API defines an “image-create” action,
but this is an action on the servers resource, that is, it creates a snapshot
of an existing instance, not the upload of an end-user supplied image.
Further, discussion at the Havana summit (see &lt;a class="reference internal" href="#ose1" id="id25"&gt;&lt;span&gt;[OSE1]&lt;/span&gt;&lt;/a&gt;) indicated that Images v2
upload shouldn’t be exposed to end users either, but should be reserved for
trusted users.  So even though it’s previously been possible for a particular
deployment to expose image upload directly to end users, it hasn’t been a
recommended practice.&lt;/p&gt;
&lt;p&gt;Image import must be designed so that a deployer can halt image imports during
an emergency.&lt;/p&gt;
&lt;p&gt;We anticipate the following security risks:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;It consumes user-provided data.  Depending upon the container_format and
disk_format allowed, this may expose Glance (and other projects that consume
images from Glance) to decompression bombs or various tar-based attacks.
(Consumers of images may already have mitigation strategies in place, but
Glance itself currently does not.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It enables a resource exhaustion attack.  Vectors include: uploading a
arbitrary number of bytes (can be mitigated by a max size restriction),
uploading an allowable number of bytes over an extremely slow connection (can
be mitigated by a Glance-side timeout), concurrent imports (can be mitigated
by user quota, user limit, task queuing, or some combination).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;(The remainder of the questions in this section will be addressed as the
discussion advances.)&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;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;The image import process should emit notifications.  (Will specify further
after the basic design is worked out.)&lt;/p&gt;
&lt;p&gt;We should implement notifications for at least the following parts of the
import workflow:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;The import operation has been accepted&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Processing has begun&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Processing status periodically (percentage)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Processing has been completed (success/failure)&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
&lt;section id="policy-impact"&gt;
&lt;h3&gt;Policy impact&lt;/h3&gt;
&lt;p&gt;Image import, as described herein, is an end user operation, not an admin
operation.  It is, however, necessary that it be governed appropriately by
Glance policies.  While the default policy setting will allow end users to
import images, a small public deployer with limited resources might want to
restrict image import to specific users.&lt;/p&gt;
&lt;p&gt;Additionally, as mentioned above, it should be possible for a deployer to “turn
off” image import if a vulnerability is discovered.&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;We need to articulate clearly how the traditional Glance image immutability
guarantee applies to image import, namely, an image is immutable once it goes
active.&lt;/p&gt;
&lt;p&gt;The python-glanceclient will be modified to support image import.  (Will
describe the interface after the basic design is worked out.)&lt;/p&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.  (Will fill in after
the basic design is worked out.)&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 may affect how people deploy and configure OpenStack in the
following ways:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Nova depends upon Glance to supply images and accept VM snapshots.  Those
operations are unaffected by this proposal.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Processing image imports may require dedicated resources, for example:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;dedicated nodes if the image validation is CPU-intensive&lt;/p&gt;&lt;/li&gt;
&lt;/ul&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;It is not anticipated that this feature will affect other developers working on
OpenStack.&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;brian-rosmaita&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;mclaren&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="reviewers"&gt;
&lt;h3&gt;Reviewers&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Core reviewer(s):&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;All current glance cores.&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&gt;
&lt;li&gt;&lt;p&gt;API version bump: &lt;a class="reference external" href="https://bugs.launchpad.net/glance/+bug/1523934"&gt;https://bugs.launchpad.net/glance/+bug/1523934&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Policy rules and new configuration options:
&lt;a class="reference external" href="https://bugs.launchpad.net/glance/+bug/1523937"&gt;https://bugs.launchpad.net/glance/+bug/1523937&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;These depend on the policy change.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Start working on the header changes:
&lt;a class="reference external" href="https://bugs.launchpad.net/glance/+bug/1523941"&gt;https://bugs.launchpad.net/glance/+bug/1523941&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Work on the API schema changes (discoverability):
&lt;a class="reference external" href="https://bugs.launchpad.net/glance/+bug/1523944"&gt;https://bugs.launchpad.net/glance/+bug/1523944&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Import call (task triggering):
&lt;a class="reference external" href="https://bugs.launchpad.net/glance/+bug/1523955"&gt;https://bugs.launchpad.net/glance/+bug/1523955&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Make task api admin only:
&lt;a class="reference external" href="https://bugs.launchpad.net/glance/+bug/1527716"&gt;https://bugs.launchpad.net/glance/+bug/1527716&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Document that &lt;cite&gt;/file&lt;/cite&gt; is not recommended for public nodes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Introduce policies so that the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/file&lt;/span&gt;&lt;/code&gt; endpoint can be easily disabled for
operators following the recommendation above. The default setting for these
policies will &lt;strong&gt;not&lt;/strong&gt; change the current behavior.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Contact the operators and product working groups about properties similar to
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_type&lt;/span&gt;&lt;/code&gt; that should be included in the import request schema.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;(internal) task configuration&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;python-glanceclient support&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;tempest tests&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;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;It is not anticipated that this feature will require dependencies not already
used by the current Glance tasks.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;It should be possible to add a tempest test that imports a small image.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;The following will need to be added to the glance developer docs.&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;any new API calls&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;changes to any existing API calls&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;tasks info for glance developers who want to work on tasks&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;tasks info for deployers who want to use tasks (I suggest starting with this
in the dev docs and then move it to one of the OpenStack operator manuals
eventually)&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
&lt;section id="faq"&gt;
&lt;span id="id26"/&gt;&lt;h2&gt;FAQ&lt;/h2&gt;
&lt;p&gt;Everything you always wanted to know about Glance Image Import but were afraid to ask.&lt;/p&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;&lt;p&gt;What is the use case addressed?&lt;/p&gt;
&lt;p&gt;A cloud end-user has a bunch of bits that they want to give to Glance in
the expectation that (in the absence of error conditions) Glance will
produce an Image (record, file) tuple that can subsequently be used by
other OpenStack services that consume Images.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Why is the “regular” upload insufficient?&lt;/p&gt;
&lt;p&gt;Unlike taking a “snapshot” of a instance using the Compute API, where Nova
handles the image creation, packaging, basic cataloging, and uploading into
Glance, exposing image upload opens a cloud to human error (for example,
not a VM image, incorrect type of image for the hypervisors in that cloud,
maliciously packaged/structured image to attack the hypervisor) that
exposes a cloud to extra support load, denial of service, or security
concerns.&lt;/p&gt;
&lt;p&gt;Plus, it’s not just security issues.  Another common use case would be an
end user uploading an OVA that could be automatically unpacked and the
manifest introspected to set appropriate metadata on the image.  Or if
OpenStack were to agree to a common image interchange format, conversion of
the imported image might be required.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How are the above problems addressed by the proposed import process?&lt;/p&gt;
&lt;p&gt;In contrast to “regular” upload, which puts the image data directly into
the storage backend, the image import process allows an operator to examine
the putative image and perform validation/conversion/packaging (or nothing)
before it’s stored in the backend.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Doesn’t this introduce unwanted variability into the import process?&lt;/p&gt;
&lt;p&gt;No, it does not.  The API is fixed so that the API request and response
formats are identical in all OpenStack clouds.  The variability is behind
the scenes, after the user has made the data available to Glance but before
the image status goes to ‘active’.&lt;/p&gt;
&lt;p&gt;Note that while there are multiple import methods, each method is precisely
defined and schematized so that the API calls/responses are standard.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Why multiple methods?&lt;/p&gt;
&lt;p&gt;This is a situation in which a one-size-fits-all approach doesn’t really
work.  There are several issues that come into play that affect the user
experience of both end users and operators, for example, the size of the
images to be imported, the speed of available connections, the ability to
deploy extra upload nodes, the presence/absence of an object store, then
volume of end users doing image imports, the size of a cloud’s operations
team, etc.  Some usage patterns can be accommodated by the method we’re
calling ‘glance-direct’ whereby an end-user directly streams the object
into Glance; others might be better accommodated by import from an object
store whereby end users can make use of appropriate tooling to ensure a
good user experience when uploading large binary objects.  Since OpenStack
provides free software for an object store solution, and since Swift is
deployed in roughly half of all OpenStack clouds, we propose implementing a
‘swift-local’ import method in which the image data would be uploaded to
Swift out of band.&lt;/p&gt;
&lt;p&gt;Additionally, in anticipation of the deprecation of the Images v1 API, some
operators have pointed out that the “copy-from” capability in the older API
is missing from the Images v2 API.  While it’s not a driver for this work,
a well-defined copy-from import method can be accommodated by this design.&lt;/p&gt;
&lt;p&gt;In short, the multiple import methods allow us to have a consistent and
discoverable API across clouds that will empower operators and end users to
offer/use the import methods that work best for them.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What if I don’t like there being multiple import methods?&lt;/p&gt;
&lt;p&gt;Believe me, we have thought about this carefully.  The alternative would be
to have different API calls for each of the different import methods.
That, however, would mitigate against the goal of having stable API calls
supported in all OpenStack-branded clouds, since not every cloud operator
will want to expose all import methods.  That would make it difficult for
image import to be in DefCore.&lt;/p&gt;
&lt;p&gt;Let’s be really careful in describing what we’re talking about here.  The
approved design for image import allows operator choice, but in a very
constrained way.  As far as the end user is concerned, each import method
will operate identically in each OpenStack cloud, and we envision there
being a small number of these methods as each must make it through the
specs process and be implemented in-tree.  Thus it will be possible to code
a client to handle image import seamlessly from the end user point of view.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If there are multiple methods, must a cloud support them all in order to
achieve the “OpenStack” brand via DefCore?&lt;/p&gt;
&lt;p&gt;This is ultimately up to the DefCore project.  Our idea is that since all
OpenStack clouds would support at least one of the import methods, all
OpenStack clouds would thereby have a working Images v2 API image import
facility, and could pass an image import requirement.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If there are multiple methods, how can I determine what’s available in a
particular cloud?&lt;/p&gt;
&lt;p&gt;This can be done programmatically. (a) The GET v2/info/import returns a
well-defined document that contains the list of import methods supported at
a particular site.  (b) A header that comes back from the POST v2/images
call also contains the list of import methods supported at the site.  See
the &lt;a class="reference internal" href="#value-discovery"&gt;&lt;span class="std std-ref"&gt;value discovery&lt;/span&gt;&lt;/a&gt; section of this spec.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If there are multiple methods, how do I know what the request for the
method I want to use is supposed to look like?&lt;/p&gt;
&lt;p&gt;There’s a JSON schema with this information.  See &lt;a class="reference internal" href="#format-discovery"&gt;&lt;span class="std std-ref"&gt;format discovery&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If there are multiple import methods, what’s to stop someone from adding
more?&lt;/p&gt;
&lt;p&gt;Additional methods would have to be proposed in a Glance spec and would
have to meet the discoverability and interoperability constraints we’re
implementing for image import.  So it’s not the kind of thing that can be
done lightly.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What about the old image upload call?&lt;/p&gt;
&lt;p&gt;The PUT to v2/images/{image_id}/file makes sense as a call used by
operators and trusted services, so we are not proposing that it be removed.
We do, however, recommend that operators not expose it directly to end
users.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I have a question you haven’t covered here.&lt;/p&gt;
&lt;p&gt;Well, you could read through this entire spec.  But here are some pointers:&lt;/p&gt;
&lt;p&gt;For details about the import workflow and API calls, start at the
&lt;a class="reference internal" href="#proposed-change"&gt;&lt;span class="std std-ref"&gt;Proposed change&lt;/span&gt;&lt;/a&gt; section.&lt;/p&gt;
&lt;p&gt;If you want more background about why that workflow was chosen, you
need to read the beginning of this document.&lt;/p&gt;
&lt;p&gt;If you want a quick summary of the design constraints, start at the
&lt;a class="reference internal" href="#constraints"&gt;&lt;span class="std std-ref"&gt;Summary of the Constraints Around This Project&lt;/span&gt;&lt;/a&gt; section.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Wait, wasn’t this spec approved for Mitaka?&lt;/p&gt;
&lt;p&gt;Yes, it was.  It didn’t get implemented because we wanted to make sure
there was a thorough exploration of &lt;a class="reference internal" href="#alternatives"&gt;&lt;span class="std std-ref"&gt;Alternatives&lt;/span&gt;&lt;/a&gt; before
implementation began.  The ultimate the consensus was that we should stick
with the original proposal.  The key point here is that the implementation
of this spec has not been rushed through by any means.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The image import spec is really, really long, but I can’t get enough of it.
Where can I read even more?&lt;/p&gt;
&lt;p&gt;The spec has a list of &lt;a class="reference internal" href="#references"&gt;&lt;span class="std std-ref"&gt;References&lt;/span&gt;&lt;/a&gt; you may find interesting.&lt;/p&gt;
&lt;p&gt;There are also some recent etherpads:&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/newton-glance-import-refactor"&gt;Newton contributors’ meeting: image import&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/glance-image-import-implementation-tactics"&gt;Image Import MVP&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Additionally, you may find the discussion on the following patches
entertaining:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://review.openstack.org/232371"&gt;https://review.openstack.org/232371&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/271021"&gt;https://review.openstack.org/271021&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/270980"&gt;https://review.openstack.org/270980&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/311871"&gt;https://review.openstack.org/311871&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;span id="id27"/&gt;&lt;h2&gt;References&lt;/h2&gt;
&lt;div role="list" class="citation-list"&gt;
&lt;div class="citation" id="osd1" role="doc-biblioentry"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id7"&gt;OSD1&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.openstack.org/api-ref-image-v2.html#os-tasks-v2"&gt;http://developer.openstack.org/api-ref-image-v2.html#os-tasks-v2&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class="citation" id="ose1" role="doc-biblioentry"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;OSE1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class="backrefs"&gt;(&lt;a role="doc-backlink" href="#id13"&gt;1&lt;/a&gt;,&lt;a role="doc-backlink" href="#id25"&gt;2&lt;/a&gt;)&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://etherpad.openstack.org/p/havana-getting-glance-ready-for-public-clouds"&gt;https://etherpad.openstack.org/p/havana-getting-glance-ready-for-public-clouds&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class="citation" id="ose2" role="doc-biblioentry"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id4"&gt;OSE2&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.openstack.org/p/glance-upload-mechanism-reloaded"&gt;https://etherpad.openstack.org/p/glance-upload-mechanism-reloaded&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class="citation" id="ose3" role="doc-biblioentry"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id6"&gt;OSE3&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.openstack.org/p/Mitaka-glance-image-import-reloaded"&gt;https://etherpad.openstack.org/p/Mitaka-glance-image-import-reloaded&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class="citation" id="ose4" role="doc-biblioentry"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;OSE4&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class="backrefs"&gt;(&lt;a role="doc-backlink" href="#id20"&gt;1&lt;/a&gt;,&lt;a role="doc-backlink" href="#id22"&gt;2&lt;/a&gt;)&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://etherpad.openstack.org/p/glance-image-import-example"&gt;https://etherpad.openstack.org/p/glance-image-import-example&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class="citation" id="osl1" role="doc-biblioentry"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id3"&gt;OSL1&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-glance/%23openstack-glance.2015-09-22.log.html#t2015-09-22T14:31:00"&gt;http://eavesdrop.openstack.org/irclogs/%23openstack-glance/%23openstack-glance.2015-09-22.log.html#t2015-09-22T14:31:00&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class="citation" id="osm1" role="doc-biblioentry"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id1"&gt;OSM1&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/2015-September/thread.html#74360"&gt;http://lists.openstack.org/pipermail/openstack-dev/2015-September/thread.html#74360&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class="citation" id="osm2" role="doc-biblioentry"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id2"&gt;OSM2&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/2015-September/thread.html#74383"&gt;http://lists.openstack.org/pipermail/openstack-dev/2015-September/thread.html#74383&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class="citation" id="oso1" role="doc-biblioentry"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id11"&gt;OSO1&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://www.openstack.org/brand/interop/"&gt;http://www.openstack.org/brand/interop/&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class="citation" id="osr1" role="doc-biblioentry"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id10"&gt;OSR1&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://git.openstack.org/cgit/openstack/defcore/tree/doc/source/process/CoreCriteria.rst"&gt;http://git.openstack.org/cgit/openstack/defcore/tree/doc/source/process/CoreCriteria.rst&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class="citation" id="osw1" role="doc-biblioentry"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id9"&gt;OSW1&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.openstack.org/wiki/Glance-tasks-api"&gt;https://wiki.openstack.org/wiki/Glance-tasks-api&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class="citation" id="osw2" role="doc-biblioentry"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id8"&gt;OSW2&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.openstack.org/wiki/Glance-tasks-api-product"&gt;https://wiki.openstack.org/wiki/Glance-tasks-api-product&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class="citation" id="osw3" role="doc-biblioentry"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;OSW3&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class="backrefs"&gt;(&lt;a role="doc-backlink" href="#id5"&gt;1&lt;/a&gt;,&lt;a role="doc-backlink" href="#id12"&gt;2&lt;/a&gt;)&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://wiki.openstack.org/wiki/Glance-tasks-import"&gt;https://wiki.openstack.org/wiki/Glance-tasks-import&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class="citation" id="new1" role="doc-biblioentry"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id14"&gt;NEW1&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://governance.openstack.org/resolutions/20151211-bring-your-own-kernel.html"&gt;https://governance.openstack.org/resolutions/20151211-bring-your-own-kernel.html&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class="citation" id="new2" role="doc-biblioentry"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id15"&gt;NEW2&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/defcore/commit/10562c245a6332f52cb5c5d15739dfab15b2baa6"&gt;https://github.com/openstack/defcore/commit/10562c245a6332f52cb5c5d15739dfab15b2baa6&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="other-relevant-supporting-information"&gt;
&lt;h2&gt;Other Relevant Supporting Information&lt;/h2&gt;
&lt;p&gt;[OSB1] &lt;a class="reference external" href="https://blueprints.launchpad.net/glance/+spec/upload-download-workflow"&gt;https://blueprints.launchpad.net/glance/+spec/upload-download-workflow&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;[OSG1] &lt;a class="reference external" href="https://review.openstack.org/#/c/220166/"&gt;https://review.openstack.org/#/c/220166/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;[OSG2] &lt;a class="reference external" href="https://review.openstack.org/#/c/220166/4/doc/source/tasks.rst"&gt;https://review.openstack.org/#/c/220166/4/doc/source/tasks.rst&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;[OSW4] &lt;a class="reference external" href="https://wiki.openstack.org/wiki/Glance-upload-mechanism-reloaded"&gt;https://wiki.openstack.org/wiki/Glance-upload-mechanism-reloaded&lt;/a&gt;&lt;/p&gt;
&lt;/section&gt;
</description><pubDate>Sun, 11 Jan 2026 00:00:00 </pubDate></item><item><title>Operator maintained images lifecycle</title><link>http://specs.openstack.org/openstack/glance-specs/specs/rocky/implemented/glance/operator-image-workflow.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/glance/+spec/hidden-images"&gt;https://blueprints.launchpad.net/glance/+spec/hidden-images&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This spec addresses the problem that cloud operators have into keep a
public image list with only the latest images versions available.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Cloud operators supply &lt;em&gt;public images&lt;/em&gt; that can be used by end users to boot
servers.  An example is an image containing the CentOS 7 operating system.
Such images must be updated as security concerns, etc., are addressed.  In
Glance, however, image data is immutable, so each update results in a new
public image.  Further, operators do not want to delete the “old” public
images, as end users may require them for different use cases like server
rebuilds.  As a result, the default image-list for end users becomes very
large.  Further, the default image-list may contain multiple CentOS 7 images,
for example, making it difficult for end users to determine which image to
use.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;Example&lt;/p&gt;
&lt;p&gt;An operator provides an image for CentOS 7 with a standard set of packages
as image 1. Some minor security problem is discovered in OpenSSL, so the
operator provides image 2 of CentOS 7 with updated OpenSSL. Then a kernel
vulnerability is discovered and the operator issues image 3 of CentOS 7
with updated OpenSSL and a patched kernel. Each of these is a “version” of
the image, but the same version of CentOS 7. The operator wants a new end
user to start with image 3, but a user who’s been around a while longer may
want to continue to use image 1 and patch/upgrade himself (for example, the
OpenSSL update brings in a dependency that conflicts with some key software
the user is running).  If all three images have public visibility, then all
three of them will appear in an end user’s default image-list.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;A current practice is to address this by adding a custom property on an
image, for example, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;"is_current":&lt;/span&gt; &lt;span class="pre"&gt;"yes"&lt;/span&gt;&lt;/code&gt;, but this is operator-specific and
not interoperable.  This only solves part of the problem, however, because end
users must be educated to look for the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;"is_current"&lt;/span&gt;&lt;/code&gt; image property.  It
would be better if &lt;em&gt;only&lt;/em&gt; those images with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;"is_current":&lt;/span&gt; &lt;span class="pre"&gt;"yes"&lt;/span&gt;&lt;/code&gt; were
included in the end user’s default image-list in the first place.&lt;/p&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 boolean column &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;"os_hidden"&lt;/span&gt;&lt;/code&gt; in images table.
Images where &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;"os_hidden"&lt;/span&gt; &lt;span class="pre"&gt;=&lt;/span&gt; &lt;span class="pre"&gt;True&lt;/span&gt;&lt;/code&gt; will be omitted from the image list
presented to the user. This will apply to all image visibilities.
However, the images will continue to be discoverable.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;Example&lt;/p&gt;
&lt;p&gt;An user wants a CentOS 7 provider image, so he uses:
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;"?visibility=public"&lt;/span&gt;&lt;/code&gt; on the  &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt; &lt;span class="pre"&gt;v2/images&lt;/span&gt;&lt;/code&gt; call.
He sees a CentOS 7 image, but notices that it was created_at today,
so he realizes that it’s not the same image that he’s searching for.
So now he uses &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;"?visibility=public&amp;amp;os_hidden=true"&lt;/span&gt;&lt;/code&gt; to get the list of all
available images.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;If the image has &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;"os_hidden"&lt;/span&gt; &lt;span class="pre"&gt;=&lt;/span&gt; &lt;span class="pre"&gt;False&lt;/span&gt;&lt;/code&gt; the image is not omitted from the
image list. It preserves the current behaviour.&lt;/p&gt;
&lt;p&gt;At image creation, if not specified, it’s used &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;"os_hidden"&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;p&gt;Changing the property “os_hidden” will be considered an image update. Because,
the policy is already defined for this operation no other changes are required.&lt;/p&gt;
&lt;p&gt;In the response of create/show image the new property will be displayed as
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_hidden&lt;/span&gt;&lt;/code&gt;. If a pre-Rocky image already has a custom property named as
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_hidden&lt;/span&gt;&lt;/code&gt; then that property will no longer be visible in the response
from Rocky release.&lt;/p&gt;
&lt;p&gt;All operations in the image will continue to be available considering the
policy defined.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Instead using a new image property we can have a new visibility = “hidden”.
Images with this new visibility state will not be in the default image list.
To list images with visibility “hidden” it will be required to explicitly
request it. Ex:
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;"property&lt;/span&gt; &lt;span class="pre"&gt;--visibility=hide"&lt;/span&gt;&lt;/code&gt;
Images with the visibility “hidden” will always be discoverable by the user.&lt;/p&gt;
&lt;p&gt;This solution is less flexible because visibility “hidden” has potentially
the same scope as “public”. The user roles that can use this visibility
need to be controlled by policy.&lt;/p&gt;
&lt;p&gt;Another approach is to use the proposed new image property “hidden” but not
make these images discoverable with the API. However, there is the use case
where a project may require a particular image version (for example: different
OS releases like CentOS7.4 to CentOS7.5; appliance vendors that support their
software on particular images). If “hidden” images are not discoverable cloud
admins will need implement their own solution to expose these images.&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 the “os_hidden” boolean column in images table.&lt;/p&gt;
&lt;p&gt;For the E-M-C migration strategy is proposed:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Triggers: not required. A pre-Rocky glance release will reject an
image-update call setting ‘os_hidden’ with a 400 because it doesn’t recognize
the field.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Expand: will add a boolean “os_hidden” column to the images table.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Contract: not required&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Data Migration: Not required.&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;A new property “os_hidden” will be accepted for the GET call.
GET v2/images … os_hidden=true/false
By default the API will consider os_hidden=false.&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="notification-impact"&gt;
&lt;h3&gt;Notification 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 needs to be aware that the Cloud provider may “hide” old
images. This is specific to each Cloud provider.&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="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;p&gt;Primary assignee:
- Abhishek Kekane&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 support in GET call for the property “os_hidden”.
Consider the default “os_hidden=false”.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Change the image table schema adding a new field.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Change the glance-client to support the new property.&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;TBD&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://review.openstack.org/#/c/327980"&gt;https://review.openstack.org/#/c/327980&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/108574"&gt;https://review.openstack.org/#/c/108574&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/508133"&gt;https://review.openstack.org/#/c/508133&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
</description><pubDate>Sun, 11 Jan 2026 00:00:00 </pubDate></item><item><title>Handle sparse images</title><link>http://specs.openstack.org/openstack/glance-specs/specs/victoria/approved/glance_store/handle-sparse-image.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/glance-store/+spec/handle-sparse-image"&gt;https://blueprints.launchpad.net/glance-store/+spec/handle-sparse-image&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Some drivers like rbd and filesystem support sparse image, meaning
not really write null byte sequences but only the data itself at a given
offset, the “holes” who can appear will automatically interpreted by the
storage backend as null bytes, and do not really consume your storage.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;As glance deal with instance image, it appear that they are majorly composed
of null bytes sequence to represent the whole disk size of the instances, by
exemple the 8GB base CentOS 7 cloud image contain 1GB of data for 7GB of
holes, so it will significantly optimize storage usage and upload time.&lt;/p&gt;
&lt;p&gt;Current implementation of rbd and filesystem driver rely on the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;utils.chunkreadable&lt;/span&gt;&lt;/code&gt; function, which will basically split the file to
import into block of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CHUNK_SIZE&lt;/span&gt;&lt;/code&gt;, then these blocks will be directly written
to the backend whatever the content, and the offset will be incremented by the
size of the chunk.&lt;/p&gt;
&lt;p&gt;Here is an example for a ceph backend with a standard CentOS 7 cloud image
using Glance:&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;rbd&lt;span class="w"&gt; &lt;/span&gt;du&lt;span class="w"&gt; &lt;/span&gt;9b86961e-6bf3-4d0d-99dc-7c762fe6881d
NAME&lt;span class="w"&gt;                                      &lt;/span&gt;PROVISIONED&lt;span class="w"&gt; &lt;/span&gt;USED
9b86961e-6bf3-4d0d-99dc-7c762fe6881d@snap&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="m"&gt;8&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;GiB&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;8&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;GiB
9b86961e-6bf3-4d0d-99dc-7c762fe6881d&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="m"&gt;8&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;GiB&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;B
&amp;lt;TOTAL&amp;gt;&lt;span class="w"&gt;                                         &lt;/span&gt;&lt;span class="m"&gt;8&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;GiB&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;8&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Gi
$&lt;span class="w"&gt; &lt;/span&gt;rbd&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;export&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;9b86961e-6bf3-4d0d-99dc-7c762fe6881d&lt;span class="w"&gt; &lt;/span&gt;/tmp/Centos7full.raw
$&lt;span class="w"&gt; &lt;/span&gt;md5sum&lt;span class="w"&gt; &lt;/span&gt;/tmp/Centos7full.raw
aae49f6f57aecb9774f399149a0b7f35&lt;span class="w"&gt; &lt;/span&gt;/tmp/Centos7full.raw
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;And the same result when uploading the same image with qemu-img convert or rbd
import:&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;rbd&lt;span class="w"&gt; &lt;/span&gt;du&lt;span class="w"&gt; &lt;/span&gt;437e8de0-b897-4846-96aa-aff70cd8794c
NAME&lt;span class="w"&gt;                                      &lt;/span&gt;PROVISIONED&lt;span class="w"&gt; &lt;/span&gt;USED
437e8de0-b897-4846-96aa-aff70cd8794c@snap&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="m"&gt;8&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;GiB&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1008&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;MiB
437e8de0-b897-4846-96aa-aff70cd8794c&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="m"&gt;8&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;GiB&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;B
&amp;lt;TOTAL&amp;gt;&lt;span class="w"&gt;                                         &lt;/span&gt;&lt;span class="m"&gt;8&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;GiB&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1008&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;MiB
$&lt;span class="w"&gt; &lt;/span&gt;rbd&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;export&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;437e8de0-b897-4846-96aa-aff70cd8794c&lt;span class="w"&gt; &lt;/span&gt;/tmp/Centos7sparse.raw
$&lt;span class="w"&gt; &lt;/span&gt;md5sum&lt;span class="w"&gt; &lt;/span&gt;/tmp/Centos7sparse.raw
aae49f6f57aecb9774f399149a0b7f35&lt;span class="w"&gt; &lt;/span&gt;/tmp/Centos7sparse.raw
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;We can see here that the checksum of the downloaded file, either sparse or not
stay the same, so it should not have impact on the file integrity. In both
case, the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance&lt;/span&gt; &lt;span class="pre"&gt;image-download&lt;/span&gt;&lt;/code&gt; command will produce a non sparse file
because download process just read the file in the backend chunk after chunk,
so null byte sequence will be read, sparse file or not.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;There is two successive optimization we can make to achieve the same result
as other import tool like qemu-img:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Do not write null bytes sequences inside chunk (Write optimization)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Rely on filesystem instruction to skip holes (Read optimization)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A new configuration option &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;enable_thin_provisioning&lt;/span&gt;&lt;/code&gt; will be added to rbd
and filesystem backend in order to make it switchable by operator. Enable it
will enable both read and write optimization.&lt;/p&gt;
&lt;section id="do-not-write-null-bytes-sequences-inside-chunk"&gt;
&lt;h3&gt;Do not write null bytes sequences inside chunk&lt;/h3&gt;
&lt;p&gt;This first optimization will work in all case, wether or not the image file
is sparse or not, it is the behaviour implemented in qemu-img. It consist on
checking if the chunk readed is only composed of null bytes, if it’s the
case, just increase the offset without writing any data to the store.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rely-on-filesystem-instruction-to-skip-holes"&gt;
&lt;h3&gt;Rely on filesystem instruction to skip holes&lt;/h3&gt;
&lt;p&gt;This second optimization will rely on the syscall SEEK_HOLE and SEEK_DATA,
available since kernel 3.8 and python 3.3. It consist on directly skipping
holes, without even reading the null bytes sequences, which can be very long
in case of a large image like an appliance (hundred of GB). As it rely on
linux kernel syscall, older linux kernel or Windows node will just
skip the optimization and work like before.&lt;/p&gt;
&lt;p&gt;This second optimization can only work when the image file is actually
considered as sparse by the filesystem, so it require to be converted
“in-place” on staging store to raw file by the convert plugin of import
workflow. If not, by exemple by sending directly a raw file trough Glance
REST API, filesystem of the staging store won’t be aware of the hole.&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;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;section id="write-optimization"&gt;
&lt;h4&gt;Write optimization&lt;/h4&gt;
&lt;p&gt;These tests have been done against 2 rbd backend sent through web-download
image-import workflow, with raw conversion enabled.&lt;/p&gt;
&lt;p&gt;For a 8GO Centos qcow2:&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;Chunk size&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;8MB&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;32MB&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;64MB&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;Time without sparse upload&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;3min31&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;3min26&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;3min28&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Time with sparse upload&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;1min59&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;1min58&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;2min04&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td/&gt;
&lt;td&gt;&lt;p&gt;&lt;strong&gt;-44%&lt;/strong&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;strong&gt;-43%&lt;/strong&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;strong&gt;-40%&lt;/strong&gt;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Storage used without sparse upload&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;8 GiB/8 GiB&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;8 GiB/8 GiB&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;8 GiB/8 GiB&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Storage used with sparse upload&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;1.0 GiB/8 GiB&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;1.0 GiB/8 GiB&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;1.0 GiB/8 GiB&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td/&gt;
&lt;td&gt;&lt;p&gt;&lt;strong&gt;-88%&lt;/strong&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;strong&gt;-88%&lt;/strong&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;strong&gt;-88%&lt;/strong&gt;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;For a 200GO Centos qcow2:&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;Chunk size&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;8MB&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;Time without sparse upload&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;4h&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Time with sparse upload&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;41min11&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td/&gt;
&lt;td&gt;&lt;p&gt;&lt;strong&gt;-83%&lt;/strong&gt;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Storage used without sparse upload&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;200 GiB/200 GiB&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Storage used with sparse upload&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;5.8 GiB/200 GiB&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td/&gt;
&lt;td&gt;&lt;p&gt;&lt;strong&gt;-88%&lt;/strong&gt;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
&lt;section id="read-optimization"&gt;
&lt;h4&gt;Read optimization&lt;/h4&gt;
&lt;p&gt;The following tests have been done by reading data of a Centos 7 image file&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;th class="head"&gt;&lt;p&gt;Centos 8GB Qcow2&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Centos 8GB RAW&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Centos 100GB Qcow2&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Centos 100GB RAW&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;Read all file (including holes)&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;0m3.964s&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;0m16.746s&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;0m4.666s&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;3m4.003s&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Read only data (skip holes)&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;0m2.662s&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;0m4.686s&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;0m3.916s&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;0m4.425s&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td/&gt;
&lt;td&gt;&lt;p&gt;&lt;strong&gt;-32,8%&lt;/strong&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;strong&gt;-72,0%&lt;/strong&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;strong&gt;-16,1%&lt;/strong&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;strong&gt;-97,6%&lt;/strong&gt;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The optimization for the Qcow2 image tends to be negligible, as Qcow2 images
does not have holes, so it should be very fast in all case.
The point here is to show that there is no negative impact for Qcow2 images,
and huge positive one for raw images, so we can apply this behaviour in all
case.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;Addition of a new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;enable_thin_provisioning&lt;/span&gt;&lt;/code&gt; configuration option for rbd
and filesystem store will require operator to enable it. Without this option,
behaviour will stay the same as before.&lt;/p&gt;
&lt;p&gt;As this configuration option is per store, it is possible in a multi-store
environment to choose on which store it will 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, as these optimizations are handled inside drivers itself and should not
change their interfaces.&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;alistarle&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;yebinama&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 drivers who can handle sparse images: filesystem and rbd.&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;Testing that there is no functional regression for the modified drivers.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Testing that it does not have a negative impact on system where
SEEK_DATA/SEEK_HOLE instruction are not available.&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 the new configuration option &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;enable_thin_provisioning&lt;/span&gt;&lt;/code&gt; for rbd
and filesystem driver.&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;Original ceph.io article who expose these optimizations:
&lt;a class="reference external" href="https://ceph.io/planet/importing-an-existing-ceph-rbd-image-into-glance/"&gt;https://ceph.io/planet/importing-an-existing-ceph-rbd-image-into-glance/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Initial abandonned patch in glance_store:
&lt;a class="reference external" href="https://review.opendev.org/#/c/430641/"&gt;https://review.opendev.org/#/c/430641/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Python implementation of SEEK_HOLE/SEEK_DATA syscall:
&lt;a class="reference external" href="https://bugs.python.org/issue10142"&gt;https://bugs.python.org/issue10142&lt;/a&gt;&lt;/p&gt;
&lt;/section&gt;
</description><pubDate>Sun, 11 Jan 2026 00:00:00 </pubDate></item><item><title>Add new cinder’s attachment API and multiattach support</title><link>http://specs.openstack.org/openstack/glance-specs/specs/xena/approved/glance_store/attachment-api-and-multiattach-support.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/glance-store/+spec/attachment-api-and-multiattach-support"&gt;https://blueprints.launchpad.net/glance-store/+spec/attachment-api-and-multiattach-support&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Make glance cinder store use cinder’s new attachment APIs for image operations.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Currently when we make simultaneous requests to glance for using the image to
create multiple volumes or launch multiple instances, the same image volume needs
to be attached multiple times to serve the requests and since the support doesn’t
exist in glance cinder store, some of the requests fails.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Cinder’s new attachment API was introduced in microversion 3.27 which should be
supported by cinder and is required to pass while making calls through cinderclient.
There were 2 new methods introduced, attachment_complete in MV 3.44 and passing
attach mode during attachment_create in MV 3.54 which are also required and hence
we will be using MV 3.54 for attachment related operations.
All these changes are required prior to adding the multiattach handling.&lt;/p&gt;
&lt;p&gt;This should be a 2 stage change:&lt;/p&gt;
&lt;p&gt;1) Replace existing API calls to cinder for attachment with new attachment API
calls&lt;/p&gt;
&lt;ol class="arabic simple" start="2"&gt;
&lt;li&gt;&lt;p&gt;Add multiattach handling for glance cinder usecase&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Use cinder’s image volume cache that will clone the first bootable volume created
from image and subsequent requests will result in cinder’s clone operation instead
of downloading the image from glance.&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 current number of calls to cinder will be reduced resulting in performance
improvement. Example: initialize_connection and attach calls will be replaced
by attachment_update and similarly terminate_connection and detach calls will
be replaced by attachment_delete.&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;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;p&gt;Primary assignee:
* whoami-rajat&lt;/p&gt;
&lt;dl class="simple"&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="reviewers"&gt;
&lt;h3&gt;Reviewers&lt;/h3&gt;
&lt;p&gt;Core reviewer(s):&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;abhishek-kekane&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;jokke&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;rosmaita&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;smcginnis&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;Replace existing calls to old attachment methods with the new attachment API
calls&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Modify cinderclient calls to include microversion&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add code for multiattach handling&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add appropriate 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;Unit tests to have the code coverage and the new attachment code path will
be tested with the glance cinder tempest job running on glance gate.&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;None&lt;/p&gt;
&lt;/section&gt;
</description><pubDate>Sun, 11 Jan 2026 00:00:00 </pubDate></item><item><title>Eliminate Redundant Downloads of Uncached Images</title><link>http://specs.openstack.org/openstack/glance-specs/specs/zed/approved/glance/duplicate-downloads.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/glance/+spec/duplicate-downloads"&gt;https://blueprints.launchpad.net/glance/+spec/duplicate-downloads&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Multiple requests for an image that is not yet cached on the Glance
API node handling the request currently results in multiple
download requests for the same image from the backend store. For
example, 1000 concurrent build requests based off an uncached image
can result in 1000 download requests from the backend store.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;div class="highlight-cucumber notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="k"&gt;Feature:&lt;/span&gt;&lt;span class="nf"&gt; Elasticity&lt;/span&gt;

&lt;span class="nf"&gt;    In order to briefly leverage the power of the Cloud to do some work,&lt;/span&gt;
&lt;span class="nf"&gt;    As an OpenStack Powered Cloud customer leveraging Glance caching&lt;/span&gt;
&lt;span class="nf"&gt;    I want to quickly provision a large number of servers, perform some&lt;/span&gt;
&lt;span class="nf"&gt;    work, and then destroy them.&lt;/span&gt;

&lt;span class="nf"&gt;    &lt;/span&gt;&lt;span class="k"&gt;Scenario Outline:&lt;/span&gt;&lt;span class="nf"&gt; Concurrent Requests for Uncached Image&lt;/span&gt;
&lt;span class="k"&gt;        Given &lt;/span&gt;&lt;span class="nf"&gt;a single Glance API node&lt;/span&gt;
&lt;span class="nf"&gt;        &lt;/span&gt;&lt;span class="k"&gt;And &lt;/span&gt;&lt;span class="nf"&gt;the requested image exists in the backend store&lt;/span&gt;
&lt;span class="nf"&gt;        &lt;/span&gt;&lt;span class="k"&gt;And &lt;/span&gt;&lt;span class="nf"&gt;the requested image is uncached on the Glance API node&lt;/span&gt;
&lt;span class="nf"&gt;        &lt;/span&gt;&lt;span class="k"&gt;When &lt;/span&gt;&lt;span class="nv"&gt;&amp;lt;n&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt; concurrent request(s) for the image is/are made&lt;/span&gt;
&lt;span class="nf"&gt;        &lt;/span&gt;&lt;span class="k"&gt;Then &lt;/span&gt;&lt;span class="nf"&gt;the image will be downloaded from the backend store &lt;/span&gt;&lt;span class="nv"&gt;&amp;lt;m&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt; times&lt;/span&gt;
&lt;span class="nf"&gt;        &lt;/span&gt;&lt;span class="k"&gt;And &lt;/span&gt;&lt;span class="nf"&gt;the image will be cached on the Glance API node&lt;/span&gt;
&lt;span class="nf"&gt;        &lt;/span&gt;&lt;span class="k"&gt;And &lt;/span&gt;&lt;span class="nf"&gt;every request for the image will succeed&lt;/span&gt;

&lt;span class="nf"&gt;        &lt;/span&gt;&lt;span class="k"&gt;Examples:&lt;/span&gt;&lt;span class="nf"&gt; Concurrent Requests&lt;/span&gt;
&lt;span class="k"&gt;            |&lt;/span&gt;&lt;span class="nv"&gt; n&lt;/span&gt;&lt;span class="k"&gt; |&lt;/span&gt;&lt;span class="nv"&gt; m&lt;/span&gt;&lt;span class="k"&gt; |&lt;/span&gt;
&lt;span class="k"&gt;            |&lt;/span&gt;&lt;span class="s"&gt; 1&lt;/span&gt;&lt;span class="k"&gt; |&lt;/span&gt;&lt;span class="s"&gt; 1&lt;/span&gt;&lt;span class="k"&gt; |&lt;/span&gt;
&lt;span class="k"&gt;            |&lt;/span&gt;&lt;span class="s"&gt; 2&lt;/span&gt;&lt;span class="k"&gt; |&lt;/span&gt;&lt;span class="s"&gt; 1&lt;/span&gt;&lt;span class="k"&gt; |&lt;/span&gt;

&lt;span class="nf"&gt;    &lt;/span&gt;&lt;span class="k"&gt;Scenario:&lt;/span&gt;&lt;span class="nf"&gt; Concurrent Requests for Uncached Image Fails&lt;/span&gt;
&lt;span class="k"&gt;        Given &lt;/span&gt;&lt;span class="nf"&gt;a single Glance API node&lt;/span&gt;
&lt;span class="nf"&gt;        &lt;/span&gt;&lt;span class="k"&gt;And &lt;/span&gt;&lt;span class="nf"&gt;the requested image exists in the backend store&lt;/span&gt;
&lt;span class="nf"&gt;        &lt;/span&gt;&lt;span class="k"&gt;And &lt;/span&gt;&lt;span class="nf"&gt;the requested image is uncached on the Glance API node&lt;/span&gt;
&lt;span class="nf"&gt;        &lt;/span&gt;&lt;span class="k"&gt;When &lt;/span&gt;&lt;span class="s"&gt;2&lt;/span&gt;&lt;span class="nf"&gt; concurrent requests for the image are made&lt;/span&gt;
&lt;span class="nf"&gt;        &lt;/span&gt;&lt;span class="k"&gt;And &lt;/span&gt;&lt;span class="nf"&gt;mid-download the client closes the first connection&lt;/span&gt;
&lt;span class="nf"&gt;        &lt;/span&gt;&lt;span class="k"&gt;Then &lt;/span&gt;&lt;span class="nf"&gt;only the first download request will fail&lt;/span&gt;
&lt;span class="nf"&gt;        &lt;/span&gt;&lt;span class="k"&gt;And &lt;/span&gt;&lt;span class="nf"&gt;the image will be cached on the Glance API node&lt;/span&gt;

&lt;span class="nf"&gt;    &lt;/span&gt;&lt;span class="k"&gt;Scenario:&lt;/span&gt;&lt;span class="nf"&gt; Stream to all requests while caching&lt;/span&gt;
&lt;span class="k"&gt;        Given &lt;/span&gt;&lt;span class="nf"&gt;a Glance API node (&lt;/span&gt;&lt;span class="s"&gt;1&lt;/span&gt;&lt;span class="nf"&gt;) with this feature deployed&lt;/span&gt;
&lt;span class="nf"&gt;        &lt;/span&gt;&lt;span class="k"&gt;And &lt;/span&gt;&lt;span class="nf"&gt;a Glance API node (&lt;/span&gt;&lt;span class="s"&gt;2&lt;/span&gt;&lt;span class="nf"&gt;) without this feature deployed&lt;/span&gt;
&lt;span class="nf"&gt;        &lt;/span&gt;&lt;span class="k"&gt;And &lt;/span&gt;&lt;span class="nf"&gt;the requested image exists in the backend store&lt;/span&gt;
&lt;span class="nf"&gt;        &lt;/span&gt;&lt;span class="k"&gt;And &lt;/span&gt;&lt;span class="nf"&gt;the requested image is uncached on Glance API node &lt;/span&gt;&lt;span class="s"&gt;1&lt;/span&gt;
&lt;span class="nf"&gt;        &lt;/span&gt;&lt;span class="k"&gt;And &lt;/span&gt;&lt;span class="nf"&gt;the requested image is uncached on Glance API node &lt;/span&gt;&lt;span class="s"&gt;2&lt;/span&gt;
&lt;span class="nf"&gt;        &lt;/span&gt;&lt;span class="k"&gt;When &lt;/span&gt;&lt;span class="s"&gt;2&lt;/span&gt;&lt;span class="nf"&gt; concurrent requests are made to API node &lt;/span&gt;&lt;span class="s"&gt;1&lt;/span&gt;
&lt;span class="nf"&gt;        &lt;/span&gt;&lt;span class="k"&gt;And &lt;/span&gt;&lt;span class="s"&gt;2&lt;/span&gt;&lt;span class="nf"&gt; concurrent requests are made to API node &lt;/span&gt;&lt;span class="s"&gt;2&lt;/span&gt;
&lt;span class="nf"&gt;        &lt;/span&gt;&lt;span class="k"&gt;Then &lt;/span&gt;&lt;span class="nf"&gt;the &lt;/span&gt;&lt;span class="s"&gt;2&lt;/span&gt;&lt;span class="nf"&gt; requests to API node &lt;/span&gt;&lt;span class="s"&gt;1&lt;/span&gt;&lt;span class="nf"&gt; will succeed&lt;/span&gt;
&lt;span class="nf"&gt;        &lt;/span&gt;&lt;span class="k"&gt;And &lt;/span&gt;&lt;span class="nf"&gt;the &lt;/span&gt;&lt;span class="s"&gt;2&lt;/span&gt;&lt;span class="nf"&gt; requests to API node &lt;/span&gt;&lt;span class="s"&gt;2&lt;/span&gt;&lt;span class="nf"&gt; will succeed&lt;/span&gt;
&lt;span class="nf"&gt;        &lt;/span&gt;&lt;span class="k"&gt;And &lt;/span&gt;&lt;span class="nf"&gt;the image will be cached on Glance API node &lt;/span&gt;&lt;span class="s"&gt;1&lt;/span&gt;
&lt;span class="nf"&gt;        &lt;/span&gt;&lt;span class="k"&gt;And &lt;/span&gt;&lt;span class="nf"&gt;the image will be cached on Glance API node &lt;/span&gt;&lt;span class="s"&gt;2&lt;/span&gt;
&lt;span class="nf"&gt;        &lt;/span&gt;&lt;span class="k"&gt;And &lt;/span&gt;&lt;span class="nf"&gt;the request completion time between the &lt;/span&gt;&lt;span class="s"&gt;2&lt;/span&gt;&lt;span class="nf"&gt; requests to node &lt;/span&gt;&lt;span class="s"&gt;1&lt;/span&gt;
&lt;span class="nf"&gt;            will be statistically less than or equal to&lt;/span&gt;
&lt;span class="nf"&gt;            the request completion time between the &lt;/span&gt;&lt;span class="s"&gt;2&lt;/span&gt;&lt;span class="nf"&gt; requests to node &lt;/span&gt;&lt;span class="s"&gt;2&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Currently, the Glance caching middleware returns an iterator that
downloads from the cache only if the image is already cached. If
the image is uncached, the request is passed onto the API to
obtain an iterator that will download directly from the store. The
response from the API containing this direct iterator is returned
back through the caching middleware. If the image is completely
uncached when the middleware processes the response, it will wrap
the direct download iterator from the API in an another iterator
that will tee to the cache (i.e. read from the store and write to
both the client and the cache via a split pipe).&lt;/p&gt;
&lt;p&gt;Therefore, depending on the state of the cache, one of three
iterators can be returned: an iterator to the cache (if the image
is completely cached), an iterator to the store (if the image is
partially cached), or a teeing iterator that streams from the
store and writes to the cache (if the image is completely
uncached). This approach is racey and can result in many responses
downloading directly from the store and a subset of those teeing
data to the same location on the filesystem.&lt;/p&gt;
&lt;p&gt;The proposed solution is for the first download request to instead of writing
the whole file to the cache, we write the file to cache in chunks. Then, the
subsequent download requests read from the chunks that have been written. Once
the subsequent request finishes reading all the available chunks in the cache,
it will wait for the next available chunk written to the cache by the first
request. It will keep doing this until the first request finishes all the
chunks.&lt;/p&gt;
&lt;p&gt;For the first request:&lt;/p&gt;
&lt;div class="highlight-text notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;if the cache entry does not exist:
    mark the image "caching"
    create a new folder in the cache directory with the image id
    take the iterator from the download (like we are doing now)
    write the data in 1GB chunks to cache
    upon finish, mark the image "cached"
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;For the subsequent request:&lt;/p&gt;
&lt;div class="highlight-text notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;if the image is marked "caching" or "cached":
    read the chunk from the cache until we get all the expected chunks
    if a chunk is not available:
    wait for it to be written by the first request
&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;Note: The hit count of cached image should not be increased for each chunk read,
instead it should be increased once per actual request to read the image from cache.&lt;/p&gt;
&lt;/div&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;&lt;p&gt;Add a configuration option, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;eliminate_duplicate_downloads&lt;/span&gt;&lt;/code&gt;,
to enable this feature. The addition of a configuration option
to control how the caching middleware behaves puts unnecessary
burden on the operator. The caching middleware should meet the
expected behaviors as outlined in the problem description
without introducing a new configuration option. The only value
of such option is to allow a phased roll-out of the feature. If
the consensus is to introduce such an option, being defaulted
to disabled, it should then be deprecated and defaulted to
enabled in the next release.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;To avoid streaming partial image to multiple clients in case
of the initial caching request failing we could block all the
subsequent requests until the image is fully in cache and serve
those only from cache.&lt;/p&gt;
&lt;p&gt;This approach would cause significant delay serving the rest of
the clients with a benefit of saved bandwidth in those rare cases
where the caching gets interrupted by the image or store going
unavailable. Due to possible very long delays on large images this
would complicate the download process as some kind of keepalive for
the client connection would be needed to avoid timeouts.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create a lock within the middleware request handler: This
prevents requests from reaching the root app and establishing a
download iterator in a race to be the first to initiate the
download in the cache middleware response handler. However, it
comes at a reliability and complexity cost. Logic would have to
be implemented in the request handler to recover from failures
between the request and response. That’s a lot of squeeze for
not a lot of juice.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Move the cache out of the middleware into the root app and
provide a locking mechanism around caching and downloading.
There are architectural benefits to this. However, it is a
serious undertaking, and I believe that any conversations
around this should be had completely outside the context of
this change.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Move cache out of Glance API: This requires client side logic
and new / external caching code.&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;See Other deployer impact&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Image request time for concurrent requests will decrease.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Bandwidth consumed between Glance API nodes and backend store
will decrease.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;Every request being served from the cache will impact the
reliability and performance profile. The bottleneck between the
backend store and Glance will be removed for the thundering herd
problem.  However, there could still be a bottleneck between the
hypervisors and the Glance API nodes.&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;p&gt;Primary assignee: Mridula Joshi&lt;/p&gt;
&lt;/section&gt;
&lt;section id="reviewers"&gt;
&lt;h3&gt;Reviewers&lt;/h3&gt;
&lt;p&gt;Core reviewer(s): Erno Kuvaja&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;Add tests&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update the cache methods in the drivers&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update the cache request handler&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update the cache response handler&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update the docs&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;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Unit Tests&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;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;Document any new configuration options, if any.&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://review.opendev.org/c/openstack/glance-specs/+/206120"&gt;https://review.opendev.org/c/openstack/glance-specs/+/206120&lt;/a&gt;&lt;/p&gt;
&lt;/section&gt;
</description><pubDate>Sun, 11 Jan 2026 00:00:00 </pubDate></item><item><title>Spec Lite: Add Application Credential Support to Cinder Backend</title><link>http://specs.openstack.org/openstack/glance-specs/specs/2026.1/approved/glance_store/spec-lite-cinder-application-credential-support.html</link><description>

&lt;dl class="field-list"&gt;
&lt;dt class="field-odd"&gt;project&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;glance_store&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;problem&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;The Cinder backend driver in glance_store currently uses V3Password
authentication for backend storage operations. This prevents Zero
Downtime Password Rotation (ZDPR) from working for Glance deployments
using Cinder as the image backend.&lt;/p&gt;
&lt;p&gt;When the service user password is rotated during ZDPR, Cinder backend
operations fail because the driver cannot authenticate using the
rotated password. This creates a critical gap in ZDPR functionality,
as image uploads and downloads to/from Cinder volumes will fail
during password rotation, defeating the zero-downtime goal.&lt;/p&gt;
&lt;p&gt;The main Glance API service already supports application credentials
via keystonemiddleware, but backend storage operations (Cinder and
Swift) do not support application credentials, creating an incomplete
ZDPR implementation.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;solution&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;Add application credential support to the Cinder backend driver by:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Adding configuration options for application credentials:
- application_credential_id (registered in both [cinder] and
[backend_defaults] groups)
- application_credential_secret (registered in both [cinder] and
[backend_defaults] groups, marked as secret)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Modifying the Cinder driver’s authentication logic to:
- Use BackendGroupConfiguration to read configuration (supports
fallback to [backend_defaults] section)
- Check for application credential configuration first
- Use V3ApplicationCredential authentication if AC credentials
are available
- Fall back to V3Password authentication if AC credentials are
not configured (backward compatible)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update get_cinder_session() function to support application
credentials for Cinder volume operations.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This unified approach allows Cinder backend to use the same AC
credentials from [backend_defaults] section (when same service user
is used) or per-backend overrides (when different service users are
configured), aligning with existing glance_store architecture.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;how&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Add application_credential_id and application_credential_secret options
to Cinder driver configuration options&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Check for AC credentials and use V3ApplicationCredential when
available&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Maintain backward compatibility by falling back to V3Password if AC
credentials are not provided&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;alternatives&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;None&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;impacts&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;DocImpact, ConfigImpact&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;timeline&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;Include in 2026.1 release (or next appropriate release cycle)&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;link&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;None&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;reviewers&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;croelandt, rosmaita&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;assignee&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;abhishekk&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
</description><pubDate>Tue, 16 Dec 2025 00:00:00 </pubDate></item><item><title>Spec Lite: Add Application Credential Support to Swift Backend</title><link>http://specs.openstack.org/openstack/glance-specs/specs/2026.1/approved/glance_store/spec-lite-swift-application-credential-support.html</link><description>

&lt;dl class="field-list"&gt;
&lt;dt class="field-odd"&gt;project&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;glance_store&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;problem&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;The Swift backend driver in glance_store currently uses V3Password
authentication for trustee authentication when using service user
credentials. This prevents Zero Downtime Password Rotation (ZDPR)
from working for Glance deployments using Swift as the image backend.&lt;/p&gt;
&lt;p&gt;When the service user password is rotated during ZDPR, Swift backend
operations fail because the driver cannot authenticate using the
rotated password. This creates a critical gap in ZDPR functionality,
as image uploads and downloads to/from Swift containers will fail
during password rotation, defeating the zero-downtime goal.&lt;/p&gt;
&lt;p&gt;The main Glance API service already supports application credentials
via keystonemiddleware, but backend storage operations (Swift and
Cinder) do not support application credentials, creating an incomplete
ZDPR implementation.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;solution&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;Add application credential support to the Swift backend driver by:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Adding configuration options for application credentials:
- application_credential_id (registered in both [swift] and
[backend_defaults] groups)
- application_credential_secret (registered in both [swift] and
[backend_defaults] groups, marked as secret)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Modifying the Swift driver’s authentication logic to:
- Use BackendGroupConfiguration to read configuration (supports
fallback to [backend_defaults] section)
- Check for application credential configuration first
- Use V3ApplicationCredential authentication if AC credentials
are available
- Fall back to V3Password authentication if AC credentials are
not configured (backward compatible)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update both SingleTenantStore and MultiTenantStore init_client()
functions to support application credentials for trustee
authentication.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This unified approach allows Swift backend to use the same AC
credentials from [backend_defaults] section (when same service user
is used) or per-backend overrides (when different service users are
configured), aligning with existing glance_store architecture.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;how&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Add application_credential_id and application_credential_secret options
to Swift driver configuration options&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update SingleTenantStore.init_client() and MultiTenantStore.init_client()
to check for AC credentials and use V3ApplicationCredential when
available&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Maintain backward compatibility by falling back to V3Password if AC
credentials are not provided&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;alternatives&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;None&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;impacts&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;DocImpact, ConfigImpact&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;timeline&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;Include in 2026.1 release (or next appropriate release cycle)&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;link&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;None&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;reviewers&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;croelandt, rosmaita&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;assignee&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;abhishekk&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
</description><pubDate>Tue, 16 Dec 2025 00:00:00 </pubDate></item><item><title>Download Image from Suggested Stores</title><link>http://specs.openstack.org/openstack/glance-specs/specs/2026.1/approved/glance/download-from-suggested-stores.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/glance/+spec/download-from-specific-store"&gt;https://blueprints.launchpad.net/glance/+spec/download-from-specific-store&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Right now when you download an image using GET /v2/images/{image_id}/file,
Glance tries the default store first. If the image is not there, it tries
other stores until it finds the image. This spec adds a way to tell Glance
what ordering to use to locate the image data for a particular request.
You can give a list of stores you want to try. This helps compute nodes and
services like Nova and Cinder download from stores that are close to them.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;In deployments with multiple stores, images can be in different places like
Swift, Cinder, filesystem, or S3. Right now Glance downloads from the default
store first. If not there, it tries other stores one by one until it finds
the image.&lt;/p&gt;
&lt;p&gt;This has problems:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Services cannot say which store to use&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Services cannot pick a faster store or one that is close to them&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Operators cannot test if a specific store is working&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Cannot spread downloads across different stores&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The store weight feature from 2023.2 lets operators set store priorities. But
this is only for operators. Services like Nova and Cinder cannot choose stores
based on where they are running.&lt;/p&gt;
&lt;p&gt;Use cases:&lt;/p&gt;
&lt;p&gt;Services can find available stores using existing APIs like GET /v2/info/stores
and GET /v2/info/stores/detail. These show store names, descriptions, types,
and properties that help decide which store to use.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Performance: A compute node can download from a local store instead of a
remote one&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Proximity: Edge compute nodes can download from stores close to them (like
“us-east” or “eu-west”)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Testing: Operators can test if a specific store works&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Load distribution: Spread downloads across stores so one store does not get
too much load&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Cost concerns:&lt;/p&gt;
&lt;p&gt;If users can pick any store, they might pick expensive ones. For example, if
there is a backup store on S3, downloading from it costs money for data egress.
Users may not know this. To fix this, operators can use policy to control who
can use this feature. Operators can also use good store names and descriptions
to guide users to cheaper stores.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Add new query parameters to the existing download endpoint. This lets services
suggest the ordering of stores to try.&lt;/p&gt;
&lt;p&gt;API call:
GET /v2/images/{image_id}/file?prefer=store1,store2&lt;/p&gt;
&lt;p&gt;How it works:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;If caching is enabled, and the image is cached, the ‘prefer’ parameter
is ignored and the data is returned.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Check if the stores in the list exist and are configured. Return errors
if store does not exist.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Try stores from the list in order. Download from the first store that
has the image.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If image is not found in any of the listed stores, fall back to default
behavior (try all stores)&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This approach is better than a new endpoint because:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Does not add another download API&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Easy for Nova and Cinder to add preferred stores without big changes&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Still backward compatible - if no parameters given, works like before&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;Important cache behavior: Store preference parameters only work when
fetching images from backend stores, not when serving from cache. When an
image is cached, the cache middleware serves it directly and bypasses the
store preference logic entirely. This means cached images will always return
HTTP 200 regardless of store parameters, and store preference validation (400
errors for invalid stores) will not occur for cached images.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Policy for store preference:&lt;/p&gt;
&lt;p&gt;A new policy rule “download_from_store” will be added to control who can use
store preference parameters. The default policy will allow anyone who can
download images to also use store preference. This matches the current behavior
where store preference is available to all users who can download. Deployers
can restrict this policy later if needed. For example, they can make it admin
or service role only to prevent regular users from picking expensive stores.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;New endpoint approach: Create GET /v2/stores/{store_id}/{image_id}/file
endpoint. This follows the same pattern as delete-from-store API. But it
only allows one store at a time. Services would need to make multiple calls
to try different stores. This makes things slower and more complex.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Header-based approach: Use HTTP headers to say which store. But headers are
harder to discover and use.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Store weight only: Use the existing store weight from 2023.2. But this only
works at operator level. Services cannot choose stores based on where they
run.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;No change: Keep current behavior. But this does not let services pick stores
close to them.&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;Modified endpoint: GET /v2/images/{image_id}/file&lt;/p&gt;
&lt;p&gt;New query parameters:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;prefer: Comma-separated list of store names (optional)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Response codes:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;200 OK: Image downloaded&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;400 Bad Request: Invalid store name or bad parameters&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;403 Forbidden: User does not have permission to use this feature&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;404 Not Found: Image not found&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Examples:&lt;/p&gt;
&lt;p&gt;Download from preferred stores:&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;dl class="simple"&gt;
&lt;dt&gt;curl -H “X-Auth-Token: $TOKEN” &lt;/dt&gt;&lt;dd&gt;&lt;p&gt;“&lt;a class="reference external" href="http://glance-api:9292/v2/images"&gt;http://glance-api:9292/v2/images&lt;/a&gt;/{image_id}/file?prefer=local-store,backup-store”&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;Download normal way (no change):&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;dl class="simple"&gt;
&lt;dt&gt;curl -H “X-Auth-Token: $TOKEN” &lt;/dt&gt;&lt;dd&gt;&lt;p&gt;“&lt;a class="reference external" href="http://glance-api:9292/v2/images"&gt;http://glance-api:9292/v2/images&lt;/a&gt;/{image_id}/file”&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;Store discovery:&lt;/p&gt;
&lt;p&gt;Services can find available stores using GET /v2/info/stores:&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;dl class="simple"&gt;
&lt;dt&gt;curl -H “X-Auth-Token: $TOKEN” &lt;/dt&gt;&lt;dd&gt;&lt;p&gt;“&lt;a class="reference external" href="http://glance-api:9292/v2/info/stores"&gt;http://glance-api:9292/v2/info/stores&lt;/a&gt;”&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;Response 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;"stores"&lt;/span&gt;&lt;span class="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;"local-store"&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;"Fast local store"&lt;/span&gt;&lt;span class="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;"backup-store"&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;"S3 backup store"&lt;/span&gt;&lt;span class="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;Backward compatibility:&lt;/p&gt;
&lt;p&gt;If no query parameters are given, the endpoint works exactly like before. This
means existing code keeps working without any changes.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;Access control:&lt;/p&gt;
&lt;p&gt;The normal image download policy still applies. Users must have permission to
download the image. A new policy rule “download_from_store” controls who can
use store preference parameters. By default, anyone who can download images can
also use store preference. Deployers can restrict this policy later if needed.&lt;/p&gt;
&lt;p&gt;Store validation:&lt;/p&gt;
&lt;p&gt;Glance will check that store names are valid and configured before trying to
use them.&lt;/p&gt;
&lt;p&gt;No new data exposure:&lt;/p&gt;
&lt;p&gt;This only changes which store to download from. Users can only download images
they already have access to.&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;User docs and API reference need updates to explain the new query parameters.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;Positive impact:&lt;/p&gt;
&lt;p&gt;Services can pick faster stores or stores close to them. This can make downloads
faster.
uncached requests.&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;Store management:&lt;/p&gt;
&lt;p&gt;Deployers should use good store names and descriptions. This helps services
pick the right stores. For example, “local-fast” vs “backup-s3” makes it clear
which is local and which is expensive.&lt;/p&gt;
&lt;p&gt;Cost considerations:&lt;/p&gt;
&lt;p&gt;Services might pick expensive stores like S3 backup stores without knowing the
cost. To handle this:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Use clear store names to show which stores are expensive&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add policy rules to limit who can use store suggestion&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Consider making this admin or service role only initially&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Policy controls:&lt;/p&gt;
&lt;p&gt;Operators can add optional policy rules to control who can use this feature.
This can be based on user roles or projects.&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;abhishek-kekane&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 query parameter parsing to download endpoint&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Implement store list validation&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add policy support for store suggestion control&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add logic to try stores from the list, fallback to default if not found&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add unit tests for new parameters&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add functional tests for different scenarios&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update API 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;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 required unit and functional tests&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;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Update API documentation&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update user docs&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update operator docs&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;Store weight specification: &lt;a class="reference external" href="https://specs.openstack.org/openstack/glance-specs/specs/2023.2/approved/glance_store/store-weight.html"&gt;https://specs.openstack.org/openstack/glance-specs/specs/2023.2/approved/glance_store/store-weight.html&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Store weight implementation: &lt;a class="reference external" href="https://review.opendev.org/c/openstack/glance_store/+/885595"&gt;https://review.opendev.org/c/openstack/glance_store/+/885595&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
</description><pubDate>Tue, 07 Oct 2025 00:00:00 </pubDate></item><item><title>Enhanced filesystem driver with configurable timeout protection</title><link>http://specs.openstack.org/openstack/glance-specs/specs/2026.1/approved/glance_store/filesystem-timeout-protection.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/glance-store/+spec/filesystem-timeout-protection"&gt;https://blueprints.launchpad.net/glance-store/+spec/filesystem-timeout-protection&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Add timeout protection to filesystem operations. This prevents operations from
hanging forever when storage is not available. This works for all filesystem
types (local or network) based on configuration.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;The filesystem store driver in glance_store does not have any timeouts for
filesystem operations. When storage becomes unavailable, operations like
os.path.exists(), os.unlink(), and os.statvfs() can hang forever. This causes
Glance API timeouts and bad user experience.&lt;/p&gt;
&lt;p&gt;Common scenarios where these problems happen:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;NFS server outages or network problems&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Storage backend failures (PowerFlex, PowerStore, etc.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Network connectivity issues between Glance and storage&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Storage maintenance windows&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Local disk failures that cause IO operations to hang&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When these problems happen, Glance operations like image deletion, retrieval,
and storage capacity checks will hang forever. This causes:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;API timeouts and bad user experience&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Resource exhaustion on Glance API servers&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Cannot perform maintenance operations&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Cascading failures in OpenStack deployments&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Add timeout protection to the filesystem driver. This prevents operations from
hanging forever. This keeps backward compatibility by default. Default is
blocking IO (timeout = 0 means wait forever).&lt;/p&gt;
&lt;p&gt;Three new configuration options will be added:&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;[filesystem]&lt;/span&gt;
&lt;span class="c1"&gt;# Timeout for all filesystem operations (seconds)&lt;/span&gt;
&lt;span class="c1"&gt;# Set to 0 to disable timeout protection (blocking IO, normal behavior)&lt;/span&gt;
&lt;span class="c1"&gt;# Set &amp;gt; 0 to enable timeout protection with thread pool&lt;/span&gt;
&lt;span class="c1"&gt;# Recommended: 30 seconds for network storage, higher for slow networks&lt;/span&gt;
&lt;span class="na"&gt;filesystem_store_timeout&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;0&lt;/span&gt;

&lt;span class="c1"&gt;# Thread pool size for timeout-protected operations&lt;/span&gt;
&lt;span class="c1"&gt;# Only meaningful when filesystem_store_timeout &amp;gt; 0&lt;/span&gt;
&lt;span class="c1"&gt;# Ignored when filesystem_store_timeout = 0 (no thread pool is created)&lt;/span&gt;
&lt;span class="c1"&gt;# Each store instance gets its own pool to avoid starvation&lt;/span&gt;
&lt;span class="c1"&gt;# Set based on expected concurrency and WSGI worker count&lt;/span&gt;
&lt;span class="na"&gt;filesystem_store_thread_pool_size&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;10&lt;/span&gt;

&lt;span class="c1"&gt;# Thread pool usage threshold for warning logs (percentage)&lt;/span&gt;
&lt;span class="c1"&gt;# Only meaningful when filesystem_store_timeout &amp;gt; 0&lt;/span&gt;
&lt;span class="c1"&gt;# Ignored when filesystem_store_timeout = 0 (no thread pool is created)&lt;/span&gt;
&lt;span class="c1"&gt;# When thread pool usage exceeds this threshold, a warning is logged&lt;/span&gt;
&lt;span class="c1"&gt;# indicating that the pool is getting busy and may start blocking&lt;/span&gt;
&lt;span class="na"&gt;filesystem_store_threadpool_threshold&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;75&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The options &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;filesystem_store_thread_pool_size&lt;/span&gt;&lt;/code&gt; and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;filesystem_store_threadpool_threshold&lt;/span&gt;&lt;/code&gt; are only used when
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;filesystem_store_timeout&lt;/span&gt; &lt;span class="pre"&gt;&amp;gt;&lt;/span&gt; &lt;span class="pre"&gt;0&lt;/span&gt;&lt;/code&gt;. When &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;filesystem_store_timeout&lt;/span&gt; &lt;span class="pre"&gt;=&lt;/span&gt; &lt;span class="pre"&gt;0&lt;/span&gt;&lt;/code&gt;, these
options are ignored since no thread pool is created.&lt;/p&gt;
&lt;p&gt;We use ThreadPoolExecutor to wrap filesystem operations when
filesystem_store_timeout &amp;gt; 0. When filesystem_store_timeout = 0 (or not set),
operations run directly without thread pool overhead (blocking IO, current
behavior).&lt;/p&gt;
&lt;p&gt;Each store instance will have its own thread pool.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;When an operation times out:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The calling thread stops waiting and raises TimeoutError&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The worker thread continues running (cannot be killed) but we move on&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Error message: “Operation timed out after {timeout}s. Check storage
health and connectivity.”&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When filesystem_store_timeout = 0 (or not set):&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Operations run directly without thread pool overhead&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;No timeout protection (current behavior, backward compatible)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The options &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;filesystem_store_thread_pool_size&lt;/span&gt;&lt;/code&gt; and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;filesystem_store_threadpool_threshold&lt;/span&gt;&lt;/code&gt; are ignored (no thread pool
is created).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Operations that will be wrapped (when timeout &amp;gt; 0):&lt;/p&gt;
&lt;p&gt;For the first implementation, timeout protection will be limited to metadata
operations. Data pipeline operations (get(), add()) are more complex and will
be considered for a future enhancement.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;delete() - wraps os.unlink()&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;When delete() times out, we return an error to the user. But the worker
thread may still complete the deletion later if storage becomes available
again. This can leave the DB record while the file is gone. We will
consider deleting from the DB first, then the store. That way, if the
store delete times out, the DB is already cleaned up. Operators can handle
orphaned files later. This potential inconsistency will be documented. We
may enhance this later to handle it better. For example, if a subsequent
delete() finds the file already gone, treat it as success (idempotent
delete).&lt;/p&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;get_size() - wraps os.path.getsize()&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;_get_capacity_info() - wraps os.statvfs()&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Data pipeline operations (future enhancement):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;add() - wraps os.path.exists(), file open(), and file writes&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;get() - wraps file location resolution (os.path.exists, os.path.getsize)
and ChunkedFile creation (which opens the file via open())&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;Protecting get() is complex because it only protects the initial file
open, not the streaming reads that happen later when the iterator is
consumed. If the mount goes away during streaming, those reads will still
hang. Full protection would require a wrapper iterator that delegates all
reads to the thread pool, which adds significant complexity and overhead.&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;None.&lt;/p&gt;
&lt;p&gt;The following alternatives were considered but none are useful:&lt;/p&gt;
&lt;p&gt;Filesystem Detection Approach&lt;/p&gt;
&lt;p&gt;We could detect filesystem types (NFS, CIFS, etc.) and only apply timeout
protection to network filesystems. This adds complexity without clear benefit.
Local filesystems can also hang (failing disks). Operators can configure timeout
protection if needed.&lt;/p&gt;
&lt;p&gt;Dedicated NFS Driver&lt;/p&gt;
&lt;p&gt;We could create a separate NFS driver alongside the filesystem driver. This
would require operators to change their driver configuration. This would break
backward compatibility.&lt;/p&gt;
&lt;p&gt;Application-Level Timeouts&lt;/p&gt;
&lt;p&gt;We could implement timeouts only at the API level. This does not work because
the hanging happens at the filesystem driver level. We need protection at the
storage layer.&lt;/p&gt;
&lt;p&gt;No Configuration Options&lt;/p&gt;
&lt;p&gt;We could skip adding configuration options and just hardcode timeouts. This was
rejected because different storage backends have different latency
characteristics. Operators need the flexibility to tune timeouts.&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 prevents resource exhaustion attacks. An attacker could exploit hanging
filesystem operations to consume server resources. Since each store instance has
its own thread pool, an attack on one filesystem cannot exhaust all server
resources. The damage is limited to that specific store.&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 get faster failure responses when storage is unavailable. This
happens instead of indefinite hanging (when timeout protection is enabled).
Operators will also get warning logs when thread pool usage exceeds the
configured threshold, helping them identify potential issues before operations
start failing.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;When timeout protection is enabled (timeout &amp;gt; 0), there is some overhead
from thread pool operations. When disabled (timeout = 0), there is no
performance impact (normal behavior). This prevents resource exhaustion from
hanging operations when enabled.&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 can configure the timeout value based on their storage
characteristics. The default of 0 (blocking IO) keeps backward compatibility.
For network storage or unreliable storage, operators can set
filesystem_store_timeout &amp;gt; 0 to enable protection.&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;abhishek-kekane&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 thread pool wrapper for filesystem operations with timeout&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update delete(), get_size(), and _get_capacity_info() to use thread pool
when timeout &amp;gt; 0&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Implement thread pool usage monitoring and warning logs when threshold is exceeded&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add generic timeout error messages&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Document timeout edge cases (e.g., delete operations that complete after timeout)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Write unit and functional tests for timeout behavior&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;Tempest tests for timeout behavior&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 new configuration options&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Provide guidance on timeout values for different storage types&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Document potential inconsistency when delete() times out (file may be deleted
later, leaving DB record)&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;
</description><pubDate>Tue, 30 Sep 2025 00:00:00 </pubDate></item><item><title>RBD Erasure-Coded Pools Support</title><link>http://specs.openstack.org/openstack/glance-specs/specs/2026.1/approved/glance_store/rbd-erasure-coded-pools.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/glance/+spec/rbd-erasure-coded-pools"&gt;https://blueprints.launchpad.net/glance/+spec/rbd-erasure-coded-pools&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This specification proposes adding support for erasure-coded pools in the
Glance RBD store driver for cold storage and archival use cases. Erasure-coded
pools reduce storage overhead by 50-75% compared to traditional 3x replication,
but have significant performance costs (CPU overhead, slower operations). This
makes them suitable for infrequently-accessed images where storage efficiency
is more important than performance.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;The current RBD store driver in Glance only supports replicated pools, which
typically use 3x replication and require 200% storage overhead. For large-scale
deployments with terabytes of images, particularly cold storage or archival
images that are infrequently accessed, this overhead is expensive.&lt;/p&gt;
&lt;p&gt;Erasure-coded pools can provide similar data protection with 50-75% less
storage overhead, but they have significant performance trade-offs (higher CPU
usage on the Ceph cluster, slower write and read operations, slower recovery).
These trade-offs make them unsuitable as a general replacement for replication,
but valuable for specific use cases where storage cost is more important than
performance.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;This specification proposes extending the RBD store driver to support
erasure-coded pools using Ceph’s two-pool model.&lt;/p&gt;
&lt;p&gt;Use librbd’s native &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;data_pool&lt;/span&gt;&lt;/code&gt; parameter to store image metadata in a
replicated pool and image data in an erasure-coded pool.&lt;/p&gt;
&lt;p&gt;Before enabling this feature, deployers must create and configure the required
pools on their Ceph cluster. The following commands are expected to be run:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;$&lt;span class="w"&gt; &lt;/span&gt;ceph&lt;span class="w"&gt; &lt;/span&gt;osd&lt;span class="w"&gt; &lt;/span&gt;pool&lt;span class="w"&gt; &lt;/span&gt;create&lt;span class="w"&gt; &lt;/span&gt;images_data&lt;span class="w"&gt; &lt;/span&gt;erasure
$&lt;span class="w"&gt; &lt;/span&gt;ceph&lt;span class="w"&gt; &lt;/span&gt;osd&lt;span class="w"&gt; &lt;/span&gt;pool&lt;span class="w"&gt; &lt;/span&gt;create&lt;span class="w"&gt; &lt;/span&gt;images&lt;span class="w"&gt; &lt;/span&gt;replicated
$&lt;span class="w"&gt; &lt;/span&gt;ceph&lt;span class="w"&gt; &lt;/span&gt;osd&lt;span class="w"&gt; &lt;/span&gt;pool&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;images_data&lt;span class="w"&gt; &lt;/span&gt;allow_ec_overwrites&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;true&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;allow_ec_overwrites&lt;/span&gt; &lt;span class="pre"&gt;true&lt;/span&gt;&lt;/code&gt; setting is required on the erasure-coded
pool. Without this setting, image creation will fail when using the two-pool
model, as librbd needs to be able to overwrite objects in the erasure-coded
pool for metadata operations.&lt;/p&gt;
&lt;p&gt;Add &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;rbd_store_data_pool&lt;/span&gt;&lt;/code&gt; configuration option to specify the erasure-coded
pool for data storage. If not configured, the driver behaves exactly as it
currently does with single replicated pools.&lt;/p&gt;
&lt;p&gt;Implementation:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;When creating new images, pass the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;data_pool&lt;/span&gt;&lt;/code&gt; parameter to librbd’s
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;create()&lt;/span&gt;&lt;/code&gt; method. librbd handles all the complexity of managing the
two pools.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Existing images remain in their original single-pool location (all data and
metadata in the replicated pool). librbd transparently handles reading them
from their current location.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;New images created after enabling &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;rbd_store_data_pool&lt;/span&gt;&lt;/code&gt; will use the
two-pool model (metadata in the replicated pool, data in the erasure-coded
pool).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;rbd_store_data_pool&lt;/span&gt;&lt;/code&gt; is enabled, the replicated pool (specified by
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;rbd_store_pool&lt;/span&gt;&lt;/code&gt;) will contain both:
* Existing images: All image data and metadata (single-pool storage)
* New images: Only image metadata (two-pool storage)&lt;/p&gt;
&lt;p&gt;While this mixing is technically supported by librbd, it is not recommended
for production deployments. Operators should consider one of the following
approaches:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Use separate pools (recommended): Create a new replicated pool
specifically for metadata when enabling erasure-coded pools, keeping the
existing pool for legacy images. For example:
- Keep existing &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;images&lt;/span&gt;&lt;/code&gt; pool for legacy images
- Create new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;images_meta&lt;/span&gt;&lt;/code&gt; pool for metadata of new images
- Create &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;images_data&lt;/span&gt;&lt;/code&gt; pool for data of new images&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Migration path: Use Glance multistore to migrate existing images to a
separate backend before enabling erasure-coded pools, or use external tools
to migrate images between pools.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Accept mixing: Allow mixing in the same pool if the deployment can
tolerate the operational complexity.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Migration of existing images to use the two-pool model is not part of this
specification. If needed, this would be a future enhancement that could use
Glance multistore capabilities or external migration tools.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;Performance Considerations:&lt;/p&gt;
&lt;p&gt;Erasure-coded pools have significant performance trade-offs. The Ceph OSD
daemons (storage nodes) need substantial CPU power to encode and decode data.
This overhead is not on Glance itself, but on the Ceph cluster. Higher k+m
values (e.g., 8+3 vs 4+2) increase CPU usage.&lt;/p&gt;
&lt;p&gt;Writes are slower due to encoding work. Reads can be slower, especially if
data reconstruction is needed when nodes are down. Rebuilding data after
hardware failures is much more CPU-intensive and slower than with replicated
pools.&lt;/p&gt;
&lt;p&gt;For large image uploads, operators may need to increase timeout settings
(particularly for image imports using the stage-&amp;gt;import workflow) if write
performance to EC pools is significantly slower than to replicated pools.&lt;/p&gt;
&lt;p&gt;Best use cases are cold storage or archival images that are infrequently
accessed, where storage cost savings are more important than performance.&lt;/p&gt;
&lt;p&gt;This feature is disabled by default. Deployers should test performance with
their specific Ceph hardware and erasure coding profile before enabling
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;rbd_store_data_pool&lt;/span&gt;&lt;/code&gt; in production.&lt;/p&gt;
&lt;/div&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Implement a system that automatically selects pools based on image
characteristics. This adds complexity and isn’t needed for most deployments.&lt;/p&gt;
&lt;p&gt;Use external tools to move images between pools. This lacks integration with
Glance and requires separate management tools.&lt;/p&gt;
&lt;p&gt;Don’t add this feature. Deployments that need cost-efficient cold storage would
have to accept the storage overhead or use external solutions.&lt;/p&gt;
&lt;p&gt;The proposed solution is simple: just pass the data pool configuration through
to librbd, which already supports this natively.&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;When &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;rbd_store_data_pool&lt;/span&gt;&lt;/code&gt; is configured, write and read operations will be
slower than with replicated pools due to the CPU overhead of erasure coding on
the Ceph cluster. The exact impact depends on the Ceph hardware and the erasure
coding profile used (k+m values).&lt;/p&gt;
&lt;p&gt;When &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;rbd_store_data_pool&lt;/span&gt;&lt;/code&gt; is not configured (the default), there is no
performance 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;New option &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;rbd_store_data_pool&lt;/span&gt;&lt;/code&gt; to specify the erasure-coded pool for image
data. When not configured, behavior is unchanged.&lt;/p&gt;
&lt;p&gt;Deployers need to create and configure erasure-coded pools on their Ceph
cluster before enabling this feature. Specifically:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Create an erasure-coded pool for image data (e.g., &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;images_data&lt;/span&gt;&lt;/code&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create a replicated pool for image metadata (e.g., &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;images&lt;/span&gt;&lt;/code&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Set &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;allow_ec_overwrites&lt;/span&gt; &lt;span class="pre"&gt;true&lt;/span&gt;&lt;/code&gt; on the erasure-coded pool (required for
librbd to function correctly with the two-pool model)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Ensure the Ceph cluster has sufficient CPU resources to handle erasure coding
overhead.&lt;/p&gt;
&lt;p&gt;Can be enabled without service interruption. Existing images continue to work
from their current pools.&lt;/p&gt;
&lt;p&gt;Note that when &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;rbd_store_data_pool&lt;/span&gt;&lt;/code&gt; is enabled, the replicated pool will
contain both legacy images (with all data) and new images (metadata only). While
this mixing is supported, it is recommended to use separate pools for clean
separation (see “Proposed change” section for details).&lt;/p&gt;
&lt;div class="admonition warning"&gt;
&lt;p class="admonition-title"&gt;Warning&lt;/p&gt;
&lt;p&gt;Do not enable erasure-coded pools in Glance if Nova or Cinder share the
same RBD pool as Glance. Erasure-coded pools use a two-pool model where
image metadata is stored in the replicated pool (rbd_store_pool) and image
data is stored in the erasure-coded pool (rbd_store_data_pool). If Nova or
Cinder are configured to use the same pool as Glance’s metadata pool, they
will not be able to properly access or create resources because they do not
support the two-pool model. This will cause failures when Nova tries to
boot instances from images stored in erasure-coded pools, or when Cinder
tries to create volumes from such images.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;May want to monitor pool usage and Ceph cluster CPU utilization.&lt;/p&gt;
&lt;p&gt;Test write/read performance and timeout behavior before enabling in production.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;The RBD store driver needs to be modified to pass the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;data_pool&lt;/span&gt;&lt;/code&gt; parameter
to librbd when configured.&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;cyril-roelandt or abhishekk&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;pranali-deore (Tempest testing)
whoami-rajat (Cinder changes)&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 the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;rbd_store_data_pool&lt;/span&gt;&lt;/code&gt; configuration option to glance_store&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Modify the RBD driver to pass the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;data_pool&lt;/span&gt;&lt;/code&gt; parameter to librbd’s
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;create()&lt;/span&gt;&lt;/code&gt; method when creating images&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update devstack-ceph-plugin to create erasure-coded pools for testing&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Coordinate with Cinder and Nova teams - they may need similar changes to
their RBD configuration to work with images stored in erasure-coded pools&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add tests for the two-pool scenario&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update documentation with configuration examples and performance guidance&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Note: Migration tools are not part of this 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;Need a Ceph cluster with erasure-coded pools configured.&lt;/p&gt;
&lt;p&gt;Cinder writes volumes and snapshots directly to Ceph. It may need similar
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;data_pool&lt;/span&gt;&lt;/code&gt; support in its &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;rbd_pool&lt;/span&gt;&lt;/code&gt; configuration to create
volumes/snapshots in erasure-coded pools.&lt;/p&gt;
&lt;p&gt;Nova may write instance snapshots directly to Ceph pools. It may need similar
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;data_pool&lt;/span&gt;&lt;/code&gt; support in its &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;libvirt.images_rbd_pool&lt;/span&gt;&lt;/code&gt; configuration.&lt;/p&gt;
&lt;p&gt;The devstack-ceph-plugin needs updates to create erasure-coded pools for
testing.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Test the two-pool configuration and error scenarios with unit tests.&lt;/p&gt;
&lt;p&gt;Add tempest tests after devstack-ceph plugin supports creating
erasure-coded pools.&lt;/p&gt;
&lt;p&gt;The devstack-ceph-plugin needs to be updated to:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Create the erasure-coded pool (e.g., &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;images_data&lt;/span&gt;&lt;/code&gt;) with the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;erasure&lt;/span&gt;&lt;/code&gt;
pool type&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create the replicated pool (e.g., &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;images&lt;/span&gt;&lt;/code&gt;) for metadata&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Set &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;allow_ec_overwrites&lt;/span&gt; &lt;span class="pre"&gt;true&lt;/span&gt;&lt;/code&gt; on the erasure-coded pool&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Without the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;allow_ec_overwrites&lt;/span&gt;&lt;/code&gt; setting, image creation operations will
fail during testing, as verified in testing with Ceph Tentacle release.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Document the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;rbd_store_data_pool&lt;/span&gt;&lt;/code&gt; option, performance considerations, and
when to use erasure-coded pools.&lt;/p&gt;
&lt;p&gt;Include how to set up Ceph erasure-coded pools and enable the feature in
Glance.&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://review.opendev.org/c/openstack/glance-specs/+/863110"&gt;Existing Ceph EC Pools Specification&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://docs.ceph.com/en/latest/rados/operations/erasure-code/"&gt;Ceph Erasure Coding&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://docs.ceph.com/en/latest/rados/operations/erasure-code-profile/"&gt;Ceph Erasure Code Profiles&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
</description><pubDate>Tue, 30 Sep 2025 00:00:00 </pubDate></item><item><title>2026.1 Project Priorities</title><link>http://specs.openstack.org/openstack/glance-specs/priorities/2026.1-priorities.html</link><description>
&lt;span id="priorities"/&gt;
&lt;p&gt;TODO(glance-ptl): fill this in after the PTG&lt;/p&gt;
</description><pubDate>Thu, 28 Aug 2025 00:00:00 </pubDate></item><item><title>Make provision to set image size on upload</title><link>http://specs.openstack.org/openstack/glance-specs/specs/2025.2/approved/glance/set-size-on-upload.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/glance/+spec/set-size-on-upload"&gt;https://blueprints.launchpad.net/glance/+spec/set-size-on-upload&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Historically, the python-glanceclient included the option to specify a
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;--size&lt;/span&gt;&lt;/code&gt; parameter for the image-upload and image-stage commands. However,
this feature is currently unused and is retained in the codebase solely
for backward compatibility. Even if a user provides this option when
executing the aforementioned commands, it is not forwarded to the Glance API.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;As the python-glanceclient uploads image data without requiring a prior
specification of the image size, it functions as intended. However, this can
lead to complications when Glance utilizes Cinder, RBD, or S3 as its backend.
Since Glance does not have the data size beforehand, it conducts an iterative
“resize-before-write” process, gradually expanding the Cinder volume by 1
GB at a time until all image data is received. This approach poses a challenge
because the Cinder volume needs to be detached and reattached during each
iteration, which can significantly slow down the process.&lt;/p&gt;
&lt;p&gt;The same issue arises when using Ceph (RBD) as the backend, where a
similar “resize-before-write” operation occurs, resulting in time-consuming
operations.&lt;/p&gt;
&lt;p&gt;If Glance is configured to use S3 as a backend, the multipart upload feature
cannot be utilized because the image size is unknown in advance.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;We propose to enable the use of the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;--size&lt;/span&gt;&lt;/code&gt; option for the image-upload and
image-stage commands, as well as to add this option to the image-create
command. The image size will be calculated automatically if a file-like object
is detected during the upload or staging operations. Otherwise, users can
specify the image size via the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;--size&lt;/span&gt;&lt;/code&gt; command-line option. If the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;--size&lt;/span&gt;&lt;/code&gt; option is provided, we will not calculate the image size internally,
and the user-specified size will be sent directly to the Glance API. We will
introduce a new request header &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;x-openstack-image-size&lt;/span&gt;&lt;/code&gt; which will be
passed to API.&lt;/p&gt;
&lt;p&gt;On the API side, we will read the size passed from glanceclient or any
request source via header &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;x-openstack-image-size&lt;/span&gt;&lt;/code&gt; and pass it to the
designated storage backend. This approach will help prevent resize-on-write
operations for Cinder and RBD backends and enable the use of the multipart
upload feature for the S3 backend. Each backend of glance_store will
verify the size during the data pipeline whether the total data size
exceeds the user-specified limit. If the size exceeds the allowed limit,
the upload will be rejected, the data will be removed from the backend,
and an appropriate error message will be returned to the user. Additionally,
at the end of the process, we will compare the actual image size to the
size provided by the user. If there is any mismatch in actual and expected
size, the data will be deleted from the backend, the upload rejected, and
a warning will be logged, consistent with existing checks for image disk
format and hash.&lt;/p&gt;
&lt;p&gt;If the image size is not included in the request header, we will have no option
but to allow the storage backends to perform resize-on-write operations or
to utilize the single-part upload feature for the S3 backend.&lt;/p&gt;
&lt;p&gt;For asynchronous operations (import APIs), such as the glance-direct and
web-download import methods, we already gather data in a local staging area
before transferring it to the backend. We will ensure that the image size is
set before starting the import operation to avoid these resize operations.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;The Python Requests library also facilitates streaming uploads by sending
data in chunks with a “Content-Length: &amp;lt;file size&amp;gt;” header, rather than
using “Transfer-Encoding: chunked.” This approach avoids chunked transfer,
which we should steer clear of, as it is a more stable method for long
transfers. Since the development of the glanceclient library is currently
at a standstill, we should avoid introducing changes that could lead to
instability.&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 PUT /v2/images/{image_id}/file and PUT /v2/images/{image_id}/stage
APIs will be modified to recognize the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;x-openstack-image-size&lt;/span&gt;&lt;/code&gt; header.&lt;/p&gt;
&lt;p&gt;HTTP 400 response will be returned if user provided size does not matches
with actual image size.&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 can provide the image size in advance if they are aware of it.&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 improve the upload/import process for cinder, ceph (rbd) and s3 backend
of glance.&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;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;abhishekk&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;abhishekk&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 command line option &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;--size&lt;/span&gt;&lt;/code&gt; to image-create command&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Calculate file size if file like object is provided&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Make sure upload and stage commands passes size to API as request header&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Make similar provision in openstack client and sdk&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;At Glance side read the size form request header and pass it to backend&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Then compare provided size with actual size&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Make sure image size is set before import operation starts&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Required functional, unit and tempest tests&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Document new behavior&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://bugs.launchpad.net/glance-store/+bug/2110185"&gt;https://bugs.launchpad.net/glance-store/+bug/2110185&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;Required unit, functional and 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;Document the use of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;--size&lt;/span&gt;&lt;/code&gt; command line option and new request header
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;x-openstack-image-size&lt;/span&gt;&lt;/code&gt; at glance side&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://requests.readthedocs.io/en/latest/user/advanced/#chunk-encoded-requests"&gt;https://requests.readthedocs.io/en/latest/user/advanced/#chunk-encoded-requests&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://requests.readthedocs.io/en/latest/user/advanced/#streaming-uploads"&gt;https://requests.readthedocs.io/en/latest/user/advanced/#streaming-uploads&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
</description><pubDate>Wed, 16 Apr 2025 00:00:00 </pubDate></item><item><title>2025.2 Project Priorities</title><link>http://specs.openstack.org/openstack/glance-specs/priorities/2025.2-priorities.html</link><description>
&lt;span id="priorities"/&gt;
&lt;p&gt;TODO(glance-ptl): fill this in after the PTG&lt;/p&gt;
</description><pubDate>Fri, 21 Mar 2025 00:00:00 </pubDate></item><item><title>Add new import method to support downloading image from another glance/region</title><link>http://specs.openstack.org/openstack/glance-specs/specs/zed/approved/glance/glance-download-import.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/glance/+spec/glance-download-import"&gt;https://blueprints.launchpad.net/glance/+spec/glance-download-import&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This spec describe a new import method called glance-download that implements a
glance to glance download in a multi-region cloud with a federated Keystone.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;When dealing with a multi-region cloud it often appears that operators or
customers need to copy images from a region to another, for example:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Copy all your public images between your regions (operator)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Copy instance snapshot in another region to have a backup (user)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Build your base application image from a factory in one region, then
propagate it to multiple regions (user)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We can’t rely on the “copy-image” import method to copy an image from a
backend to another because it requires the same glance endpoint in the same
region which is not our use-case here.&lt;/p&gt;
&lt;p&gt;The only way we have to do it now is to locally download the image data and
upload it elsewhere, which requires some orchestration, and is a huge disk
space and bandwidth loss.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Implement an internal plugin called glance-download based on the existing
internal plugin web-download that will import an image stored on a remote
glance. The web-download workflow will remain unchanged, the only difference
is to retrieve the downloadable data from an other glance endpoint instead of
from an arbitrary URL.&lt;/p&gt;
&lt;p&gt;We should note several things:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;To authenticate on the remote glance we propose to use the context token
of the call, so it will require a federated Keystone environment between
the two Glance.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The creation of the image must be handled by the end user as for the
web-download plugin meaning that it is the responsibility of the user to
take care of disk format, container format and metadata of the newly
created image.
If necessary, the plugin will update the container_format and disk_format
to match what is set on source glance.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The plugin will come with an extra task in the taskflow that will be in
charge of setting the container_format and disk_format to be the same as it
is on the source glance. It will also copy some extra properties defined in
the extra_properties_prefixes option of glance_download_properties section.
The default extra_properties_prefixes values are ‘hw_’, ‘trait:’, ‘os_distro’,
‘os_secure_boot’ and ‘os_type’ which are needed to ensure an instance can boot
on the image. An operator will be able to remove or add other extra
properties by modifying this configuration variable.
This extra_properties_prefixes is a list of prefixes, meaning that all the
metadata that are starting with a prefix belonging to that list will be
copied.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight-ini notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="k"&gt;[glance_download_properties]&lt;/span&gt;
&lt;span class="na"&gt;extra_properties_prefixes&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;[&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="na"&gt;hw_,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="na"&gt;trait&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="s"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="na"&gt;os_distro,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="na"&gt;os_secure_boot,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="na"&gt;os_type&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="na"&gt;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;If metadata injection is configured on the target glance it will override
the metadata as the injection is run after the import.&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 could imagine a take out alternative where the owner of the image in the
source cloud generates a limited-use tokenized URL that allows access to the
image without any keystone auth. Such solution is more risky as we do not
have any authentication mechanism to access the remote image. It will also
require rewriting the code as there is no existing source.&lt;/p&gt;
&lt;p&gt;This would also require developing a mechanism to manage creation and
expiration of the temporary urls which would result in a more complex solution
that requires more time to develop, document and test.&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;Modification of existing API resource&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Resource &lt;strong&gt;/v2/images/&amp;lt;image id&amp;gt;/import&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Method: &lt;strong&gt;POST&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;dl class="simple"&gt;
&lt;dt&gt;Common response code:&lt;/dt&gt;&lt;dd&gt;&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;201&lt;/em&gt;: import job queued&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;400&lt;/em&gt;: bad request with details&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;401&lt;/em&gt;: Unauthorized&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;403&lt;/em&gt;: Forbidden&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;JSON body definition&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight-javascript notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="s2"&gt;"method"&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;"name"&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;"description"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Name of the method used, here is glance-download"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"string"&lt;/span&gt;
&lt;span class="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;"glance_image_id"&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;"description"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"The image id to download on remote glance"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"string"&lt;/span&gt;
&lt;span class="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;"glance_region"&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;"description"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"The region name of remote glance"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"string"&lt;/span&gt;
&lt;span class="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;"glance_service_interface"&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;"decription"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"The interface of remote glance, default to 'public'"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"string"&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;Example:&lt;/p&gt;
&lt;div class="highlight-javascript notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"method"&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;"name"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"glance-download"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="s2"&gt;"glance_image_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;"02ea04ba-72b3-4687-810d-8ba10c991a97"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="s2"&gt;"glance_region"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"REGION1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="s2"&gt;"glance_service_interface"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"admin"&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;We use the token of the request to authenticate on remote glance. As we are in
multi-region context with a federated keystone, there is no security impact.&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 have a new import mechanism open to them, after updating their
client&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;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;alistarle&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&gt;
&lt;li&gt;&lt;p&gt;glance:&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Create a base download class that will be inherited by web-download and
glance-download&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Patch the web-download class to inherit from base download class&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Write the glance-download class&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Patch the api image import to support the glance-download method&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add in task flow a class in charge of:&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;setting the correct container_format and disk_format&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;copying the metadatas defined in extra_properties option of the
glance_download_properties section. Default list must be
[‘hw_’, ‘trait:’, ‘os_distro’, ‘os_secure_boot’, ‘os_type’]&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The class has to be added to taskflow as a normal task to be reusable if
needed. We only have to check for input parameters to know if it can be
run or not.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add the glance-download internal plugin in setup&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;write unit/functional tests&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;update documentation&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;glance and openstack client&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;add support for glance-download method&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;update documentation&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;&lt;/blockquote&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 tests in Glance&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Tempest tests. Testing glance-download plugin with the g-api-r separate
endpoint looks good even if it shares the same database to validate the
workflow.&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 documentation needs to be updated to identify this new import method&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://review.opendev.org/c/openstack/glance/+/840318"&gt;https://review.opendev.org/c/openstack/glance/+/840318&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
</description><pubDate>Tue, 14 Jan 2025 00:00:00 </pubDate></item><item><title>Implement Calculate Hash API</title><link>http://specs.openstack.org/openstack/glance-specs/specs/2025.1/approved/glance/calculate-hash-for-active-images.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/glance/+spec/calculate-hash-api"&gt;https://blueprints.launchpad.net/glance/+spec/calculate-hash-api&lt;/a&gt;&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;There will be 2 cases when image will be in &lt;cite&gt;active&lt;/cite&gt; state without
os_hash_value and checksum,&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;During the implementation of New Add Location 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; it’s been
noticed that some images will remain in ‘active’ state without
checksum and os_hash_value if the hash calculation is failed after
adding the location to the image.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Some legacy images which are created by consumers like
instance snapshot or volume snapshot(image created by upload volume
operation when glance backend is cinder) may also not have checksum,
os_hash_value and os_hash_algo set.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Currently there is no other way to calculate hash for such images.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;We are planning to add a separate new admin-only api to calculate the
os_hash_value and checksum for the image which are in &lt;cite&gt;active&lt;/cite&gt; state.&lt;/p&gt;
&lt;p&gt;This API will be handled as follows:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Since hash calculation will be a long running operation, it will be
executed in the background in the async task by setting the value of
&lt;cite&gt;os_hash_algo&lt;/cite&gt; before caclulation process starts.
If hash calculation fails, retry mechanism for hash calculation will
be added by using existing configuration option &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;http_retries&lt;/span&gt;&lt;/code&gt; for
maximum retries. If after all the retries, the hash calculation still
fails we will not update the hash and checksum values and image will
stay in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;active&lt;/span&gt;&lt;/code&gt; state and &lt;cite&gt;os_hash_algo&lt;/cite&gt; will be reverted back to
&lt;cite&gt;None&lt;/cite&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Incase delete image has been attempted during hash calculation of that
image, there are different responses from stores while reading the data,&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;RBD throws &lt;cite&gt;ImageNotFound&lt;/cite&gt; during data read but deletes the data from
backend and image remains in active state even though delete call fails
with &lt;cite&gt;InUseByStore&lt;/cite&gt; error. There is a bug reported for this issue &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;.
In this case as a workaround hash calculation will be marked as failed
with proper log message and the image will be marked as &lt;cite&gt;deleted&lt;/cite&gt; if
it’s not marked as &lt;cite&gt;deleted&lt;/cite&gt; by delete api.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Filesystem backend throws &lt;cite&gt;NotFound&lt;/cite&gt; since delete operation is
successful.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Swift allows image deletion during data reading or image-download.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Cinder backend does not allow to delete the image since while reading
data or downloading the image from volume, volume will be in-use state.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Since this is async API call, admin can use API /v2/images/{id}/tasks
to check the progress of the task.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;We will introduce a new admin-only policy &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;calculate_hash&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 can have a separate new command under glance-manage to run from cron.&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;strong&gt;New API&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Calculate Hash&lt;/p&gt;
&lt;p&gt;This spec proposes the following new endpoint:&lt;/p&gt;
&lt;p&gt;POST /v2/images/{image_id}/hash&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;JSON 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;"os_hash_algo"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"sha512"&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;Response
- Accepted - 202&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;dl class="simple"&gt;
&lt;dt&gt;Error - 409 (if image is not in ACTIVE state),&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;403 (Forbidden for normal user)
400 (BadRequest if invalid os_hash_algo passed)
404 (Image ID does not exist)&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/li&gt;
&lt;/ul&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;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;Changes in glanceclient and openstackclient will be required to expose
for admin users only.&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;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;pranali-deore&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 the API with unit/functional tests&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Document the API in api-ref&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Write a tempest test to check these API&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Implement support in OSC/SDK&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Implement support in glanceclient&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add documentation for behaviour of new 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;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Unit and functional tests in Glance. Tempest tests against the same.&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 documentation needs to be updated with the new API extension and usage.&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;&lt;a class="reference external" href="https://bugs.launchpad.net/glance/+bug/2045769"&gt;https://bugs.launchpad.net/glance/+bug/2045769&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;/aside&gt;
&lt;/section&gt;
</description><pubDate>Mon, 09 Dec 2024 00:00:00 </pubDate></item><item><title>API for cleaning and pruning cache</title><link>http://specs.openstack.org/openstack/glance-specs/specs/2025.1/approved/glance/clean-prune-cache-api.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/glance/+spec/clean-prune-cache-api"&gt;https://blueprints.launchpad.net/glance/+spec/clean-prune-cache-api&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;New API calls for cleaning and pruning image cache directories.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;As of today if image caching is enabled in the deployment, then deployer
need to configure glance-cache-cleaner and glance-cache-pruner as
cron jobs so that invalid image cache files gets cleaned periodically
and if cache directory oversized then old cache files gets deleted
automatically. This is an overhead for the deployer to make sure
cron jobs are configured and running effectively.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;We are propsing to deprecate &lt;cite&gt;glance-cache-cleaner&lt;/cite&gt;, &lt;cite&gt;glance-cache-pruner&lt;/cite&gt;
and &lt;cite&gt;glance-cache-prefetcher&lt;/cite&gt; command line tools in this cycle and remove
them in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;G&lt;/span&gt;&lt;/code&gt; developemnt cycle. As we already have an API call
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/v2/cache/{image_id}&lt;/span&gt;&lt;/code&gt; to cache an image, similarly we will add two
new API POST calls &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/v2/cache/clean&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/v2/cache/prune&lt;/span&gt;&lt;/code&gt; which will
do the job of pruning and cleaning for us. These two APIs will be admin
only and non-admin user will be restricted to use it.&lt;/p&gt;
&lt;p&gt;We will introduce two new policies &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cache_clean&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cache_prune&lt;/span&gt;&lt;/code&gt;
default to used by &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;admin&lt;/span&gt;&lt;/code&gt; for restricting the use of these new
APIs.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Instead of adding new API calls we can move existing code to reuse
it as a periodic call under glance API service. This will need
to introduce two additional configuration parameters to introduce
interval of periodic calls.&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 spec propose the following new APIs:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Clean invalid cached images&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;[New API] Clean invalid cached images&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Clean invalid cached 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;POST&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;v2&lt;/span&gt;&lt;span class="o"&gt;/&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;clean&lt;/span&gt;
&lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Response codes:
* 200 – Upon authorization and successful request.
* 403 – Permission denied&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Prune image cache directory&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;[New API] Prune image cache directory&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Prune image cache directory:&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;POST&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;v2&lt;/span&gt;&lt;span class="o"&gt;/&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;prune&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="n"&gt;response&lt;/span&gt; &lt;span class="n"&gt;body&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;block&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;

    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="s2"&gt;"total_files_pruned"&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;total_files_pruned&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;"total_bytes_pruned"&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;total_bytes_pruned&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;Response codes:
* 200 – Upon authorization and successful request.
* 403 – Permission denied&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 proposed change section new policies will be enforced
to avoid security breach.&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 glance client and openstack client should be updated, with new commands:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;glance cache-clean&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;glance cache-prune&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;openstack cache clean&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;openstack cache-prune&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;Deployer needs to stop using &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance-cache-cleaner&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance-cache-pruner&lt;/span&gt;&lt;/code&gt;
and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance-cache-prefetcher&lt;/span&gt;&lt;/code&gt; command line tools in the environment.&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;abhishekk&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 new API calls&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Enforce new policy rules&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Documentation&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Testing&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;New tempest test to cover this scenario&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 API documentation needs to be updated&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Need to update Cache documentation as well with new commands&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://docs.openstack.org/glance/victoria/admin/cache.html"&gt;https://docs.openstack.org/glance/victoria/admin/cache.html&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
</description><pubDate>Tue, 05 Nov 2024 00:00:00 </pubDate></item><item><title>New API to list nodes where Image is cached</title><link>http://specs.openstack.org/openstack/glance-specs/specs/2025.1/approved/glance/list-nodes-image-cached.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/glance/+spec/list-nodes-image-cached"&gt;https://blueprints.launchpad.net/glance/+spec/list-nodes-image-cached&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Deployer would like to see on which glance worker nodes an image is
cached in one API call.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;As of today if you have configured multiple glance nodes and you need
to see whether image is cached on particular node then you need to
query to that particular glance node or query each glance node for the
same.&lt;/p&gt;
&lt;p&gt;Use case, In a DCN environment you want to see whether that particular
edge node has image cached or not.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Glance now by default uses a centralized database for cache, which allows
us to have access to all cached images across glance nodes. We are
adding a new admin only API which will accept &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;image_id&lt;/span&gt;&lt;/code&gt; as an input
parameter and will return us the direct URL of all  glance nodes where
that particular image is cached.&lt;/p&gt;
&lt;p&gt;We will also introduce a new policy &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;list_cached_nodes&lt;/span&gt;&lt;/code&gt; so that users
with appropriate permissions can perform this operation.&lt;/p&gt;
&lt;p&gt;If caching is not enabled in deployment or deployment is not using
centralized database for caching then this API will return HTTP
409 Conflict response to the user.&lt;/p&gt;
&lt;p&gt;In the future we can use this API from consumers like nova or cinder
in such a way that they can directly send the API request to
particular glance node where the image is cached.&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;This spec propose the following new API:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;New API&lt;/strong&gt;&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;List nodes where image is cached&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Common Response Codes&lt;/strong&gt;&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Accepted: &lt;cite&gt;200 Accepted&lt;/cite&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Forbidden: &lt;cite&gt;403 Forbidden&lt;/cite&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Conflict: &lt;cite&gt;409 Conflict&lt;/cite&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Not Found: &lt;cite&gt;404 Not Found&lt;/cite&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;[New API] List nodes where image is cached&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;List nodes:&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&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;v2&lt;/span&gt;&lt;span class="o"&gt;/&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;nodes&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;image_id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;"cached_nodes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="n"&gt;node_1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;60999&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="n"&gt;node_2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;60999&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="n"&gt;node_5&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;60999&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;As described in proposed change section new policy will be enforced
to avoid security breach.&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 glance client and openstack client should be updated, with new commands:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;glance cache-nodes-list &amp;lt;image_id&amp;gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;openstack cache nodes list &amp;lt;image_id&amp;gt;&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&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;abhishekk&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 new API call&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Enforce new policy rule&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Documentation&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Testing&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;New tempest test to cover this scenario&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 API documentation will need to be updated&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Need to update Cache documentation as well with new commands&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://docs.openstack.org/glance/victoria/admin/cache.html"&gt;https://docs.openstack.org/glance/victoria/admin/cache.html&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
</description><pubDate>Wed, 30 Oct 2024 00:00:00 </pubDate></item><item><title>Sharing Images using the Image API v2</title><link>http://specs.openstack.org/openstack/glance-specs/specs/api/v2/sharing-image-api-v2.html</link><description>

&lt;p&gt;The OpenStack Image Service API v2 allows users to share images with
each other in the following ways:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;An image can be shared with specific other users of the cloud.  This mode of
sharing has been available since version 2.1 of the API.  Thus when we speak
about “shared” images in this document, we’re talking about this kind of
sharing.  It’s described in the section &lt;a class="reference internal" href="#one-one-sharing"&gt;&lt;span class="std std-ref"&gt;Sharing Images with Particular Users&lt;/span&gt;&lt;/a&gt;, below.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;An image can be shared with all users of the cloud.  This mode of sharing
became available in version 2.5 of the API.  Images shared in this way are
referred to as “community” images because they’re available to the entire
community of users in a cloud (and because we couldn’t think of a better
name).  Community images are discussed below in the section
&lt;a class="reference internal" href="#one-all-sharing"&gt;&lt;span class="std std-ref"&gt;Sharing Images with All Users&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To keep the discussion to follow clear, here’s some terminology that will be
used.&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;producer&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;A user who owns an image that’s going to be shared with other users.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;consumer&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;A user who wants to use an image.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;shared image&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;An image that’s been made accessible to specific other users, as described in
&lt;a class="reference internal" href="#one-one-sharing"&gt;&lt;span class="std std-ref"&gt;Sharing Images with Particular Users&lt;/span&gt;&lt;/a&gt;.  Since version 2.5 of the API, the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;visibility&lt;/span&gt;&lt;/code&gt;
property of such an image is &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;shared&lt;/span&gt;&lt;/code&gt;.  (If you are using a prior version
of the API, the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;visibility&lt;/span&gt;&lt;/code&gt; is &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;private&lt;/span&gt;&lt;/code&gt;.)&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;community image&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;An image that’s been made accessible to all users in a cloud, as described in
&lt;a class="reference internal" href="#one-all-sharing"&gt;&lt;span class="std std-ref"&gt;Sharing Images with All Users&lt;/span&gt;&lt;/a&gt;.  Since version 2.5 of the API, the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;visibility&lt;/span&gt;&lt;/code&gt;
property of such an image is &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;community&lt;/span&gt;&lt;/code&gt;.  (This type of image is not
available prior to version 2.5.)&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;section id="sharing-images-with-particular-users"&gt;
&lt;span id="one-one-sharing"/&gt;&lt;h2&gt;Sharing Images with Particular Users&lt;/h2&gt;
&lt;p&gt;Let the “producer” be the owner of image 71c675ab-d94f-49cd-a114-e12490b328d9,
and let the “consumer” be a user who would like to boot an instance from that
image.&lt;/p&gt;
&lt;p&gt;The producer can share the image with the consumer by making the
consumer a &lt;strong&gt;member&lt;/strong&gt; of that image.&lt;/p&gt;
&lt;p&gt;To prevent spamming, the consumer must &lt;strong&gt;accept&lt;/strong&gt; the image before it
will be included in the consumer’s image list.&lt;/p&gt;
&lt;p&gt;The consumer can still boot from the image, however, if the consumer
knows the image ID.&lt;/p&gt;
&lt;p&gt;In summary:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;The image producer may add or remove image members, but may not
modify the member status of an image member.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;An image consumer may change his or her member status, but may not
add or remove him or herself as an image member.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A consumer may boot an instance from a shared image regardless of
whether he/she has “accepted” the image.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;section id="how-do-you-identify-a-producer-or-consumer"&gt;
&lt;span id="owner-is-tenant"/&gt;&lt;h3&gt;How do you identify a producer or consumer?&lt;/h3&gt;
&lt;p&gt;As an image producer, you know who you are, but how do you identify a potential
consumer of your image?  As an image consumer, how do you refer to yourself,
and if you want to consume community images, what do you use to identify the
producer of an image you’re looking for?  These are actually complicated
questions, because Glance allows an operator to decide whether images will be
owned by &lt;em&gt;projects&lt;/em&gt; or whether they will be owned by &lt;em&gt;users&lt;/em&gt;.  The default is
that images are owned by &lt;em&gt;projects&lt;/em&gt;, so that’s what you’ll see most often.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;Sometimes you’ll see a &lt;em&gt;project&lt;/em&gt; referred to as a &lt;em&gt;tenant&lt;/em&gt;.  A “tenant”
was the original OpenStack term for a project.  It’s been phased out
because the word “tenant” in English is often used to refer to a person,
and this makes it easy to confuse a tenant with an &lt;em&gt;owner&lt;/em&gt;.  But when
documentation or members of the OpenStack community refer to a “tenant”
or “tenant ID”, they really mean “project” or “project ID”.&lt;/p&gt;
&lt;/div&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;In clouds where an image owner is a &lt;em&gt;project&lt;/em&gt;, the way to identify an image
producer or consumer is to use their &lt;strong&gt;project ID&lt;/strong&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;In such a cloud, images are shared project-to-project.  Thus &lt;em&gt;all&lt;/em&gt; users
within the consuming project will have access to the image.  In such a
cloud, there is no way to share an image with only a single user.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In clouds where an image owner is a &lt;em&gt;user&lt;/em&gt;, an image producer or consumer is
identified by their &lt;strong&gt;user ID&lt;/strong&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;In such a cloud, images are shared user-to-user.  Thus only the specific
users who are image members have access to the image.  This extends to
other users in the same project as the user owning the image.  Even though
they are in the same project, they must explictly be made members in order
to have access to the image.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Note that image producers or consumers do &lt;em&gt;not&lt;/em&gt; get to decide which identifier
to use.  This is decided for the entire cloud by the cloud administrator.
Consult your cloud’s local documentation to find out which applies in a
particular cloud you’re using.  (As mentioned above, the default is that images
are owned by &lt;em&gt;projects&lt;/em&gt;, so if the local documentation doesn’t say anything,
it’s a good bet that the default is being used.)&lt;/p&gt;
&lt;/section&gt;
&lt;section id="producer-consumer-communication"&gt;
&lt;h3&gt;Producer-Consumer Communication&lt;/h3&gt;
&lt;p&gt;No provision is made in this API for producer-consumer communication.
All such communication must be done independently of the API.&lt;/p&gt;
&lt;p&gt;An example workflow for shared images is:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;The producer posts the availability of specific images on a public
website.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A potential consumer provides the producer with his/her appropriate
identifier and email address.  (See &lt;a class="reference internal" href="#owner-is-tenant"&gt;&lt;span class="std std-ref"&gt;How do you identify a producer or consumer?&lt;/span&gt;&lt;/a&gt; if you’re
not sure what the appropriate identifier is.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The producer uses the Images v2 API to share the image with the
consumer.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The producer notifies the consumer via email that the image has been
shared and what its UUID is.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If the consumer wishes the shared image to appear in his/her image list, the
Images v2 API is used to change the image status to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;accepted&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If the consumer subsequently wishes to hide the image, the Images v2
API may be used to change the member status to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;rejected&lt;/span&gt;&lt;/code&gt;. If the
consumer wishes to hide the image, but is open to the possibility of
being reminded by the producer that the image is available, the
Images v2 API may be used to change the member status to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;pending&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Note that as far as this API is concerned, the member status has only
two effects:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;If the member status is &lt;em&gt;not&lt;/em&gt; &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;accepted&lt;/span&gt;&lt;/code&gt;, the image will not appear
in the consumer’s default image list.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The consumer’s image list may be filtered by status to see shared
images in the various member statuses. For example, the consumer can
discover images that have been shared with him or her by filtering on
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;visibility=shared&amp;amp;member_status=pending&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="image-sharing-schemas"&gt;
&lt;h3&gt;Image Sharing Schemas&lt;/h3&gt;
&lt;p&gt;JSON schema documents are provided at the URIs listed below.&lt;/p&gt;
&lt;p&gt;Recall that the schemas contained in this document are only examples and
should not be used to validate your requests.&lt;/p&gt;
&lt;section id="get-image-member-schema"&gt;
&lt;h4&gt;Get Image Member Schema&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;GET /v2/schemas/member&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;There is no request body.&lt;/p&gt;
&lt;p&gt;Response body contains a json-schema document representing an image
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;member&lt;/span&gt;&lt;/code&gt; entity.&lt;/p&gt;
&lt;p&gt;The response from the API should be considered authoritative. The schema
is reproduced here solely for your convenience:&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;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"member"&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;"created_at"&lt;/span&gt;&lt;span class="p"&gt;:&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;"Date and time of image member creation"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"string"&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="s2"&gt;"image_id"&lt;/span&gt;&lt;span class="p"&gt;:&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;"An identifier for the image"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"pattern"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"^([0-9a-fA-F])&lt;/span&gt;&lt;span class="si"&gt;{8}&lt;/span&gt;&lt;span class="s2"&gt;-([0-9a-fA-F])&lt;/span&gt;&lt;span class="si"&gt;{4}&lt;/span&gt;&lt;span class="s2"&gt;-([0-9a-fA-F])&lt;/span&gt;&lt;span class="si"&gt;{4}&lt;/span&gt;&lt;span class="s2"&gt;-([0-9a-fA-F])&lt;/span&gt;&lt;span class="si"&gt;{4}&lt;/span&gt;&lt;span class="s2"&gt;-([0-9a-fA-F])&lt;/span&gt;&lt;span class="si"&gt;{12}&lt;/span&gt;&lt;span class="s2"&gt;$"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"string"&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="s2"&gt;"member_id"&lt;/span&gt;&lt;span class="p"&gt;:&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;"An identifier for the image member"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"string"&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="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;"The status of this image member"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"enum"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
                &lt;span class="s2"&gt;"pending"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s2"&gt;"accepted"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s2"&gt;"rejected"&lt;/span&gt;
            &lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"string"&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="s2"&gt;"updated_at"&lt;/span&gt;&lt;span class="p"&gt;:&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;"Date and time of last modification of image member"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"string"&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="s2"&gt;"schema"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"string"&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="get-image-members-schema"&gt;
&lt;h4&gt;Get Image Members Schema&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;GET /v2/schemas/members&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;There is no request body.&lt;/p&gt;
&lt;p&gt;Response body contains a json-schema document representing an image
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;members&lt;/span&gt;&lt;/code&gt; entity (a container of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;member&lt;/span&gt;&lt;/code&gt; entities).&lt;/p&gt;
&lt;p&gt;The response from the API should be considered authoritative. The schema
is reproduced here solely for your convenience:&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;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"members"&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;"members"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="s2"&gt;"items"&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;"member"&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;"created_at"&lt;/span&gt;&lt;span class="p"&gt;:&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;"Date and time of image member creation"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"string"&lt;/span&gt;
                    &lt;span class="p"&gt;},&lt;/span&gt;
                    &lt;span class="s2"&gt;"image_id"&lt;/span&gt;&lt;span class="p"&gt;:&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;"An identifier for the image"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="s2"&gt;"pattern"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"^([0-9a-fA-F])&lt;/span&gt;&lt;span class="si"&gt;{8}&lt;/span&gt;&lt;span class="s2"&gt;-([0-9a-fA-F])&lt;/span&gt;&lt;span class="si"&gt;{4}&lt;/span&gt;&lt;span class="s2"&gt;-([0-9a-fA-F])&lt;/span&gt;&lt;span class="si"&gt;{4}&lt;/span&gt;&lt;span class="s2"&gt;-([0-9a-fA-F])&lt;/span&gt;&lt;span class="si"&gt;{4}&lt;/span&gt;&lt;span class="s2"&gt;-([0-9a-fA-F])&lt;/span&gt;&lt;span class="si"&gt;{12}&lt;/span&gt;&lt;span class="s2"&gt;$"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"string"&lt;/span&gt;
                    &lt;span class="p"&gt;},&lt;/span&gt;
                    &lt;span class="s2"&gt;"member_id"&lt;/span&gt;&lt;span class="p"&gt;:&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;"An identifier for the image member"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"string"&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="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;"The status of this image member"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="s2"&gt;"enum"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
                            &lt;span class="s2"&gt;"pending"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                            &lt;span class="s2"&gt;"accepted"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                            &lt;span class="s2"&gt;"rejected"&lt;/span&gt;
                        &lt;span class="p"&gt;],&lt;/span&gt;
                        &lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"string"&lt;/span&gt;
                    &lt;span class="p"&gt;},&lt;/span&gt;
                    &lt;span class="s2"&gt;"updated_at"&lt;/span&gt;&lt;span class="p"&gt;:&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;"Date and time of last modification of image member"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"string"&lt;/span&gt;
                    &lt;span class="p"&gt;},&lt;/span&gt;
                    &lt;span class="s2"&gt;"schema"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                        &lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"string"&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;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"array"&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="s2"&gt;"schema"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"string"&lt;/span&gt;
        &lt;span class="p"&gt;}&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="p"&gt;{&lt;/span&gt;
            &lt;span class="s2"&gt;"href"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{schema}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"rel"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"describedby"&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="image-producer-calls"&gt;
&lt;h3&gt;Image Producer Calls&lt;/h3&gt;
&lt;p&gt;The following calls are germane to a user who wishes to act as a
producer of shared images.&lt;/p&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;shared&lt;/span&gt;&lt;/code&gt; value for an image’s &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;visiblity&lt;/span&gt;&lt;/code&gt; property was introduced in
version 2.5 of the Image API.  From version 2.5 on, a necessary condition
for image member calls to succeed is that the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;visibility&lt;/span&gt;&lt;/code&gt; field of the
image referred to in the call has the value &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;shared&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;section id="create-an-image-member"&gt;
&lt;h4&gt;Create an Image Member&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;POST /v2/images/&amp;lt;IMAGE_ID&amp;gt;/members&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The request body must be JSON in the following 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="p"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;"member"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&amp;lt;MEMBER_ID&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;where the MEMBER_ID is the ID of the consumer with whom the image is to
be shared.&lt;/p&gt;
&lt;p&gt;The member status of a newly created image member is &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;pending&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;If the user making the call is not the image owner, the response is HTTP
status code 404.&lt;/p&gt;
&lt;p&gt;The response conforms to the JSON schema available at
&lt;strong&gt;/v2/schemas/member&lt;/strong&gt;, 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="p"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;"created_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"2013-09-19T20:36:53Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"image_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"71c675ab-d94f-49cd-a114-e12490b328d9"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"member_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"8989447062e04a818baf9e073fd04fa7"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"schema"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"/v2/schemas/member"&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;"pending"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"updated_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"2013-09-19T20:36:53Z"&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="delete-an-image-member"&gt;
&lt;h4&gt;Delete an Image Member&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;DELETE /v2/images/&amp;lt;IMAGE_ID&amp;gt;/members/&amp;lt;MEMBER_ID&amp;gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;There is no request body.&lt;/p&gt;
&lt;p&gt;A successful response is 204 (No Content).&lt;/p&gt;
&lt;p&gt;The call returns HTTP status code 404 if MEMBER_ID is not an image
member of the specified image.&lt;/p&gt;
&lt;p&gt;The call returns HTTP status code 404 if the user making the call is not
the image owner.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="image-consumer-calls"&gt;
&lt;h3&gt;Image Consumer Calls&lt;/h3&gt;
&lt;p&gt;The following calls pertain to a user who wishes to act as a consumer of
shared images.&lt;/p&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;shared&lt;/span&gt;&lt;/code&gt; value for an image’s &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;visiblity&lt;/span&gt;&lt;/code&gt; property was introduced in
version 2.5 of the Image API.  From version 2.5 on, a necessary condition
for image member calls to succeed is that the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;visibility&lt;/span&gt;&lt;/code&gt; field of the
image referred to in the call has the value &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;shared&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;section id="update-an-image-member"&gt;
&lt;h4&gt;Update an Image Member&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;PUT /v2/images/&amp;lt;IMAGE_ID&amp;gt;/members/&amp;lt;MEMBER_ID&amp;gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The body of the request is a JSON object specifying the member status to
which the image member should be updated:&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;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&amp;lt;STATUS_VALUE&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;where STATUS_VALUE is one of { &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;pending&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;accepted&lt;/span&gt;&lt;/code&gt;, or
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;rejected&lt;/span&gt;&lt;/code&gt; }.&lt;/p&gt;
&lt;p&gt;The response conforms to the JSON schema available at
&lt;strong&gt;/v2/schemas/member&lt;/strong&gt;, 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="p"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;"created_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"2013-09-20T19:22:19Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"image_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"a96be11e-8536-4910-92cb-de50aa19dfe6"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"member_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"8989447062e04a818baf9e073fd04fa7"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"schema"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"/v2/schemas/member"&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;"accepted"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"updated_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"2013-09-20T20:15:31Z"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;If the call is made by the image owner, the response is HTTP status code
403 (Forbidden).&lt;/p&gt;
&lt;p&gt;If the call is made by a user who is not the image owner and whose
identifier does not match the MEMBER_ID, the response is HTTP status
code 404.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="image-member-status-values"&gt;
&lt;h4&gt;Image Member Status Values&lt;/h4&gt;
&lt;p&gt;There are three image member status 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;pending&lt;/span&gt;&lt;/code&gt;: When a member is created, its status is set to
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;pending&lt;/span&gt;&lt;/code&gt;. The image is not visible in the member’s image-list, but
the member can still boot instances from the image.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;accepted&lt;/span&gt;&lt;/code&gt;: When a member’s status is &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;accepted&lt;/span&gt;&lt;/code&gt;, the image is
visible in the member’s image-list. The member can boot instances
from the image.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;rejected&lt;/span&gt;&lt;/code&gt;: When a member’s status is &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;rejected&lt;/span&gt;&lt;/code&gt;, the member has
decided that he or she does not wish to see the image. The image is
not visible in the member’s image-list, but the member can still boot
instances from the image.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="calls-for-both-producers-and-consumers"&gt;
&lt;h3&gt;Calls for Both Producers and Consumers&lt;/h3&gt;
&lt;p&gt;These calls are applicable to users acting either as producers or
consumers of shared images.&lt;/p&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;shared&lt;/span&gt;&lt;/code&gt; value for an image’s &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;visiblity&lt;/span&gt;&lt;/code&gt; property was introduced in
version 2.5 of the Image API.  From version 2.5 on, a necessary condition
for image member calls to succeed is that the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;visibility&lt;/span&gt;&lt;/code&gt; field of the
image referred to in the call has the value &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;shared&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;section id="show-image-member"&gt;
&lt;h4&gt;Show Image Member&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;GET /v2/images/&amp;lt;IMAGE_ID&amp;gt;/members/&amp;lt;MEMBER_ID&amp;gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The response conforms to the JSON schema available at
&lt;strong&gt;/v2/schemas/member&lt;/strong&gt;, 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="p"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;"created_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"2014-02-20T04:15:17Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"image_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"634985e5-0f2e-488e-bd7c-928d9a8ea82a"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"member_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"46a12bfd09c8459483c03e1b0d71bda8"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"schema"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"/v2/schemas/member"&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;"pending"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"updated_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"2014-02-20T04:15:17Z"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The image owner (the producer) may make this call successfully for each image
member. An image member (a consumer) may make this call successfully only when
MEMBER_ID is the correct identifier for that consumer. For any other
MEMBER_ID, the consumer receives a 404 response.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="list-image-members"&gt;
&lt;h4&gt;List Image Members&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;GET /v2/images/&amp;lt;IMAGE_ID&amp;gt;/members&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The response conforms to the JSON schema available at
&lt;strong&gt;/v2/schemas/members&lt;/strong&gt;, 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="p"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;"members"&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;"created_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"2013-09-20T19:16:53Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"image_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"a96be11e-8536-4910-92cb-de50aa19dfe6"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"member_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"818baf9e073fd04fa78989447062e04a"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"schema"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"/v2/schemas/member"&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;"pending"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"updated_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"2013-09-20T19:16:53Z"&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="s2"&gt;"created_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"2013-09-20T19:22:19Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"image_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"a96be11e-8536-4910-92cb-de50aa19dfe6"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"member_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"8989447062e04a818baf9e073fd04fa7"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"schema"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"/v2/schemas/member"&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;"pending"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"updated_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"2013-09-20T19:22:19Z"&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="s2"&gt;"schema"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"/v2/schemas/members"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;If the call is made by a user with whom the image has been shared, the
member-list will contain &lt;em&gt;only&lt;/em&gt; the information for that user. For
example, if the call is made by consumer 8989447062e04a818baf9e073fd04fa7,
the response 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;"members"&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;"created_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"2013-09-20T19:22:19Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"image_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"a96be11e-8536-4910-92cb-de50aa19dfe6"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"member_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"8989447062e04a818baf9e073fd04fa7"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"schema"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"/v2/schemas/member"&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;"pending"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"updated_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"2013-09-20T19:22:19Z"&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="s2"&gt;"schema"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"/v2/schemas/members"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;If the call is made by a consumer with whom the image is &lt;em&gt;not&lt;/em&gt; shared, the
response is a 404.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="list-shared-images"&gt;
&lt;h4&gt;List Shared Images&lt;/h4&gt;
&lt;p&gt;Shared images are listed as part of the normal image list call. In this
section we emphasize some useful filtering 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;visibility=shared&lt;/span&gt;&lt;/code&gt;: show only images shared with me where my
member status is ‘accepted’&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;visibility=shared&amp;amp;member_status=accepted&lt;/span&gt;&lt;/code&gt;: same as above&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;visibility=shared&amp;amp;member_status=pending&lt;/span&gt;&lt;/code&gt;: show only images shared
with me where my member status is ‘pending’&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;visibility=shared&amp;amp;member_status=rejected&lt;/span&gt;&lt;/code&gt;: show only images shared
with me where my member status is ‘rejected’&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;visibility=shared&amp;amp;member_status=all&lt;/span&gt;&lt;/code&gt;: show all images shared with
me regardless of my member status&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;owner=&amp;lt;OWNER_ID&amp;gt;&lt;/span&gt;&lt;/code&gt;: show only images shared with me by the producer
whose identifier is OWNER_ID&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="sharing-images-with-all-users"&gt;
&lt;span id="one-all-sharing"/&gt;&lt;h2&gt;Sharing Images with All Users&lt;/h2&gt;
&lt;p&gt;Since version 2.5, the Image Service API v2 offers another kind of image
sharing, &lt;em&gt;Community Images&lt;/em&gt;.  A community image is made available to all
users in a cloud without the requirement of creating members on the image.&lt;/p&gt;
&lt;p&gt;A community image is an image whose &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;visibility&lt;/span&gt;&lt;/code&gt; value is &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;community&lt;/span&gt;&lt;/code&gt;.  The
ability to communitize an image may be prohibited or restricted to specific
users at the discretion of the cloud operator.  To make an image a community
image, use the image update call to change the image’s visibility
appropriately.  (See &lt;a class="reference internal" href="image-metadata-api-v2.html#image-update"&gt;&lt;span class="std std-ref"&gt;Update an image&lt;/span&gt;&lt;/a&gt; for more information.)&lt;/p&gt;
&lt;p&gt;Community images do not appear in the default image list of any user other
than the image owner.  In order to discover community images, make the
image-list call with a ‘visibility’ filter:&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;v2/images?visibility=community&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;As with the standard image-list call, other filters may be applied to the
request.  For example, to see the community images supplied by the image
producer identified by &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;931efe8a-0ad7-4610-9116-c199f8807cda&lt;/span&gt;&lt;/code&gt;, the
following call would be made:&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;v2/images?visibility=community&amp;amp;owner=931efe8a-0ad7-4610-9116-c199f8807cda&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;See &lt;a class="reference internal" href="#owner-is-tenant"&gt;&lt;span class="std std-ref"&gt;How do you identify a producer or consumer?&lt;/span&gt;&lt;/a&gt; for information about how to determine
an image producer’s identifier.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Keep in mind that the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;name&lt;/span&gt;&lt;/code&gt; property of an image is not required to be
unique, so filtering by name may result in multiple matches.  For example,
there may be multiple image producers promoting something named “Fred’s
Excellent OS”, and thus the following call (remembering to URL encode the
apostrophe and spaces):&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;v2/images?visibility=community&amp;amp;name=Fred%27s%20Excellent%20OS&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;may result in several image records for different image producers.  If you
want to find only images supplied by some particular producer, filtering by
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;owner&lt;/span&gt;&lt;/code&gt; will give you more accurate results.  Additionally, if “Fred’s
Excellent OS” image is ever deleted by Fred, who you trust, some other
producer George, who you don’t even know, could create a “Fred’s Excellent OS”
image.  If you are searching by name only, you’ll find George’s image—which
you probably don’t want to use until you’ve figured out who George is, whether
he’s trustworthy, and what exactly he’s put on the image.&lt;/p&gt;
&lt;p&gt;No provision is made in this API for producer-consumer communication.
All such communication must be done independently of the API.&lt;/p&gt;
&lt;p&gt;An example workflow for community images is:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;The producer posts information about community images on a public website.
This information would be a description of the image including the image’s
UUID.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A consumer uses the UUID in Images v2 API calls to access the image.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;An alternative workflow is:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;The producer posts information about community images on a public website.
This post would include the producer’s identifier.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A potential consumer uses the producer’s identifier in an image-list
call as in the example above to discover the available images and to
determine the UUID of an image to be consumed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The consumer uses the UUID in Images v2 API calls to access the image.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</description><pubDate>Wed, 09 Oct 2024 00:00:00 </pubDate></item><item><title>Standardize Image Encryption and Decryption</title><link>http://specs.openstack.org/openstack/glance-specs/specs/2025.1/approved/glance/standardized_image_encryption.html</link><description>

&lt;p&gt;OpenStack already has the ability to create encrypted volumes and ephemeral
storage to ensure the confidentiality of block data. Even though it is also
already possible to store encrypted images, there is only one service (Cinder)
that utilizes this option, but it is only indirectly usable by Nova (a user
must create a volume from the image first), and thus users don’t have an
intuitive way to create and upload encrypted images. In addition, all metadata
needed to detect and use encrypted images is either not present or specifically
scoped for Cinder right now. In conclusion, support for encrypted images does
exist to some extent but only in a non-explicit and non-standardized way. To
establish a consistent approach to image encryption for all OpenStack services
as well as users, several adjustments need to be implemented in Glance, Cinder
and OSC.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;An image, when uploaded to Glance or being created through Nova from an
existing server (a VM snapshot), may contain sensitive information. The already
provided signature functionality only protects images against alteration.
Images may be stored on several hosts over long periods of time. First and
foremost this includes the image storage hosts of Glance itself. Furthermore it
might also involve caches on systems like compute hosts. In conclusion they are
exposed to a multitude of potential scenarios involving different hosts with
different access patterns and attack surfaces. The OpenStack components
involved in those scenarios do not protect the confidentiality of image data.&lt;/p&gt;
&lt;p&gt;Using encrypted storage backends for volume and compute hosts in conjunction
with direct data transfer from/to encrypted images can enable workflows that
never expose an image’s data on a host’s filesystem. Storage of encryption keys
on a dedicated key manager host ensures isolation and access control for the
keys as well.&lt;/p&gt;
&lt;p&gt;As stated in the introduction above, some disk image encryption implementations
for ephemeral disks in Nova and volumes in Cinder already touch on this topic
but not always in a standardized and interoperable way. For example, the way of
handling image metadata and encryption keys can differ. Furthermore, users
are not easily able to make use of these implementations when supplying their
own images in a way that encryption can work the same across services.&lt;/p&gt;
&lt;p&gt;That’s why we propose the introduction of a streamlined encrypted image format
along with well-defined metadata specifications which will be supported across
OpenStack services for the existing encryption implementations and increase
interoperability as well as usability for users.&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;A user wants to upload an image, which includes sensitive information. To
ensure the integrity of the image, a signature can be generated and used
for verification. Additionally, the user wants to protect the
confidentiality of the image data through encryption. The user generates or
uploads a key in the key manager (e.g. Barbican) and uses it to encrypt the
image locally before uploading it. A mechanism to let the OpenStack Client
(OSC) do the encryption could be added in a later version.
Consequently, the image stored on the Glance host is encrypted.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A user wants to create a new server or volume based on a) an encrypted image
created externally or b) an image created as a backup from already encrypted
storage objects in components like Nova and Cinder. The corresponding
compute or volume host has to be able to directly use the encrypted image or
(if incompatible) transfer its encryption from e.g. qcow2-LUKS to raw
LUKS-encrypted blocks to be used for volumes. For this the OpenStack
services need access to the key in the key manager and a few image
properties about the encrypted image.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A user wants to download and directly decrypt an encrypted image to be used
privately or in another deployment. If possible, the download mechanism
could be adjusted on client side to directly decrypt such an image.&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;There are two ways encryption in images can be handled. The first is having a
qcow2 formatted disk with an internal encryption. The ‘disk_format’ for such an
image will consequently be ‘qcow2’ and the encryption can be detected through
the presence of the proposed additional metadata.
For other images the ‘disk_format’ will be used to indicate the encryption. It
should state the main encryption mechanism used, which for now is ‘luks’. We
additionally assume that the format of a decrypted LUKS-image will always be
‘raw’. The format can only be checked after a decryption of at least the first
few bytes this is currently out of scope for Glance. Every service, that uses
such encrypted LUKS-images needs to be aware of it.&lt;/p&gt;
&lt;p&gt;Furthermore, we propose the following additional metadata properties carried by
images of this format:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;‘os_encrypt_format’ - the specific mechanism used, e.g. ‘LUKSv1’&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;‘os_encrypt_key_id’ - reference to key in the key manager&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;‘os_encrypt_key_deletion_policy’ - on image deletion indicates whether the
key should be deleted too&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;‘os_decrypt_container_format’ - format change, e.g. from ‘compressed’ to
‘bare’&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;‘os_decrypt_size’ - size after payload decryption&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To upload an encrypted image to Glance we want to extend the OpenStack Client
to allow the specification of the necessary metadata properties as the key ID
and the encryption and optionally metadata properties as for example the
specification of the key deletion policy.
Later on there might be support added for encrypting images using the specified
key ID directly in the OpenStack Client.&lt;/p&gt;
&lt;p&gt;In other words: the user has to encrypt an image before the upload. While
uploading the encrypted image to Glance, the metadata properties above have to
be specified.&lt;/p&gt;
&lt;p&gt;We propose to align the encryption with Nova and Cinder and use LUKS, which
will be allowed in combination with qcow and raw images. We use this two
versions for the following reasons:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Nova can directly use qcow-LUKS encrypted when creating a server. This is
the standard procedure of Nova. Nova can also handle LUKS-encrypted raw
images.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Cinder allows the creation of Images from encrypted volumes. These will
always result in LUKS-encrypted raw images. Those images can be converted
directly to volumes again. Cinder currently expects encrypted images to be
raw images.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;In the latter case it is already possible to upload such an encrypted image to
another OpenStack infrastructure, upload the key as well and set the
corresponding metadata. After doing so the image can be used in the second
infrastructure to create an encrypted volume.&lt;/p&gt;
&lt;p&gt;We want to align the existing implementations between Nova and Cinder by
standardizing the used metadata parameters and adding interoperability where
applicable. Furthermore, we want to provide users with the means to encrypt
images outside of the infrastructure for upload in Glance which will later be
handled in similar ways by both Cinder and Nova.&lt;/p&gt;
&lt;p&gt;The key management is handled differently than with encrypted volumes or
encrypted ephemeral storage. The reason for this is, that the encryption and
decryption of an image should never happen in Glance but only on client side.
Therefore the service which needs to create a key for a newly created
encrypted image may not be the same service which then has to delete the key
(in most cases Glance). To delete a key, which has not been created by the same
entity, is bad behavior. To avoid this, we choose to do the following:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;if a user uploads an image the user is responsible for creation and deletion
of the key.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;if Cinder or Nova are uploading an image, they are responsible for creating
a key (e.g. as it is handled in Cinder currently).&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Optionally the deletion of the secret can be delegated to Glance through
setting the special metadata parameter “os_encrypt_key_deletion_policy” to
true. This behavior is already implemented for encrypted images from Cinder,
we will only rename the property so it is not solely be usable by Cinder.&lt;/p&gt;
&lt;p&gt;To not accidentally delete a key, which is used to encrypt an image, we will
let Glance register as a consumer of that key (secret in Barbican [1]) when the
corresponding encrypted image is uploaded and unregister as a consumer when the
image is deleted in Glance. When the parameter “os_encrypt_key_deletion_policy”
is set to “True”, we will try to delete the key. If that fails, because there
was still a consumer, we let Glance log that as a warning and proceed with the
image deletion process. In this case the key might still be used for another
image or some other ressource and we do not want to delete it, we rather assume
that the “os_encrypt_key_deletion_policy” was mistakenly set to “True”.&lt;/p&gt;
&lt;p&gt;Image conversion will not be encryption-aware as part of this spec and as such,
conversion of encrypted images will not be supported. The vmdk format is not
supported by this spec and the conversion itself would need decryption and
encryption to be handled by Glance. This would be more than the scope of this
spec will be. So if image conversion is enabled and an encrypted images that
needs conversion is uploaded the API will return a 400 Error and the image will
be put in the queued state as a result.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;We could introduce individual container types in Glance for each combination
of data format and cipher algorithm instead of a single container type with
metadata. This decision affects the implementation in nova and cinder.
Regarding the image encryption, we also explored the possibility of using more
elaborated and dynamic approaches like PKCS#7 (CMS) but ultimately failed to
find a free open-source implementation (e.g. OpenSSL) that supports streamable
decryption of CMS-wrapped encrypted data. More precisely, no implementation we
tested was able to decrypt a symmetrically encrypted, CMS-wrapped container
without trying to completely load it into memory or suffering from other
limitations regarding big files.&lt;/p&gt;
&lt;p&gt;We also evaluated an image encryption implementation based on GPG. The downside
with such an implementation is, that everytime such an image is used to create
a server or a volume the image has to be decrypted and maybe re-encrypted for
another encryption format as both Nova and Cinder use LUKS as an encryption
mechanism. This would not only have impact on the performance of the operation
but it also would need free space for the encrypted image file, the decrypted
parts and the encrypted volume or server that is created.&lt;/p&gt;
&lt;p&gt;We evaluated to use a single container format for all encrypted images, but as
Cinder already stores Images within different containers (e.g. ‘compressed’)
we decided to use the usual container format and check for the presence of
encryption parameters instead to detect an encrypted image.&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 impact depends on whether the implementation will make actual changes to
the image data model or simply use the generic properties field in the
metadata. In the latter case the encryption properties would be added to
metadefs.&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;While uploading an image, which should be encrypted, additional properties in
the request body will need to be introduced to specify the desired encryption
format and key id. Both to be used while encrypting the image locally before
uploading it.&lt;/p&gt;
&lt;p&gt;Example request:
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;`&lt;/span&gt;
&lt;span class="pre"&gt;REQ:&lt;/span&gt; &lt;span class="pre"&gt;curl&lt;/span&gt; &lt;span class="pre"&gt;-g&lt;/span&gt; &lt;span class="pre"&gt;-i&lt;/span&gt; &lt;span class="pre"&gt;-X&lt;/span&gt; &lt;span class="pre"&gt;POST&lt;/span&gt;
&lt;span class="pre"&gt;http://a.b.c.d/image/v2/images&lt;/span&gt; &lt;span class="pre"&gt;-H&lt;/span&gt; &lt;span class="pre"&gt;"Content-Type:&lt;/span&gt; &lt;span class="pre"&gt;application/json"&lt;/span&gt; &lt;span class="pre"&gt;....&lt;/span&gt; &lt;span class="pre"&gt;-d&lt;/span&gt; &lt;span class="pre"&gt;'&lt;/span&gt;
&lt;span class="pre"&gt;{"disk_format":&lt;/span&gt; &lt;span class="pre"&gt;"LUKS",&lt;/span&gt; &lt;span class="pre"&gt;"name":&lt;/span&gt; &lt;span class="pre"&gt;"cirros",&lt;/span&gt; &lt;span class="pre"&gt;"container_format":&lt;/span&gt; &lt;span class="pre"&gt;"compressed",&lt;/span&gt;
&lt;span class="pre"&gt;"os_encrypt_format":&lt;/span&gt; &lt;span class="pre"&gt;"LUKSv1",&lt;/span&gt; &lt;span class="pre"&gt;"os_encrypt_key_id":&lt;/span&gt; &lt;span class="pre"&gt;"...",&lt;/span&gt;
&lt;span class="pre"&gt;"os_encrypt_key_deletion_policy":&lt;/span&gt; &lt;span class="pre"&gt;"True",&lt;/span&gt; &lt;span class="pre"&gt;"os_decrypt_format":&lt;/span&gt; &lt;span class="pre"&gt;"raw",&lt;/span&gt;
&lt;span class="pre"&gt;"os_decrypt_container_format":&lt;/span&gt; &lt;span class="pre"&gt;"bare",&lt;/span&gt; &lt;span class="pre"&gt;"os_decrypt_size":&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;Additionally the GET image API call will display all set properties.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;There are impacts on the security of OpenStack:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;confidentiality of data in images will be addressed in this spec&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;image encryption is introduced formally, thus cryptographic algorithms will
be used in all involved components (Nova, Cinder, OSC)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Glance may lose the ability to provide a first-layer defense against image
policy violations (such as rejecting invalid/disallowed formats), because
inspection of encrypted data is not possible.&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;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Users should be able to optionally, but knowingly upload an encrypted image.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If an administrator has configured Glance to reject unencrypted images, such
images will not be accepted when attempted to be uploaded to Glance.&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;The proposed encryption/decryption mechanisms in the OpenStack components will
only be utilized on the client side and skipped entirely for images that
aren’t encrypted.&lt;/p&gt;
&lt;p&gt;When creating a volume or server from an encrypted image the only operation
that may be triggered is the conversion between qcow-LUKS and raw LUKS blocks.&lt;/p&gt;
&lt;p&gt;Thus, any performance impact is only applicable to the newly introduced
encrypted image type where the processing of the image will have increased
computational costs and longer processing times than regular images. Impact
will vary depending on the individual host performance and supported CPU
extensions for cipher algorithms.&lt;/p&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;A key manager - like Barbican - is required, if encrypted images are to be
used.&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;We can assume, that all images that are encrypted and already present in an
OpenStack deployment were created from encrypted Cinder volumes. They need to
be adjusted in the following way:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;all images that have ‘cinder_encryption_key_id’ set, need to convert it to
‘os_encrypt_key_id’&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;all images that have ‘cinder_encryption_key_deletion_policy’ set, need to
convert it to ‘os_encrypt_key_deletion_policy’&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;Primary assignee: Markus Hentsch (IRC: mhen)&lt;/p&gt;
&lt;p&gt;Other contributors: Josephine Seifert (IRC: Luzi)&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 standardized parameters with encryption support to Glance&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add registering as consumer for a Barbican secret when uploading an
encrypted image&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add unregistering as consumer for a Barbican secret when deleting an
encrypted image&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add support for providing the new image properties to the
python-openstackclient and openstacksdk, so that an encrypted image
can be uploaded&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Change the usages of ‘cinder_encryption_key_deletion_policy’ and
‘cinder_encryption_key_id’ throughout the Glance codebase to the new
parameters&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add unit test and functional test for uploading encrypted images&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add a migration script for the transformation of legacy properties of the
volume based encrypted images&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Adjust the documentation to show the new and changed parameters&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add the image encryption as documentation in the security guide&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 secret consumer API in Barbican is required for Glance to be able to
register and unregister as a consumer of a secret&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;Tempest tests would require access to encrypted images for testing. This means
that Tempest either needs to be provided with an image file that is already
encrypted and its corresponding key or needs to be able to encrypt images
itself. This point is still open for discussion.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;It should be documented for deployers, how to enable this feature in the
OpenStack configuration. An end user should have documentation on how to create
and use encrypted images.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;[1] Barbican Secret Consumer Spec:
&lt;a class="reference external" href="https://review.opendev.org/#/c/662013/"&gt;https://review.opendev.org/#/c/662013/&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;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>Tue, 03 Sep 2024 00:00:00 </pubDate></item><item><title>2025.1 Project Priorities</title><link>http://specs.openstack.org/openstack/glance-specs/priorities/2025.1-priorities.html</link><description>
&lt;span id="priorities"/&gt;
&lt;p&gt;TODO(glance-ptl): fill this in after the PTG&lt;/p&gt;
</description><pubDate>Tue, 30 Jul 2024 00:00:00 </pubDate></item><item><title>User-configurable hash algorithms</title><link>http://specs.openstack.org/openstack/glance-specs/specs/2024.2/approved/glance/configurable-hash-algorithms.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/glance/+spec/configurable-hash-algorithms"&gt;https://blueprints.launchpad.net/glance/+spec/configurable-hash-algorithms&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Allow end-users to specify a hash algorithm to be used when creating a new
image, allowing them to compare existing hashes provided by the creator of the
image with hashes returned by Glance, rather than having to generate the hashes
themselves on the client side.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;As described &lt;a class="reference external" href="https://docs.openstack.org/glance/latest/user/os_hash_algo.html"&gt;in the docs&lt;/a&gt;, the
Secure Hash Algorithm feature adds image properties that may be used to verify
image integrity based on its hash. Two properties are added, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_hash_algo&lt;/span&gt;&lt;/code&gt;
which contains the name of the hash algorithm used to generate the hash, and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_hash_value&lt;/span&gt;&lt;/code&gt; which contains the hash itself.&lt;/p&gt;
&lt;p&gt;We would like to be able to use &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;web-download&lt;/span&gt;&lt;/code&gt; to upload an image
to Glance - be that an OpenShift release images or a stock CentOS Stream or
Ubuntu image - and then verify the hash of the uploaded image against a
signature given by the image provider. However, currently the hash algorithm
represented by &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_hash_algo&lt;/span&gt;&lt;/code&gt; is not user-configurable: it can only be
configured by the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[DEFAULT]&lt;/span&gt; &lt;span class="pre"&gt;hashing_algorithm&lt;/span&gt;&lt;/code&gt; configuration option. This
defaults to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;sha512&lt;/span&gt;&lt;/code&gt;, which was chosen as it was more performant than SHA-256
(see &lt;a class="reference internal" href="../../../rocky/implemented/glance/multihash.html"&gt;&lt;span class="doc"&gt;Secure Hash Algorithm Support&lt;/span&gt;&lt;/a&gt;), but SHA-512 signatures
are not published by all image providers: for example, while Debian publishes
SHA-512 signatures (&lt;a class="reference external" href="https://cdimage.debian.org/debian-cd/current/amd64/iso-cd/"&gt;source&lt;/a&gt;), Ubuntu only
publishes SHA-256 signatures (&lt;a class="reference external" href="https://releases.ubuntu.com/24.04/"&gt;source&lt;/a&gt;)
as does Fedora (&lt;a class="reference external" href="https://fedora.ip-connect.vn.ua/linux/releases/40/Workstation/x86_64/iso/"&gt;source&lt;/a&gt;).
When signatures are not provided in a suitable format, it is necessary to
either ask an admin to change the hash algorithm (which affects the entire
deployment and might not be possible, particularly in public cloud
environments) or generate the hash on the client-side before uploading the
image (which limits the usefulness of the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;web-download&lt;/span&gt;&lt;/code&gt; image import
mechanism). We would like to address this gap.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;To resolve this, we propose allowing users to select the hash algorithm to be
used when creating the image. We will rename the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[DEFAULT]&lt;/span&gt;
&lt;span class="pre"&gt;hashing_algorithm&lt;/span&gt;&lt;/code&gt; config option to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[DEFAULT]&lt;/span&gt; &lt;span class="pre"&gt;default_hashing_algorithm&lt;/span&gt;&lt;/code&gt;
(providing an alias for the older name) and add a new config option,
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[DEFAULT]&lt;/span&gt; &lt;span class="pre"&gt;allowed_hashing_algorithms&lt;/span&gt;&lt;/code&gt;, which will be a list of algorithms
that are permitted to specified by the user and will initially default to
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;['sha512',&lt;/span&gt; &lt;span class="pre"&gt;'sha256',&lt;/span&gt; &lt;span class="pre"&gt;'sha1',&lt;/span&gt; &lt;span class="pre"&gt;'md5']&lt;/span&gt;&lt;/code&gt;. In this way, users can select a
hashing algorithm that suits their use case while operators can still restrict
certain algorithms to e.g. maintain regulatory compliance.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Instead of allowing users to specify the hash algorithm to be used, we could
start storing multiple hash algorithms. This would require replacing the two
image properties, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_hash_algo&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_hash_value&lt;/span&gt;&lt;/code&gt; with either a new
map-like property or flat algorithm-specific properties (e.g.
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_hash_value.sha512&lt;/span&gt;&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;This was rejected because it has a far larger API impact, would require
database changes, and would increase CPU utilisation due to the need to
generate multiple hashes for every image.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Instead on introducing a new configuration option, we could modify the
behavior of the existing &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[DEFAULT]&lt;/span&gt; &lt;span class="pre"&gt;hashing_algorithm&lt;/span&gt;&lt;/code&gt; option such
that it now accepts a list of allowed hashing algorithms, with the first item
(index 0) being the default used.&lt;/p&gt;
&lt;p&gt;This was rejected because it overloads the option to have two purposes - both
configuring a default and configuring allowed options - which could be
confusing for operators. In addition, any deployments that have non-default
values (e.g. &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;sha256&lt;/span&gt;&lt;/code&gt;) will have those values persisted and the value will
now affect both default and allowed hashing algorithms, which may be
undesirable from an operator perspective yet easy to miss.&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 &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;POST&lt;/span&gt; &lt;span class="pre"&gt;/images&lt;/span&gt;&lt;/code&gt; API will now allow users to specify the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_hash_algo&lt;/span&gt;&lt;/code&gt;
property during image creation. If a user specifies an unsupported algorithm,
the request will be rejected with a HTTP 400 (Bad Request) error and
appropriate error message.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;There are a number of potential issues with these but we believe none of them
are actual issues.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A malicious user could rely on a hash collision with a (significantly) weaker
or insecure algorithm to trick users into believing they are downloading e.g.
an official Ubuntu image when in fact they are downloading a weaker image.&lt;/p&gt;
&lt;p&gt;Using this would require that the malicious user has the ability to create
public or community images, or they would require the potential victim to
accept a share request for a shared image. This is unlikely in a public cloud
environment. In addition, and perhaps more importantly, a hash collision
attack using SHA-256 or SHA-512 has not been publicly demonstrated. This is
obviously not the case for SHA1 and MD5 but as both algorithms’ lack of
security is well documented and well known, there should be no expectation of
security from end-users.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A malicious user could conduct a denial-of-service attack on Glance by
uploading images using an expensive hashing algorithm.&lt;/p&gt;
&lt;p&gt;The set of hashing algorithms that a user can specify will be
operator-configurable, meaning only well-known, well-understood algorithms
will be permitted by default. In addition, such a hashing algorithm would
have to be &lt;strong&gt;astoundingly&lt;/strong&gt; expensive to make a dent in the existing overhead
costs of downloading and storing a glance image. We are not aware of any such
hash algorithms in practical use.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use of a particular algorithm could cause the operator to run afoul of
regulatory requirements.&lt;/p&gt;
&lt;p&gt;The supported hashing algorithms will be operator-configurable. The operator
can merely disable those that are not permitted due to e.g. FIPS compliance
requirements.&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;This field is already supported by openstacksdk but is currently silently
ignored. This will no longer be the case. Put another way, this will now work:&lt;/p&gt;
&lt;div class="highlight-python notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&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="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="n"&gt;openstack&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;enable_logging&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;debug&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;image&lt;/span&gt; &lt;span class="o"&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;image&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;create_image&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s1"&gt;'foobar'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;os_hash_algo&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'sha256'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Or, using OpenStackClient (OSC):&lt;/p&gt;
&lt;div class="highlight-shell notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;openstack&lt;span class="w"&gt; &lt;/span&gt;image&lt;span class="w"&gt; &lt;/span&gt;create&lt;span class="w"&gt; &lt;/span&gt;--property&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;os_hash_algo&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;sha256&lt;span class="w"&gt; &lt;/span&gt;foobar
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;We may wish to add a new helper alias to the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;image&lt;/span&gt; &lt;span class="pre"&gt;create&lt;/span&gt;&lt;/code&gt; command in
OpenStackClient, to allow users to specify this well-known alias easily but
this is a nice-to-have.&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 now have the ability to configure the hashing algorithms that
users can use when creating image. While this will default to a sensible set of
default algorithms, they may wish to tweak this further to meet regulatory or
organisational requirements.&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;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="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Add the new configuration option&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add necessary API logic to allow the user to specify this option during image
creation and respect it during image upload.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update 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;Unit test and manual testing should suffice here, though we can also test this
via a new Tempest test.&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 need to update the API documentation along with the Secure Hash
Algorithm feature documentation.&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, 14 Jun 2024 00:00:00 </pubDate></item><item><title>Improve filesystem store driver to utilize NFS capabilities</title><link>http://specs.openstack.org/openstack/glance-specs/specs/2024.2/approved/glance/improve-filesystem-driver.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/glance/+spec/improve-filesystem-driver"&gt;https://blueprints.launchpad.net/glance/+spec/improve-filesystem-driver&lt;/a&gt;&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;The filesystem backend of glance can be used to mount NFS share as local
filesystem, so it is not required to store any special configs at
glance side. Glance does not care about NFS server address or NFS share
path at all, it just assumes that each image is stored in the local
filesystem. The downside of this assumption is that glance is not
aware whether NFS server is connected/available or not, NFS share
is mounted or not and just keeps performing add/delete operations
on local filesystem directory which later might causes problem
in synchronization when NFS is back online.&lt;/p&gt;
&lt;p&gt;Use case: In a k8s environment where OpenStack Glance is installed on
top of OpenShift and NFS share is mounted via the &lt;cite&gt;Volume/VolumeMount&lt;/cite&gt;
interface, the Glance pod won’t start if NFS share isn’t ready. Whereas
if NFS share is not available after Glance pod is available then
upload operation will fail with following error:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;sh-5.1$ openstack image create --container-format bare --disk-format raw --file /tmp/cirros-0.5.2-x86_64-disk.img cirros
ConflictException: 409: Client Error for url: https://glance-default-public-openstack.apps-crc.testing/v2/images/0ce1f894-5af7-44fa-987d-f4c47c77d0cf/file, Conflict
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Even though the Glance Pod is still up, &lt;cite&gt;liveness&lt;/cite&gt; and &lt;cite&gt;readiness&lt;/cite&gt; probes
starts failing and as a result the Glance Pods are marked as &lt;cite&gt;Unhealthy&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="n"&gt;Normal&lt;/span&gt;   &lt;span class="n"&gt;Started&lt;/span&gt;         &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;                    &lt;span class="n"&gt;kubelet&lt;/span&gt;            &lt;span class="n"&gt;Started&lt;/span&gt; &lt;span class="n"&gt;container&lt;/span&gt; &lt;span class="n"&gt;glance&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;api&lt;/span&gt;
  &lt;span class="ne"&gt;Warning&lt;/span&gt;  &lt;span class="n"&gt;Unhealthy&lt;/span&gt;       &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="n"&gt;m24s&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x2&lt;/span&gt; &lt;span class="n"&gt;over&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="n"&gt;m24s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="n"&gt;kubelet&lt;/span&gt;            &lt;span class="n"&gt;Liveness&lt;/span&gt; &lt;span class="n"&gt;probe&lt;/span&gt; &lt;span class="n"&gt;failed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Get&lt;/span&gt; &lt;span class="s2"&gt;"https://10.217.0.247:9292/healthcheck"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;net&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt; &lt;span class="n"&gt;canceled&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Timeout&lt;/span&gt; &lt;span class="n"&gt;exceeded&lt;/span&gt; &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;awaiting&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="ne"&gt;Warning&lt;/span&gt;  &lt;span class="n"&gt;Unhealthy&lt;/span&gt;       &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="n"&gt;m24s&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x3&lt;/span&gt; &lt;span class="n"&gt;over&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="n"&gt;m24s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="n"&gt;kubelet&lt;/span&gt;            &lt;span class="n"&gt;Liveness&lt;/span&gt; &lt;span class="n"&gt;probe&lt;/span&gt; &lt;span class="n"&gt;failed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Get&lt;/span&gt; &lt;span class="s2"&gt;"https://10.217.0.247:9292/healthcheck"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;net&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt; &lt;span class="n"&gt;canceled&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Timeout&lt;/span&gt; &lt;span class="n"&gt;exceeded&lt;/span&gt; &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;awaiting&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="ne"&gt;Warning&lt;/span&gt;  &lt;span class="n"&gt;Unhealthy&lt;/span&gt;       &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="n"&gt;m24s&lt;/span&gt;                  &lt;span class="n"&gt;kubelet&lt;/span&gt;            &lt;span class="n"&gt;Readiness&lt;/span&gt; &lt;span class="n"&gt;probe&lt;/span&gt; &lt;span class="n"&gt;failed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Get&lt;/span&gt; &lt;span class="s2"&gt;"https://10.217.0.247:9292/healthcheck"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;net&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt; &lt;span class="n"&gt;canceled&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Timeout&lt;/span&gt; &lt;span class="n"&gt;exceeded&lt;/span&gt; &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;awaiting&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="ne"&gt;Warning&lt;/span&gt;  &lt;span class="n"&gt;Unhealthy&lt;/span&gt;       &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="n"&gt;m54s&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x2&lt;/span&gt; &lt;span class="n"&gt;over&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="n"&gt;m24s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="n"&gt;kubelet&lt;/span&gt;            &lt;span class="n"&gt;Readiness&lt;/span&gt; &lt;span class="n"&gt;probe&lt;/span&gt; &lt;span class="n"&gt;failed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Get&lt;/span&gt; &lt;span class="s2"&gt;"https://10.217.0.247:9292/healthcheck"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;net&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt; &lt;span class="n"&gt;canceled&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Timeout&lt;/span&gt; &lt;span class="n"&gt;exceeded&lt;/span&gt; &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;awaiting&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="ne"&gt;Warning&lt;/span&gt;  &lt;span class="n"&gt;Unhealthy&lt;/span&gt;       &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="n"&gt;m54s&lt;/span&gt;                  &lt;span class="n"&gt;kubelet&lt;/span&gt;            &lt;span class="n"&gt;Readiness&lt;/span&gt; &lt;span class="n"&gt;probe&lt;/span&gt; &lt;span class="n"&gt;failed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Get&lt;/span&gt; &lt;span class="s2"&gt;"https://10.217.0.247:9292/healthcheck"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;net&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt; &lt;span class="n"&gt;canceled&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Timeout&lt;/span&gt; &lt;span class="n"&gt;exceeded&lt;/span&gt; &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;awaiting&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Later in time, according to the failure threshold set for the Pod,
the kubelet marks the Pod as Failed, and we can see a failure, and
given that the policy is supposed to recreate it:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;glance-default-single-0                                         0/3     CreateContainerError   4 (3m39s ago)   28m

$ oc describe pod glance-default-single-0 | tail
Normal   Started    29m                    kubelet   Started container glance-api
Warning  Unhealthy  10m (x3 over 26m)      kubelet   Readiness probe failed: Get "https://10.217.0.247:9292/healthcheck": net/http: request canceled (Client.Timeout exceeded while awaiting headers)
Warning  Unhealthy  10m                    kubelet   Liveness probe failed: Get "https://10.217.0.247:9292/healthcheck": net/http: request canceled (Client.Timeout exceeded while awaiting headers)
Warning  Unhealthy  10m                    kubelet   Readiness probe failed: Get "https://10.217.0.247:9292/healthcheck": context deadline exceeded (Client.Timeout exceeded while awaiting headers)
Warning  Unhealthy  9m30s (x4 over 26m)    kubelet   Liveness probe failed: Get "https://10.217.0.247:9292/healthcheck": net/http: request canceled (Client.Timeout exceeded while awaiting headers)
Warning  Unhealthy  9m30s (x5 over 26m)    kubelet   Liveness probe failed: Get "https://10.217.0.247:9292/healthcheck": net/http: request canceled (Client.Timeout exceeded while awaiting headers)
Warning  Unhealthy  9m30s (x2 over 22m)    kubelet   Readiness probe failed: Get "https://10.217.0.247:9292/healthcheck": net/http: request canceled (Client.Timeout exceeded while awaiting headers)
Warning  Unhealthy  9m30s (x3 over 22m)    kubelet   Readiness probe failed: Get "https://10.217.0.247:9292/healthcheck": net/http: request canceled (Client.Timeout exceeded while awaiting headers)
Warning  Unhealthy  9m30s                  kubelet   Liveness probe failed: Get "https://10.217.0.247:9292/healthcheck": context deadline exceeded (Client.Timeout exceeded while awaiting headers)
Warning  Failed     4m47s (x2 over 6m48s)  kubelet   Error: context deadline exceeded
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Unlike other deployments (deployment != k8s) where even if NFS share is not
available the glance service keeps running and uploads or deletes the data
from local filesystem. In this case we can definitely say that NFS share is
not available, the Glance won’t be able to upload any image in the
filesystem local to the container and the Pod will be marked as failed and
it fails to be recreated.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;We are planning to add new plugin &lt;cite&gt;enable_by_files&lt;/cite&gt; to &lt;cite&gt;healthcheck&lt;/cite&gt;
wsgi middleware in &lt;cite&gt;oslo.middleware&lt;/cite&gt; which can be used by all openstack
components to check if desired path is not present then report
&lt;cite&gt;503 &amp;lt;REASON&amp;gt;&lt;/cite&gt; error or &lt;cite&gt;200 OK&lt;/cite&gt; if everything is OK.&lt;/p&gt;
&lt;p&gt;In glance we can configure this healthcheck middleware as an application
in glance-api-paste.ini as an application:&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;[app:healthcheck]&lt;/span&gt;
&lt;span class="na"&gt;paste.app_factory&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;oslo_middleware:Healthcheck.app_factory&lt;/span&gt;
&lt;span class="na"&gt;backends&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;enable_by_files (optional, default: empty)&lt;/span&gt;
&lt;span class="c1"&gt;# used by the 'enable_by_files' backend&lt;/span&gt;
&lt;span class="na"&gt;enable_by_file_paths&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;/var/lib/glance/images/filename,/var/lib/glance/cache/filename (optional, default: empty)&lt;/span&gt;

&lt;span class="c1"&gt;# Use this composite for keystone auth with caching and cache management&lt;/span&gt;
&lt;span class="k"&gt;[composite:glance-api-keystone+cachemanagement]&lt;/span&gt;
&lt;span class="na"&gt;paste.composite_factory&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;glance.api:root_app_factory&lt;/span&gt;
&lt;span class="na"&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;api-keystone+cachemanagement&lt;/span&gt;
&lt;span class="na"&gt;/healthcheck&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;healthcheck&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The middleware will return “200 OK” if everything is OK,
or “503 &amp;lt;REASON&amp;gt;” if not with the reason of why this API should not be used.&lt;/p&gt;
&lt;p&gt;“backends” will the name of a stevedore extentions in the namespace
“oslo.middleware.healthcheck”.&lt;/p&gt;
&lt;p&gt;In glance, if local filesystem path is mounted on NFS share then we
propose to add one marker file named &lt;cite&gt;.glance&lt;/cite&gt; to NFS share and then
use that file path to configure &lt;cite&gt;enable_by_files&lt;/cite&gt; healthcheck
middleware plugin as shown below:&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;[app:healthcheck]&lt;/span&gt;
&lt;span class="na"&gt;paste.app_factory&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;oslo_middleware:Healthcheck.app_factory&lt;/span&gt;
&lt;span class="na"&gt;backends&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;enable_by_files&lt;/span&gt;
&lt;span class="na"&gt;enable_by_file_paths&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;/var/lib/glance/images/.glance&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;If NFS goes down or somehow the &lt;cite&gt;/healthcheck&lt;/cite&gt; starts reporting
&lt;cite&gt;503 &amp;lt;REASON&amp;gt;&lt;/cite&gt; admin can take appropriate actions to make NFS
share available again.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Introduce few configuration options for filesystem driver which will help to
detect if the NFS share is unmounted from underneath the Glance service. We
proposed to introduce below new configuration options for the same:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;cite&gt;filesystem_is_nfs_configured&lt;/cite&gt; - boolean, verify if NFS is configured or not&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;cite&gt;filesystem_nfs_host&lt;/cite&gt; - IP address of NFS server&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;cite&gt;filesystem_nfs_share_path&lt;/cite&gt; - Mount path of NFS mapped with local filesystem&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;cite&gt;filesystem_nfs_mount_options&lt;/cite&gt; - Mount options to be passed to NFS client&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;cite&gt;rootwrap_config&lt;/cite&gt; - To run commands as root user&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If &lt;cite&gt;filesystem_is_nfs_configured&lt;/cite&gt; is set, i.e. if NFS is configured then
deployer must specify &lt;cite&gt;filesystem_nfs_host&lt;/cite&gt; and &lt;cite&gt;filesystem_nfs_share_path&lt;/cite&gt;
config options in glance-api.conf otherwise the respective glance store will
be disabled and will not be used for any operation.&lt;/p&gt;
&lt;p&gt;We are planning to use existing os-brick library (already used by cinder driver
of glance_store) to create the NFS client with the help of above configuration
options and check if NFS share is available or not during service
initialization as well as before each image upload/import/delete operation. If
NFS share is not available during service initialization then add and delete
operations will be disabled but if NFS goes down afterwards we will raise
HTTP 410 (HTTP GONE) response to the user.&lt;/p&gt;
&lt;p&gt;Glance still doesn’t have capability to check whether particular NFS store has
storage capability to store any particular image beforehand. Also it does not
have capability to verify if network failure occurs during upload/import
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;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;Need to configure healthcheck middleware for glance.&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;abhishekk&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 &lt;cite&gt;enable_by_files&lt;/cite&gt; healthcheck backend in oslo.middleware&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Document how to configure &lt;cite&gt;enable_by_files&lt;/cite&gt; healthcheck middleware&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Unit/Functional tests for coverage&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;Functional Tests&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;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;Need to document new behavior of filesystem driver if NFS and healthcheck
middleware is configured.&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;Oslo.Middleware Implementation - &lt;a class="reference external" href="https://review.opendev.org/920055"&gt;https://review.opendev.org/920055&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
</description><pubDate>Mon, 29 Apr 2024 00:00:00 </pubDate></item><item><title>2024.2 Project Priorities</title><link>http://specs.openstack.org/openstack/glance-specs/priorities/2024.2-priorities.html</link><description>
&lt;span id="priorities"/&gt;
&lt;p&gt;The Dalmatian Cycle priorities were discussed during Dalmatian Virtual
PTG. The preliminary list was maintained on the &lt;a class="reference external" href="https://etherpad.opendev.org/p/apr2024-ptg-glance#L431"&gt;Dalmatian PTG etherpad&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The following indicates milestonewise priorities.&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;Priority Item&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Owner(s)&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Spec(s)&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Target release milestone&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;Deprecate metadata_encryption_key&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;a class="reference external" href="https://launchpad.net/~pranali-deore"&gt;Pranali Deore&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;a class="reference external" href="https://review.opendev.org/c/openstack/glance-specs/+/916178"&gt;deprecate metadata encryption key&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;M1&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;New Location APIs&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;a class="reference external" href="https://launchpad.net/~pranali-deore"&gt;Pranali Deore&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;a class="reference external" href="https://review.opendev.org/c/openstack/glance-specs/+/883491"&gt;new location apis&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;M2&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;New sub-store NFS for FS store&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;a class="reference external" href="https://launchpad.net/~abhishek-kekane"&gt;Abhishek Kekane&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;a class="reference external" href="https://review.opendev.org/c/openstack/glance-specs/+/917284"&gt;improve_filesystem_driver&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;M2&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Add CLI utility for migrating images&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;a class="reference external" href="https://launchpad.net/~abhishek-kekane"&gt;Abhishek Kekane&lt;/a&gt;&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;M3&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Removed all unused config options&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;a class="reference external" href="https://launchpad.net/~cyril-roelandt"&gt;Cyril Roelandt&lt;/a&gt;&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;M3&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;All image/metadef APIs OSC &amp;amp; SDK Support&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;a class="reference external" href="https://launchpad.net/~mrjoshi"&gt;Mridula Joshi&lt;/a&gt;&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;M3&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Image Encryption&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;a class="reference external" href="https://launchpad.net/~josei"&gt;Josephine Seifert&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;a class="reference external" href="https://review.opendev.org/c/openstack/glance-specs/+/915726"&gt;image encryption&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;M3&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;section id="important-dates"&gt;
&lt;h2&gt;Important dates&lt;/h2&gt;
&lt;p&gt;This is an abbreviated list focused on dates relevant to Glance.  See
&lt;a class="reference external" href="https://releases.openstack.org/dalmatian/schedule.html"&gt;Dalmatian Release Schedule&lt;/a&gt; for the complete list for OpenStack.&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;Milestone&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Week of&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;What&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;R-20&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;May 17&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Dalmatian-1 Milestone&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;R-13&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Jul 05&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Dalmatian-2 Milestone&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Glance Spec freeze&lt;/strong&gt;&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;R-6&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Aug 23&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;glance_store Dalmatian release (final release for non-client libraries)&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;R-5&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Aug 30&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Dalmatian-3 milestone&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Glance feature freeze&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;python-glanceclient dalmatian release (final release for client libraries);&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;R-3&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Sept 13&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;RC-1 release and &lt;strong&gt;string freeze&lt;/strong&gt;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;R-1&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Sept 27&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;final RCs&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;R-0&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Oct 04&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;strong&gt;Dalmatian release&lt;/strong&gt;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Thu, 18 Apr 2024 00:00:00 </pubDate></item><item><title>Spec Lite: Deprecate metadata_encryption_key</title><link>http://specs.openstack.org/openstack/glance-specs/specs/2024.2/approved/glance/deprecate-metadata-encryption-key.html</link><description>

&lt;dl class="field-list simple"&gt;
&lt;dt class="field-odd"&gt;project&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;glance&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;problem&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;&lt;cite&gt;metadata_encryption_key&lt;/cite&gt; config option and it’s related
functionality was added quite a long back ago. Even though as per
the description it encrypts the location metadata, it actually
encrypts location url. It encrypts the location url only for image
upload/import/download/show APIs, doesn’t encrypt url on location
APIs. If it’s enabled during upgrade then it will break the
existing deployment since existing image url is not been encrypted.
It doesn’t even work for location url encryption as expected since
it does not encrypts the legacy images url on start up, download
of that image fails with InvalidLocation error.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;solution&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;We decided to deprecate &lt;cite&gt;metadata_encryption_key&lt;/cite&gt; config option in
this cycle and remove it in &lt;cite&gt;F&lt;/cite&gt; (2025.2) cycle.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;impacts&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;None&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;how&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;In this cycle deprecate &lt;cite&gt;metadata_encryption_key&lt;/cite&gt; configuration
options. Remove it along with it’s related functionality in &lt;cite&gt;F&lt;/cite&gt; cycle.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;alternatives&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;None&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;timeline&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;Milestone 2&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;link&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;None&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;reviewers&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;abhishekk, croelandt, mrjoshi&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;assignee&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;pdeore&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
</description><pubDate>Thu, 18 Apr 2024 00:00:00 </pubDate></item><item><title>2024.1 Project Priorities</title><link>http://specs.openstack.org/openstack/glance-specs/priorities/2024.1-priorities.html</link><description>
&lt;span id="priorities"/&gt;
&lt;p&gt;The Caracal Cycle priorities were discussed during Caracal Virtual PTG.
The preliminary list was maintained on the &lt;a class="reference external" href="https://etherpad.opendev.org/p/oct2023-ptg-glance"&gt;Caracal PTG etherpad&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This list is an estimate of what the Glance project team can accomplish
during the 2024.1 Cycle based on our developer’s estimates of how much
time they can commit to Glance.&lt;/p&gt;
&lt;p&gt;The following indicates milestonewise priorities.&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;Priority Item&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Owner(s)&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Spec(s)&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Target release milestone&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;New Location APIs&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;a class="reference external" href="https://launchpad.net/~pranali-deore"&gt;Pranali Deore&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;a class="reference external" href="https://review.opendev.org/c/openstack/glance-specs/+/883491"&gt;new location apis&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;M2&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Centralize DB for cache&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;a class="reference external" href="https://launchpad.net/~abhishek-kekane"&gt;Abhishek Kekane&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;a class="reference external" href="https://review.opendev.org/c/openstack/glance-specs/+/899367"&gt;centralize DB for cache&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;M2&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Deprecate Location Strategy&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;a class="reference external" href="https://launchpad.net/~abhishek-kekane"&gt;Abhishek Kekane&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;a class="reference external" href="https://review.opendev.org/c/openstack/glance-specs/+/899804"&gt;deprecate location strategy&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;M2&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Deprecate Cachemanage middleware&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;a class="reference external" href="https://launchpad.net/~abhishek-kekane"&gt;Abhishek Kekane&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;a class="reference external" href="https://review.opendev.org/c/openstack/glance-specs/+/899805"&gt;deprecate cachemanage middleware&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;M2&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Remove/Migrate Single Store Tests&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;a class="reference external" href="https://launchpad.net/~pranali-deore"&gt;Pranali Deore&lt;/a&gt;&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;M3&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;All image/metadef APIs OSC &amp;amp; SDK Support&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;a class="reference external" href="https://launchpad.net/~mrjoshi"&gt;Mridula Joshi&lt;/a&gt;&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;M3&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Image Encryption&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;a class="reference external" href="https://launchpad.net/~josei"&gt;Josephine Seifert&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;a class="reference external" href="https://review.opendev.org/c/openstack/glance-specs/+/899856"&gt;image encryption&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;M3&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;section id="important-dates"&gt;
&lt;h2&gt;Important dates&lt;/h2&gt;
&lt;p&gt;This is an abbreviated list focused on dates relevant to Glance.  See
&lt;a class="reference external" href="https://releases.openstack.org/caracal/schedule.html"&gt;Caracal Release Schedule&lt;/a&gt; for the complete list for OpenStack.&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;Milestone&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Week of&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;What&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;R-20&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Nov 17&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Caracal-1 Milestone&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;R-12&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Jan 12&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Caracal-2 Milestone&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Glance Spec freeze&lt;/strong&gt;&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;R-6&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Feb 23&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;glance_store Caracal release (final release for non-client libraries)&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;R-5&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Mar 01&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Caracal-3 milestone&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Glance feature freeze&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;python-glanceclient caracal release (final release for client libraries);&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;R-3&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Mar 15&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;RC-1 release and &lt;strong&gt;string freeze&lt;/strong&gt;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;R-1&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Mar 29&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;final RCs&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;R-0&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Apr 05&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;strong&gt;Caracal release&lt;/strong&gt;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Wed, 01 Nov 2023 00:00:00 </pubDate></item><item><title>Spec Lite: Deprecate cachemanage middleware</title><link>http://specs.openstack.org/openstack/glance-specs/specs/2024.1/approved/glance/deprecate-cachemanage-middleware.html</link><description>

&lt;dl class="field-list simple"&gt;
&lt;dt class="field-odd"&gt;project&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;glance&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;problem&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;Deprecate cachemanage middleware&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;solution&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;Cache operations (CR(u)D) is now part of glance API. Even though
we need to depend on cache middleware to enable it. There are two
middlewares related to caching, one is &lt;cite&gt;cache&lt;/cite&gt; and other is
&lt;cite&gt;cachemanage&lt;/cite&gt; and we can now get rid of &lt;cite&gt;cachemanage&lt;/cite&gt; middleware and
glance-cache-manage  command line utility.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;impacts&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;None&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;how&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;In this cycle we are going to deprecate cachemanage middleware and api
pipeline &lt;cite&gt;keystone+cachemanage&lt;/cite&gt; (defined in glance-api-paste.ini) and
&lt;cite&gt;glance-cache-manage&lt;/cite&gt; command line utility. A deprecation warning
message will be added to each command of &lt;cite&gt;glance-cache-manage&lt;/cite&gt; utility
as well as during initialization of &lt;cite&gt;cachemanage&lt;/cite&gt; middleware.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;alternatives&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;None&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;timeline&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;Milestone 2&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;link&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;None&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;reviewers&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;pdeore, mrjoshi, croelandt&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;assignee&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;abhishekk&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
</description><pubDate>Wed, 01 Nov 2023 00:00:00 </pubDate></item><item><title>Spec Lite: Deprecate location strategy</title><link>http://specs.openstack.org/openstack/glance-specs/specs/2024.1/approved/glance/deprecate-location-strategy.html</link><description>

&lt;dl class="field-list simple"&gt;
&lt;dt class="field-odd"&gt;project&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;glance&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;problem&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;Deprecate location strategy&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;solution&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;In Bobcat we added support for weighing mechanism to glance store.
To use this new feature we decided to deprecate location strategy
in this cycle and remove it in ‘D’ (2024.2) development cycle.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;impacts&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;None&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;how&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;In this cycle we are going to deprecate following configuration
options related to location strategy:
* location_strategy
* store_type_preference
Also a warning message regarding deprecation will be added to
&lt;cite&gt;location_order&lt;/cite&gt; and &lt;cite&gt;store_type&lt;/cite&gt; strategy module during initiation
phase.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;alternatives&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;None&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;timeline&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;Milestone 2&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;link&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;None&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;reviewers&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;pdeore, mrjoshi, croelandt&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;assignee&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;abhishekk&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
</description><pubDate>Wed, 01 Nov 2023 00:00:00 </pubDate></item><item><title>Image Encryption and Decryption</title><link>http://specs.openstack.org/openstack/glance-specs/specs/2024.1/approved/glance/image-encryption.html</link><description>

&lt;p&gt;OpenStack already has the ability to create encrypted volumes and ephemeral
storage to ensure the confidentiality of block data. In contrast to that,
images are currently handled without protection towards confidentiality, only
providing the possibility to ensure integrity using image signatures. For
further protection of user data - e.g. when a user uploads an image containing
private data or confidential information - the image data should not be
accessible for unauthorized entities. For this purpose, an encrypted image
format is to be introduced in OpenStack. In conclusion, several adjustments to
support image encryption/decryption in various projects, e.g. Nova, Glance,
Cinder and OSC, need to be implemented.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;An image, when uploaded to Glance or being created through Nova from an
existing server (VM), may contain sensitive information. The already provided
signature functionality only protects images against alteration. Images may be
stored on several hosts over long periods of time. First and foremost this
includes the image storage hosts of Glance itself. Furthermore it might also
involve caches on systems like compute hosts. In conclusion they are exposed
to a multitude of potential scenarios involving different hosts with different
access patterns and attack surfaces. The OpenStack components involved in
those scenarios do not protect the confidentiality of image data.&lt;/p&gt;
&lt;p&gt;Using encrypted storage backends for volume and compute hosts in conjunction
with direct data transfer from/to encrypted images can enable workflows that
never expose an image’s data on a host’s filesystem. Storage of encryption
keys on a dedicated key manager host ensures isolation and access control for
the keys as well. With such a set of configuration recommendations for
security focused environments, we are able to reach a good foundation. Future
enhancements can build upon that and extend the provided security enhancements
to a broader set of variants.&lt;/p&gt;
&lt;p&gt;That’s why we propose the introduction of an encrypted image format.&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;A user wants to upload an image, which includes sensitive information. To
ensure the integrity of the image, a signature can be generated and used
for verification. Additionally, the user wants to protect the
confidentiality of the image data through encryption. The user generates or
uploads a key in the key manager (e.g. Barbican) and uses it to encrypt the
image locally using the OpenStack client (osc) when uploading it.
Consequently, the image stored on the Glance host is encrypted.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A user wants to create an image from an existing server with ephemeral
storage. This server may contain sensitive user data. The corresponding
compute host then generates the image based on the data of the ephemeral
storage disk. To protect the confidentiality of the data within the image,
the user wants Nova to also encrypt the image using a key from the key
manager, specified by its ID. Consequently, the image stored on the Glance
host is encrypted.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A user wants to create an image from an existing volume. This volume may
contain sensitive user data. The corresponding volume host then generates
the image based on the data of the volume. To protect the confidentiality
of the data within the image, the user wants Cinder to also encrypt the
image using a key from the key manager, specified by its ID. Consequently,
the image stored on the Glance host is encrypted.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A user wants to create a new server or volume based on an encrypted image
created by any of the use cases described above. The corresponding compute
or volume host has to be able to decrypt the image using the symmetric key
stored in the key manager and transform it into the requested resource
(server disk or volume). For this, the user needs access to the key in the
key manager which is controlled via their project role assignment.&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 Glance we propose to add a new container_format called ‘encrypted’.
Furthermore, we propose the following additional metadata properties carried by
images of this format:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;‘os_glance_encrypt_format’ - the main mechanism used, e.g. ‘GPG’&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;‘os_glance_encrypt_type’   - encryption type, e.g. ‘symmetric’&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;‘os_glance_encrypt_cipher’ - the cipher algorithm, e.g. ‘AES256’&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;‘os_glance_encrypt_key_id’ - reference to key in the key manager&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;‘os_glance_decrypt_container_format’ - format after payload decryption&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;‘os_glance_decrypt_size’ - size after payload decryption&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To upload an encrypted image to Glance we want to add support for encrypting
images using a key ID which references the symmetric key in the key manager
(e.g. Barbican) in the OpenStack Client. This also involves new CLI arguments to
specify the key ID and encryption method and this implementation should
make use of a centralized encryption implementation provided by a global
library, shared between all involved OpenStack components to eliminate the need
of individual implementations of the encryption mechanism.&lt;/p&gt;
&lt;p&gt;In other words: the user or openstack service as cinder for example has to
encrypt an image before the upload. While uploading the encrypted image to
glance, the metadata properties above have to be specified and the container
format has to be set to ‘encrypted’.&lt;/p&gt;
&lt;p&gt;We propose to use an implementation of symmetric encryption provided by GnuPG as
a basic mechanism supported by this draft. It is a well established
implementation of PGP and supports streamable encryption/decryption processes.&lt;/p&gt;
&lt;p&gt;We require the streamability of the encryption/decryption mechanism for two
reasons:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Loading entire images into the memory of compute hosts or a users system is
unacceptable.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We propose direct decryption-streaming into the target storage (e.g.
encrypted volume) to prevent the creation of temporary unencrypted files.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;There is already one existing case in Cinder’s current implementation where
encrypted images are created. This is when an image is created
directly from an encrypted volume. Since the encrypted block data is simply
copied into the image, the encryption (usually LUKS) is automatically
inherited - as is the encryption key, which is simply cloned in Barbican. We
will not change this behavior as a part of this spec. Our changes will only
apply, when the user actively intends to create an encrypted image from any
volume using the new image encryption extensions.&lt;/p&gt;
&lt;p&gt;The key management is handled differently than with encrypted volumes or
encrypted ephemeral storage. The reason for this is, that the encryption and
decryption of an image will never happen in Glance but in all other services,
which consume images. Therefore the service which needs to create a key for
a newly created encrypted image may not be the same service which then has to
delete the key (in most cases Glance). To delete a key, which has not been
created by the same entity, is bad behavior. To avoid this, we choose to let
the user create and delete the key. To not accidently delete a key, which is
used to encrypt an image, we will let Glance register as a consumer of that
key (secret in Barbican [1]) when the corresponding encrypted image is
uploaded and unregister as a consumer when the image is deleted in Glance.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;We could introduce individual container types in Glance for each combination
of data format and cipher algorithm instead of a single container type with
metadata. This decision affects the implementation in nova and cinder.&lt;/p&gt;
&lt;p&gt;Regarding the image encryption, we also explored the possibility of using more
elaborated and dynamic approaches like PKCS#7 (CMS) but ultimately failed to
find a free open-source implementation (e.g. OpenSSL) that supports streamable
decryption of CMS-wrapped encrypted data. More precisely, no implementation we
tested was able to decrypt a symmetrically encrypted, CMS-wrapped container
without trying to completely load it into memory or suffering from other
limitations regarding big files.&lt;/p&gt;
&lt;p&gt;We also evaluated an image encryption implementation based on LUKS which is
already used in Cinder and Nova as an encryption mechanism for volumes and
ephemeral disks respectively. However, we were unable to find a suitable
solution to directly handle file-based LUKS encryption in user space. Firstly,
the handling of LUKS devices (even when file-based) via cryptsetup always
requires the dm-crypt kernel module and corresponding root privileges.
Secondly, in contrast to native LUKS used by LibVirt, the LUKS handling
available via cryptsetup creates temporary device mapper endpoints where data
is read from or written to. There is no direct reading/writing from/to an
encrypted LUKS file and LUKS opening/closing needs to be handled accordingly.
Lastly, LUKS is a format primarily designed for disk encryption. Although it
may be used for files as well (by formatting files as LUKS devices), the
handling is rather inconvenient; for example, the size of the LUKS container
file needs to be calculated and allocated beforehand since it acts like a disk
with a fixed size.&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 impact depends on whether the implementation will make actual changes to
the image data model or simply use the generic properties field in the
metadata. In the latter case the encryption properties would be added to
metadefs.&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;While uploading an image, which should be encrypted, additional properties in
the request body will need to be introduced to specify the desired encryption
format and key id. Both to be used while encrypting the image locally before
uploading it.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;There are impacts on the security of OpenStack:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;confidentiality of data in images will be addressed in this spec&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;image encryption is introduced, thus cryptographic algorithms will be used
in all involved components (Nova, Cinder, OSC)&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;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Users should be able to optionally, but knowingly upload an encrypted image.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If an administrator has configured Glance to reject unencrypted images, such
images will not be accepted when attempted to be uploaded to Glance.&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;The proposed encryption/decryption mechanisms in the OpenStack components will
only be utilized on-demand and skipped entirely for image container types that
aren’t encrypted.&lt;/p&gt;
&lt;p&gt;Thus, any performance impact is only applicable to the newly introduced
encrypted image type where the processing of the image will have increased
computational costs and longer processing times than regular images. Impact
will vary depending on the individual host performance and supported CPU
extensions for cipher algorithms.&lt;/p&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;Deployers can toggle the acceptance or enforce the usage of encrypted images
by adding/omitting ‘encrypted’ in ‘container_formats’ accordingly.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Deployers enforcing the usage of encrypted images by omitting all other image
types in ‘container_formats’ will make public images unavailable due to the
lack of a public secrets functionality in Barbican.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A key manager - like Barbican - is required.&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;p&gt;Primary assignee: Markus Hentsch (IRC: mhen)&lt;/p&gt;
&lt;p&gt;Other contributors: Josephine Seifert (IRC: Luzi)&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 container type(s) with encryption support to Glance&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add registering as consumer for a Barbican secret when uploading an
encrypted image&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add unregistering as consumer for a Barbican secret when deleting an
encrypted image&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Provide compatibility to the image_conversion plugin for Interoperable Image
Import (skip conversion attempt for encrypted payload)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add support for providing the new image properties to the
python-glanceclient, so that an image with the container_format: encrypted
can be uploaded&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;GPG is required to be installed on all systems that are required to perform
encryption/decryption operations in order to support the proposed base
encryption mechanism.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;This spec requires the implementation of appropriate encryption/decryption
functionality in a global library shared between the components involved in
image encryption workflows (Nova, Cinder, OSC). We determined to use
os-brick.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The secret consumer API in Barbican is required for glance to be able to
register and unregister as a consumer of a secret&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;Tempest tests would require access to encrypted images for testing. This means
that Tempest either needs to be provided with an image file that is already
encrypted and its corresponding key or needs to be able to encrypt images
itself. This point is still open for discussion.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;It should be documented for deployers, how to enable this feature in the
OpenStack configuration. An end user should have documentation on, how to use
encrypted images.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;[1] Barbican Secret Consumer Spec:
&lt;a class="reference external" href="https://review.opendev.org/#/c/662013/"&gt;https://review.opendev.org/#/c/662013/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Nova-Spec: &lt;a class="reference external" href="https://review.openstack.org/#/c/608696/"&gt;https://review.openstack.org/#/c/608696/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Cinder Spec: &lt;a class="reference external" href="https://review.openstack.org/#/c/608663/"&gt;https://review.openstack.org/#/c/608663/&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>Wed, 01 Nov 2023 00:00:00 </pubDate></item><item><title>Use Centralized database for caching</title><link>http://specs.openstack.org/openstack/glance-specs/specs/2024.1/approved/glance/centralized-cache-db.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/glance/+spec/centralized-cache-db"&gt;https://blueprints.launchpad.net/glance/+spec/centralized-cache-db&lt;/a&gt;&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;We use two different database(s) for glance. One is a centralized database
managed by oslo.db (default is MySQL) for storing information related to
regular operations; the other one is a sqlite database for
storing information about caching related operations. Even though the
sqlite database is only created if we enable cache middleware we still
need to maintain it along with centralized database. Also glance caches
are local to each controller node (glance api service), so in case of
multiple glance services running we have multiple sqlite database(s)
operational.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;We propose to use centralized database (default MySql) for caching related
operations and stop using sqlite database from this release onwards. In this
case we can get rid of creating sqlite database per glance service and
have everything under central database.&lt;/p&gt;
&lt;p&gt;At present users can choose between &lt;cite&gt;sqlite&lt;/cite&gt; (Default) and &lt;cite&gt;xattr&lt;/cite&gt; for how
caching can be controlled using &lt;cite&gt;image_cache_driver&lt;/cite&gt; configuration option. We
propose to introduce new driver &lt;cite&gt;centralized_db&lt;/cite&gt; and required configuration
options, make it default and mark &lt;cite&gt;sqlite&lt;/cite&gt; driver and related configuration
options as deprecated in this cycle and remove it in ‘D’ development
cycle.&lt;/p&gt;
&lt;p&gt;In order to use central database for caching we recommend to have almost
similar schema (columns) as sqlite database with additional reference to
local node (glance service). New deployments will directly start using this
new central database if cache is enabled.&lt;/p&gt;
&lt;p&gt;In case of upgrades/updates we need to deal with migrating existing records
from sqlite database to central database. Since we might have multiple
glance(s) running this will be difficult to handle using alembic migrations.
To avoid this using migration we can perform this operation one time during
service startup. If sqlite database is present at service start and
&lt;cite&gt;image_cache_driver&lt;/cite&gt; is not set to &lt;cite&gt;centralized_db&lt;/cite&gt; then we will
read records from it and insert those in newly created &lt;cite&gt;cached_images&lt;/cite&gt; table
in central database. Once all records are migrated we will clear the sqlite
database table and keep the sqlite database file as it is (to be deleted by
administrator/operator later if required). Important point here is once
deployer chooses to use &lt;cite&gt;centralized_db&lt;/cite&gt; and we migrate their records out
of &lt;cite&gt;sqlite&lt;/cite&gt; to centralized database, then we will not migrate them back
if deployer wants to revert back to &lt;cite&gt;sqlite&lt;/cite&gt; driver.&lt;/p&gt;
&lt;p&gt;As deployment can have multiple glance services running, to record cache
details separately for multiple glance services, we can use existing
configuration option &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;worker_self_reference_url&lt;/span&gt;&lt;/code&gt; which will
differentiate cache records for each glance service running in the
deployment. &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;worker_self_reference_url&lt;/span&gt;&lt;/code&gt; is used to identify nodes in the case
of new import workflow earlier, and now the same can be used for this purpose
as well. Since &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;worker_self_reference_url&lt;/span&gt;&lt;/code&gt; is required for &lt;cite&gt;glance-direct&lt;/cite&gt;
import method as well, if we found that it was not set by the deployer for
any of the glance setup, then at the service startup we will log appropriate
error message and prevent the service from starting. Also, since in the case of
multiple nodes, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;worker_self_reference_url&lt;/span&gt;&lt;/code&gt; needs to be set to a unique value
per node, and if, by mistake, two or more nodes have the same value for it,
then we will not migrate the cache data of that node to a centralized database
with logging an appropriate warning message.&lt;/p&gt;
&lt;p&gt;Once we migrate existing cache records to central database we need to
ensure that existing cache related command line utilities like cache-cleaner,
cache-pruner are working as expected. Since these utilities use dedicated
configuration file (glance-cache.conf), we need to make provision to
introduce required configuration options in this file so that these tools can
connect to central database.&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;Create two new tables in mysql, one to record cache related operations and
other to record glance api references as shown below.&lt;/p&gt;
&lt;p&gt;Schema for cached_images:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;CREATE TABLE cached_images (
  id bigint auto increment PRIMARY KEY,
  image_id varchar(36),
  last_accessed DateTime,
  last_modified DateTime,
  size bigint,
  hits int,
  checksum varchar(32),
  node_reference_id int,
  UNIQUE KEY `uq_cache_unique_id` (`image_id`,`node_reference_id`)
  FOREIGN KEY (node_reference_id) REFERENCES cache_node_reference(node_reference_id)

)
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Schema for cache_node_reference:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;CREATE TABLE cache_node_reference (
  node_reference_id int PRIMARY KEY auto increment,
  node_reference_url varchar(255)
  UNIQUE KEY `uq_node_reference_url` (`node_reference_url`)
)
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&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&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;abhishekk&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;Deprecate existing sqlite driver and related configuration options&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create alembic scripts for two new tables&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add model/queries to sqlalchemy for new tables&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Introduce new centralized_db driver and related configuration options&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Change cache code to use new mysql database&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add logic at service startup to migrate data from sqlite to mysql&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Modify related commandline tools like cache-cleaner, cache-pruner
to use centralized driver&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Tempest tests to ensure multiple glance nodes uses centralized
database.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Grenade test(s) to verify upgrading scenario(s)&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;Functional Tests&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Tempest Tests&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;grenade tests to verify upgrade scenario&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 document use of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;worker_self_reference_url&lt;/span&gt;&lt;/code&gt; in case of import workflow
and cache related operations.&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, 26 Oct 2023 00:00:00 </pubDate></item><item><title>New Location APIs</title><link>http://specs.openstack.org/openstack/glance-specs/specs/2023.2/approved/glance/new-location-info-apis.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/glance/+spec/new-location-apis"&gt;https://blueprints.launchpad.net/glance/+spec/new-location-apis&lt;/a&gt;&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Currently we have two security vulnerabilities with
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;show_multiple_locations&lt;/span&gt;&lt;/code&gt; config option, OSSN-0065 &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; and OSSN-0090 &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;.
If we enable &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;show_multiple_locations&lt;/span&gt;&lt;/code&gt; and the policies for add/update
(set_image_location), get (get_image_location) and remove
(delete_image_location) locations are set for non-admins then non-admin users
can modify location data to corrupt an image that they own. Note that the
policies for add, get and remove locations are set for non-admins by default
else a non-admin user cannot associate data with an image record, or retrieve
image data, or delete image data.&lt;/p&gt;
&lt;p&gt;When show_multiple_locations is False, users cannot modify image
locations via the image-update API call, even if they have the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;{get,set,delete}_image_location&lt;/span&gt;&lt;/code&gt; permissions.  However, there are some
popular use cases where other services can bypass Glance and store or access
image data directly in the backend by writing or reading image locations,
using the image owner’s credentials, and this is why operators want to set
show_multiple_locations to True.  What operators want to do, however, is to
enable optimized image data access; exposing image locations to non-admin
users is a side-effect, not the goal.  We currently recommend that operators
who want to use optimized data access use a specialized Glance instance for
services, and only expose glance-api to end users with show_multiple_locations
set False.  This is inconvinient for certain users.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;There will be 3 phases in which the work will be done as follows:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Introduce 2 new API calls that allow operations on image locations which
are described in detail in the &lt;a class="reference internal" href="#rest-api-impact"&gt;REST API impact&lt;/a&gt; section.
These calls will replace the image-update mechanism for consumers
like cinder and nova.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Modify the consumer (cinder/nova) code to use the new location APIs.
Also modify HTTP store to use new location APIs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Remove &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;show_multiple_locations&lt;/span&gt;&lt;/code&gt; config option when it is no longer
required by other services (cinder/nova) to perform operations on
locations. This will mostly be done 1 or 2 cycles after the consumers
have adapted the new location APIs to handle the upgrade cases.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The config option &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;show_multiple_locations&lt;/span&gt;&lt;/code&gt; has been deprecated since Newton
but we will keep the config option until the consumers of glance locations
(nova, cinder, http store etc) start using the new location APIs. Since this
is a major effort spanning across multiple services (nova, cinder, glance),
we will implement the work items in different cycles to provide enough
time for developers (to implement this) and operators (to move away from the
config option).&lt;/p&gt;
&lt;p&gt;We will introduce 2 new policies, for each API performing different operations
like add and get, as follows:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;add&lt;/span&gt; &lt;span class="pre"&gt;policy&lt;/span&gt;&lt;/code&gt; can default to the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;project&lt;/span&gt; &lt;span class="pre"&gt;member&lt;/span&gt;&lt;/code&gt; or &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;service&lt;/span&gt;&lt;/code&gt;
role (when it is implemented).&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;get&lt;/span&gt; &lt;span class="pre"&gt;policy&lt;/span&gt;&lt;/code&gt; will default to the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;service&lt;/span&gt;&lt;/code&gt; role for authorization.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Along with the new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;add&lt;/span&gt; &lt;span class="pre"&gt;policy&lt;/span&gt;&lt;/code&gt;, we will add a check in the location add API
code to check the status of image and only add location if it is in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;QUEUED&lt;/span&gt;&lt;/code&gt;
state and adding location when the image is in other states will be
disallowed. This is done in order to prevent malicious users from modifying
the image location again and again since the location added for the first time
is the correct one as far as Glance is concerned.&lt;/p&gt;
&lt;p&gt;We will also introduce a new configuration parameter &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;do_secure_hash&lt;/span&gt;&lt;/code&gt; on
the glance side which will tell the API if we want to do the hash calculation
or not. This will be useful in cases when nova, cinder etc, adds a location
in glance since glance does not calculate the hash and checksum automatically
in these cases. The value of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;do_secure_hash&lt;/span&gt;&lt;/code&gt; will be &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;True&lt;/span&gt;&lt;/code&gt; by default.&lt;/p&gt;
&lt;p&gt;After nova or cinder send a request for adding a location for the VM snapshot
or upload volume case respectively and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;do_secure_hash&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;, glance
will start a background process that will calculate the hash of the image.
Unless we have &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;validation_data&lt;/span&gt;&lt;/code&gt; (in the request body) to be verified,
image will be set to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;active&lt;/span&gt;&lt;/code&gt; state after registering the location even if
the hash calculation is ongoing in the background. This is done so that the
image can be used to create instances and bootable volumes instantly after
we’ve registered the location and not wait for the hash calculation since
it is a long running task. After the hash calculation completes, image
properties will be updated with the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;checksum&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_hash_algo&lt;/span&gt;&lt;/code&gt; and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_hash_value&lt;/span&gt;&lt;/code&gt; values.&lt;/p&gt;
&lt;p&gt;Following are the cases of image transition with different values of
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;do_secure_hash&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;validation_data&lt;/span&gt;&lt;/code&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;do_secure_hash&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; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;validation_data&lt;/span&gt;&lt;/code&gt; is not None:&lt;/p&gt;
&lt;p&gt;Image transition: (queued, importing, active)&lt;/p&gt;
&lt;p&gt;In this case the consumer provides the hash values for validation and
hash is calculated by glance.
An example of this case will be providing validation_data for HTTP store.
Here image hash will be calculated and verified before setting image to
active state.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;do_secure_hash&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; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;validation_data&lt;/span&gt;&lt;/code&gt; is None:&lt;/p&gt;
&lt;p&gt;Image transition: (queued, active)&lt;/p&gt;
&lt;p&gt;In this case validation data will not be provided by the consumer but
hash is calculated by glance.
Examples of this case will be when nova snapshots an instance or cinder
uploads a volume to image.
Here image hash calculation will be done and updated after setting
image to active state.
This is a tricky case because the consumer will have no idea if the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;active&lt;/span&gt;&lt;/code&gt; image will ever have a hash value or not and if it should
wait for the hash to be populated in the image or not.
To handle this, we will set the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_hash_algo&lt;/span&gt;&lt;/code&gt; value in the image
properties so the consumer will know that hash calculation is ongoing
for this image and the hash will be populated here.
Here are the following cases:&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;active&lt;/span&gt;&lt;/code&gt; image and no &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_hash_algo&lt;/span&gt;&lt;/code&gt;: This image will not have hash
value populated.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;active&lt;/span&gt;&lt;/code&gt; image and has &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_hash_algo&lt;/span&gt;&lt;/code&gt;:  Poll for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;active&lt;/span&gt;&lt;/code&gt; image
status and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_hash_algo&lt;/span&gt;&lt;/code&gt; until you get &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_hash_value&lt;/span&gt;&lt;/code&gt;.
Polling for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;active&lt;/span&gt;&lt;/code&gt; image status is optional since the image gets
active when &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;validation_data&lt;/span&gt;&lt;/code&gt; is not provided and hash calculation
is ongoing in the background i.e. this case. The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_hash_algo&lt;/span&gt;&lt;/code&gt; value
will be popped if hash calculation fails.&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;do_secure_hash&lt;/span&gt;&lt;/code&gt; is &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;False&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;validation_data&lt;/span&gt;&lt;/code&gt; is not None:&lt;/p&gt;
&lt;p&gt;Image transition: (queued, active)&lt;/p&gt;
&lt;p&gt;In this case validation data will be provided by the consumer and hash
is not calculated by glance.
An example of this case will be providing validation_data for HTTP store.
Here image hash will not be calculated and verified but directly set to
image with values provided by the 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;do_secure_hash&lt;/span&gt;&lt;/code&gt; is &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;False&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;validation_data&lt;/span&gt;&lt;/code&gt; is None:&lt;/p&gt;
&lt;p&gt;Image transition: (queued, active)&lt;/p&gt;
&lt;p&gt;In this case validation data will not be provided by the consumer and
hash is not calculated by glance.
This can happen for all cases.
Here hash value won’t be set in the image.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If the hash calculation fails, we will add a retry mechanism that will
reinitiate the task. We will add a new configuration option &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;http_retries&lt;/span&gt;&lt;/code&gt;
with a default value of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;3&lt;/span&gt;&lt;/code&gt; i.e. the hash calculation will be executed
maximum 3 times by default if the first and second tries fail.
If after all the retries, the hash calculation still fails, we will not update
the hash and checksum values and image will stay in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;active&lt;/span&gt;&lt;/code&gt; state.&lt;/p&gt;
&lt;p&gt;End-user access to image locations via the Image API is no longer necessary.
Since Train, Glance has multiple stores support, and we have added API calls
that allow users to manipulate data locality with respect to store.
Further, a store is an opaque identifier, whereas an image location
exposes backend details that users don’t need to know.&lt;/p&gt;
&lt;p&gt;Here are the current use cases for the direct manipulation of image
locations along with an explanation of how they can be handled by the
new Location API.&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;When using a copy-on-write (COW) backend shared by Nova and Glance,
Nova can create an image record in Glance, snapshot a server image
directly in the backend, and set the location on the image record.
This use case is covered by the new add-location call, and having
its default policy be project member (image owner) or service.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A user wants to have a single image record, but have image data
stored in multiple locations for locality (i.e., to have image
data as close as possible to where it’s consumed).
This use case is handled by the glance multiple stores feature
plus image import, which since API v2.8, allows a ‘stores’ parameter
specifying where the image data should be stored.  This applies to both
newly created images and existing images (via the copy-image import
method).
In this workflow, Glance itself manipulates the image locations; there
is no need for the user to interact with locations directly.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;An operator wants to introduce a new storage backend and decommission
the current backend while keeping the same image catalog.
Similar to #2, this can be handled by using the copy-image import
method and the delete-image-from-store API call introduced in v2.10.
Note that there are some exceptions to this like:&lt;/p&gt;
&lt;ol class="loweralpha simple"&gt;
&lt;li&gt;&lt;p&gt;HTTP store is read-only, so we can’t use copy-image in this case.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For RBD store, we will create a dependency chain if we launch a VM
or create a bootable volume from it hence we can’t delete the source
image until all of it’s children are flattened.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For cinder store, if the cinder backend uses COW cloning, it is similar
to the RBD case mentioned in b) else the image delete will succeed.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Following APIs are not being implemented:&lt;/p&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Update&lt;/span&gt;&lt;/code&gt;: For service to service interaction, there is no value in updating
the metadata of a location. This would be beneficial if we plan to remove the
existing location code from image-update call and support the usecase of
operators/end-users doing location operations.&lt;/p&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Delete&lt;/span&gt;&lt;/code&gt;: We already have &lt;a class="reference external" href="https://docs.openstack.org/api-ref/image/v2/index.html?expanded=delete-image-from-store-detail#delete-image-from-store"&gt;Delete Image From Store&lt;/a&gt; API for this purpose.
We don’t require the &lt;a class="reference external" href="https://docs.openstack.org/api-ref/image/v2/index.html?expanded=delete-image-from-store-detail#delete-image-from-store"&gt;Delete Image From Store&lt;/a&gt; API call for the current
usecase but if we plan to extend the location APIs in future, we can do this
by updating the policies enforced by &lt;a class="reference external" href="https://docs.openstack.org/api-ref/image/v2/index.html?expanded=delete-image-from-store-detail#delete-image-from-store"&gt;Delete Image From Store&lt;/a&gt; operation from
the default &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;role:admin&lt;/span&gt;&lt;/code&gt; to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;role:admin&lt;/span&gt; &lt;span class="pre"&gt;or&lt;/span&gt; &lt;span class="pre"&gt;role:service&lt;/span&gt;&lt;/code&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;We can remove the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;show_multiple_locations&lt;/span&gt;&lt;/code&gt; config option and filter the
images with the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;admin_or_service&lt;/span&gt;&lt;/code&gt; role. This will require the consumers
to provide admin credentials during add or get of an image to get the
location.
This was the original proposal but due to the disagreement here &lt;a class="footnote-reference brackets" href="#id9" 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;, we
changed the design to the current proposal.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Another alternative is to add this functionality in the import workflow.
We can add a new import method &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;direct-location&lt;/span&gt;&lt;/code&gt; which will allow end
users to specify the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;location&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;metadata&lt;/span&gt;&lt;/code&gt; parameters and create a
new image based on the given parameters. We can also update an existing
image with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;location&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;metadata&lt;/span&gt;&lt;/code&gt; values but will require the image
to be in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;queued&lt;/span&gt;&lt;/code&gt; state.&lt;/p&gt;
&lt;p&gt;For this, we will need to add a new import method &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;direct-location&lt;/span&gt;&lt;/code&gt; and also
add &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;--metadata&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;--location&lt;/span&gt;&lt;/code&gt; parameters to the following commands:&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;glance&lt;/span&gt; &lt;span class="pre"&gt;image-create-via-import&lt;/span&gt; &lt;span class="pre"&gt;--import-method&lt;/span&gt; &lt;span class="pre"&gt;direct-location&lt;/span&gt; &lt;span class="pre"&gt;--location&lt;/span&gt;
&lt;span class="pre"&gt;&amp;lt;location&amp;gt;&lt;/span&gt; &lt;span class="pre"&gt;--metadata&lt;/span&gt; &lt;span class="pre"&gt;&amp;lt;key1=value1,&lt;/span&gt; &lt;span class="pre"&gt;key2=value2&lt;/span&gt; &lt;span class="pre"&gt;...&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;glance&lt;/span&gt; &lt;span class="pre"&gt;image-import&lt;/span&gt; &lt;span class="pre"&gt;--import-method&lt;/span&gt; &lt;span class="pre"&gt;direct-location&lt;/span&gt; &lt;span class="pre"&gt;--location&lt;/span&gt;
&lt;span class="pre"&gt;&amp;lt;location&amp;gt;&lt;/span&gt; &lt;span class="pre"&gt;--metadata&lt;/span&gt; &lt;span class="pre"&gt;&amp;lt;key1=value1,&lt;/span&gt; &lt;span class="pre"&gt;key2=value2&lt;/span&gt; &lt;span class="pre"&gt;...&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&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 are going to add 2 new location APIs:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Add Location&lt;/p&gt;
&lt;p&gt;This will add a new location to an existing image.
The request body will contain the location URL and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;validation_data&lt;/span&gt;&lt;/code&gt; &lt;a class="footnote-reference brackets" href="#id10" 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;
(optional). The purpose of including validation_data in the request body
is when the consumer wants to validate the image hash or just directly wants
to add the hash values to the image. The cases of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;validation_data&lt;/span&gt;&lt;/code&gt; with
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;do_secure_hash&lt;/span&gt;&lt;/code&gt; are described in the &lt;a class="reference internal" href="#proposed-change"&gt;Proposed change&lt;/a&gt; section.
An example where &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;validation_data&lt;/span&gt;&lt;/code&gt; will be provided is the HTTP store case,
where the user will provide hash value for the HTTP image.&lt;/p&gt;
&lt;p&gt;Unlike old location API, we will not provide support of adding a location
on a particular index. If we want to get the benefit of indexes, we can
use the old location APIs or set location strategy as store_type &lt;a class="footnote-reference brackets" href="#id11" 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;.
A new location strategy &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;store_identifier&lt;/span&gt;&lt;/code&gt; is proposed &lt;a class="footnote-reference brackets" href="#id12" 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; and should be
useful to download image from a specific store in case multiple stores are
configured.&lt;/p&gt;
&lt;p&gt;POST /v2/images/{image_id}/locations&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;JSON 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;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"cinder://lvmdriver-1/1a304872-b0ca-4992-b2c2-6874c6d5d5f9"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"validation_data"&lt;/span&gt;&lt;span class="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;"os_hash_algo"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"sha512"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"os_hash_value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"6b813aa46bb90b4da216a4d19376593fa3f4fc7e617f03a92b7fe11e9a3981cbe8f0959dbebe36225e5f53dc4492341a4863cac4ed1ee0909f3fc78ef9c3e869"&lt;/span&gt;&lt;span class="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;JSON response body&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Success - 200&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;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"cinder://lvmdriver-1/1a304872-b0ca-4992-b2c2-6874c6d5d5f9"&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="nt"&gt;"{'store': 'lvmdriver-1'}"&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"validation_data"&lt;/span&gt;&lt;span class="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;"os_hash_algo"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"sha512"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"os_hash_value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"6b813aa46bb90b4da216a4d19376593fa3f4fc7e617f03a92b7fe11e9a3981cbe8f0959dbebe36225e5f53dc4492341a4863cac4ed1ee0909f3fc78ef9c3e869"&lt;/span&gt;&lt;span class="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;Error - 409 (Location already exists or if image is not in QUEUED
state), 403 (Forbidden for users that are not owner), 400 (BadRequest
if hash validation fails)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Get Location(s)&lt;/p&gt;
&lt;p&gt;This will show all the locations associated to an existing image. Returns an
empty list if an image contains no locations.&lt;/p&gt;
&lt;p&gt;GET /v2/images/{image_id}/locations&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;JSON 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="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"cinder://lvmdriver-1/0f031ed1-5872-43d5-a638-4b0d07c10ab5"&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="s2"&gt;"{'store': 'lvmdriver-1'}"&lt;/span&gt;
&lt;span class="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;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"cinder://cephdriver-1/11b4fa9f-a44b-46c9-950c-0026c467252c"&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="s2"&gt;"{'store': 'cephdriver-1'}"&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;Error - 404 (Image ID does not exist), 403 (Forbidden for normal users)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The transition of image state during the image create operation will be as
follows.
Image upload (PUT), image stage (PUT) and location add (POST), will transition
the image from queued to the next state that could be either of the following:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;saving&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;uploading&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;importing&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;active&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Below are the valid transitions for image from queued state.&lt;/p&gt;
&lt;p&gt;‘queued’: (‘saving’, ‘uploading’, ‘importing’, ‘active’, ‘deleted’)&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;No worse than it is now, and possibly better.&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;The get-locations policy is restricted to the ‘service’ role,
so users will not be able to see image locations.  Thus with
‘show_multiple_locations’ and ‘show_direct_url’ set to False,
the new get-locations API will not expose location information
to users.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The add-location policy is restricted by default to image-owner.
This will allow end users to add a location to an image to address
current uses of this functionality that we aren’t aware of.
Even allowing this, the data-substitution attack is blocked because
the API call will only be allowed for an image in ‘queued’ status.
The add-location API cannot be used to add a location to an image in
other states and then delete the original location, so the OSSN-0065
attack is not possible under this scenario.
Further, the add-locations call (unlike the current method of
updating locations via PATCH), does not require the locations to
be visible to succeed.  Thus operators will be able to configure
Glance with ‘show_multiple_locations’ and ‘show_direct_url’ set
to False, even when other services are sharing a COW backend with
Glance and the operator wants an optimized workflow.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&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;Since the new APIs are mainly for service to service interaction (except the
HTTP store case), we will only expose the location add API via CLI. However,
we will need to add methods for all APIs in openstacksdk (that will call
the new location APIs) that will be used by other consumer services like
cinder and nova.
End users can still use the existing commands (that internally calls the
image-update API) to perform operations on locations:&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;glance&lt;/span&gt; &lt;span class="pre"&gt;location-add:&lt;/span&gt;&lt;/code&gt; Add a location (and related metadata) to an image.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance&lt;/span&gt; &lt;span class="pre"&gt;location-delete:&lt;/span&gt;&lt;/code&gt; Remove locations (and related metadata) from an
image.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance&lt;/span&gt; &lt;span class="pre"&gt;location-update:&lt;/span&gt;&lt;/code&gt; Update metadata of an image’s location.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We will also add a new command to glanceclient and OSC that will allow end
users to add the location &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;url&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;validation-data&lt;/span&gt;&lt;/code&gt; for HTTP store case.&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;glance&lt;/span&gt; &lt;span class="pre"&gt;add-location-properties&lt;/span&gt; &lt;span class="pre"&gt;--url&lt;/span&gt; &lt;span class="pre"&gt;&amp;lt;location&amp;gt;&lt;/span&gt; &lt;span class="pre"&gt;--validation-data&lt;/span&gt;
&lt;span class="pre"&gt;&amp;lt;os_hash_algo=value1,&lt;/span&gt; &lt;span class="pre"&gt;os_hash_value=value2&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;openstack&lt;/span&gt; &lt;span class="pre"&gt;image&lt;/span&gt; &lt;span class="pre"&gt;add&lt;/span&gt; &lt;span class="pre"&gt;location&lt;/span&gt; &lt;span class="pre"&gt;properties&lt;/span&gt; &lt;span class="pre"&gt;--url&lt;/span&gt; &lt;span class="pre"&gt;&amp;lt;location&amp;gt;&lt;/span&gt; &lt;span class="pre"&gt;--validation-data&lt;/span&gt;
&lt;span class="pre"&gt;&amp;lt;os_hash_algo=value1,&lt;/span&gt; &lt;span class="pre"&gt;os_hash_value=value2&amp;gt;&lt;/span&gt;&lt;/code&gt;&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;In the old location API, the consumers (nova, cinder) registered
the location in glance and the checksum, hash etc values weren’t
calculated. After the consumers adapt to the new location API,
and the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;do_secure_hash&lt;/span&gt;&lt;/code&gt; config parameter is &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;True&lt;/span&gt;&lt;/code&gt; (default),
glance will read the image and calculate the hash in the background.
The hash calculation will be a long running task so it will consume
resources, however, this won’t affect the operation requested by
nova or cinder as the image will transition to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;active&lt;/span&gt;&lt;/code&gt; state even
when the hash calculation is ongoing.&lt;/p&gt;
&lt;p&gt;The performance downside will result in creation of more secure
images and the impact needs to be conveyed to the operators/end users
with documentation and releasenotes. Since &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;do_secure_hash&lt;/span&gt;&lt;/code&gt; will be a
configurable parameter on glance side, we will add suitable help text
to convey the performance and security impact of enabling/disabling this
option.&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;Consumers like Cinder, Nova and HTTP store need to modify code to call the
new client functions to access the API.
Some of the key things to consider while implementing consumer side changes
are:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;We will use SDK to make the API calls. The changes to call new
location APIs will be in SDK and also in OSC/glanceclient for location
ADD in case of HTTP store.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Keep backward compatibility with old behavior. Glance should support
the legacy behavior as well as the new way to add/get locations. This is
useful in upgrade cases where one compute node is running 2023.1 (Antelope)
code and the other compute node has been upgraded to 2024.1 (CC) release.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Testing should be done to see if the existing functionalities supported
with the legacy location APIs works as expected with the new APIs.&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;pdeore&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&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 2 new Location APIs for add and get operations.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Modify consumers like cinder and nova and http store to use the new location
APIs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add a new configuration parameter &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;do_secure_hash&lt;/span&gt;&lt;/code&gt; in glance and document
it’s impact.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add a new configuration parameter &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;http_retries&lt;/span&gt;&lt;/code&gt; in glance and document
it’s usage.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add SDK support to call the new APIs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add a releasenote mentioning that we will remove the config option
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;show_multiple_locations&lt;/span&gt;&lt;/code&gt; when the consumers (nova/cinder/http store)
shift to using new location APIs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Tempest tests for the new add-location and get-location 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;Unit Tests&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Functional Tests&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Integration Tests&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;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;Need to document new location APIs.&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;&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://wiki.openstack.org/wiki/OSSN/OSSN-0065"&gt;https://wiki.openstack.org/wiki/OSSN/OSSN-0065&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;&lt;a class="reference external" href="https://wiki.openstack.org/wiki/OSSN/OSSN-0090"&gt;https://wiki.openstack.org/wiki/OSSN/OSSN-0090&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="#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/openstack/glance-specs/+/840882/2..15/specs/zed/approved/glance/new-location-info-apis.rst#b199"&gt;https://review.opendev.org/c/openstack/glance-specs/+/840882/2..15/specs/zed/approved/glance/new-location-info-apis.rst#b199&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="#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://specs.openstack.org/openstack/glance-specs/specs/stein/implemented/glance/spec-lite-locations-with-validation-data.html"&gt;https://specs.openstack.org/openstack/glance-specs/specs/stein/implemented/glance/spec-lite-locations-with-validation-data.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="#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/glance/latest/contributor/api/glance.common.location_strategy.store_type.html"&gt;https://docs.openstack.org/glance/latest/contributor/api/glance.common.location_strategy.store_type.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="#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://review.opendev.org/c/openstack/glance-specs/+/881951"&gt;https://review.opendev.org/c/openstack/glance-specs/+/881951&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;/aside&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Deprecate &lt;cite&gt;show_multiple_locations&lt;/cite&gt; option | &lt;a class="reference external" href="https://review.opendev.org/c/openstack/glance/+/313936"&gt;https://review.opendev.org/c/openstack/glance/+/313936&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update deprecated show_multiple_locations helptext | &lt;a class="reference external" href="https://review.opendev.org/c/openstack/glance/+/426283"&gt;https://review.opendev.org/c/openstack/glance/+/426283&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update show_multiple_locations deprecation note | &lt;a class="reference external" href="https://review.opendev.org/c/openstack/glance/+/625702"&gt;https://review.opendev.org/c/openstack/glance/+/625702&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Original security bug | &lt;a class="reference external" href="https://bugs.launchpad.net/ossn/+bug/1549483"&gt;https://bugs.launchpad.net/ossn/+bug/1549483&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;New security bug | &lt;a class="reference external" href="https://bugs.launchpad.net/ossn/+bug/1990157"&gt;https://bugs.launchpad.net/ossn/+bug/1990157&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
</description><pubDate>Thu, 18 May 2023 00:00:00 </pubDate></item><item><title>2023.2 Project Priorities</title><link>http://specs.openstack.org/openstack/glance-specs/priorities/2023.2-priorities.html</link><description>
&lt;span id="priorities"/&gt;
&lt;p&gt;The Bobcat Cycle priorities were discussed during Bobcat Virtual PTG.
The preliminary list was maintained on the &lt;a class="reference external" href="https://etherpad.opendev.org/p/glance-bobcat-ptg"&gt;Bobcat PTG etherpad&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This list is an estimate of what the Glance project team can accomplish
during the 2023.2 Cycle based on our developer’s estimates of how much
time they can commit to Glance.&lt;/p&gt;
&lt;p&gt;The following list is roughly indicates milestonewise priorities.&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;Priority Item&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Owner(s)&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Spec(s)&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Target release milestone&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;New Location APIs&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;a class="reference external" href="https://launchpad.net/~pranali-deore"&gt;Pranali Deore&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;a class="reference external" href="https://review.opendev.org/c/openstack/glance-specs/+/880030"&gt;new location apis&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;M1&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;RBD Trash&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;a class="reference external" href="https://launchpad.net/~eharney"&gt;Eric Harney&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;No Spec yet&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;M2&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Image Encryption&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;a class="reference external" href="https://launchpad.net/~josei"&gt;Josephine Seifert&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;a class="reference external" href="https://review.opendev.org/c/openstack/glance-specs/+/880627"&gt;image encryption&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;M2&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;All image APIs SDK Support&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;a class="reference external" href="https://launchpad.net/~mrjoshi"&gt;Mridula Joshi&lt;/a&gt;&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;M1&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Tempest coverage for New Location APIs&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;a class="reference external" href="https://launchpad.net/~pranali-deore"&gt;Pranali Deore&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;a class="reference external" href="https://review.opendev.org/c/openstack/glance-specs/+/880030"&gt;new location apis&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;M2&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;All Metadef APIs SDK Support&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;a class="reference external" href="https://launchpad.net/~mrjoshi"&gt;Mridula Joshi&lt;/a&gt;&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;M2&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Remove/Migrate Single Store Tests&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;a class="reference external" href="https://launchpad.net/~pranali-deore"&gt;Pranali Deore&lt;/a&gt;&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;M3&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Calculation multihash,checksum for existing location calls&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;a class="reference external" href="https://launchpad.net/~mrjoshi"&gt;Mridula Joshi&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;No Spec Yet&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;M3&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;section id="important-dates"&gt;
&lt;h2&gt;Important dates&lt;/h2&gt;
&lt;p&gt;This is an abbreviated list focused on dates relevant to Glance.  See
&lt;a class="reference external" href="https://releases.openstack.org/bobcat/schedule.html"&gt;Bobcat Release Schedule&lt;/a&gt; for the complete list for OpenStack.&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;Milestone&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Week of&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;What&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;R-21&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;May 12&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Bobcat-1 Milestone&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;R-13&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Jul 07&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Bobcat-2 Milestone&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Glance Spec freeze&lt;/strong&gt;&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;R-6&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Aug 25&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;glance_store Bobcat release (final release for non-client libraries)&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;R-5&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Sept 07&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Bobcat-3 milestone&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Glance feature freeze&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;python-glanceclient Bobcat release (final release for client libraries);&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;R-3&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Sept 15&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;RC-1 release and &lt;strong&gt;string freeze&lt;/strong&gt;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;R-1&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Sept 29&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;final RCs&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;R-0&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Oct 06&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;strong&gt;Bobcat release&lt;/strong&gt;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Mon, 17 Apr 2023 00:00:00 </pubDate></item><item><title>Spec Lite: Add support for extending attached (in-use) volumes</title><link>http://specs.openstack.org/openstack/glance-specs/specs/2023.1/approved/glance_store/cinder_extend_in-use_volumes.html</link><description>

&lt;dl class="field-list"&gt;
&lt;dt class="field-odd"&gt;project&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;glance_store&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;problem&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;When creating an image in cinder store, we perform a series of
API calls to cinder creating, attaching, detaching, extending etc
the volume. The sequence of operations performed to copy image into
the volume are, attach the volume, copy image contents into the
volume (until we’ve space left in volume), detach the volume,
see if extend is required (if image is bigger than current volume
size) and perform it. We repeat the operations until the whole
image is copied into the volume.
The part where we detach the volume, extend and attach it again is
very inefficient as we’ve to do it for every 1GB of image. For some
backends, cinder supports extending attached (in-use) volumes and
we should use that to optimize the image create operation.
Cinder backends that support extend in-use volumes:
&lt;a class="reference external" href="https://docs.openstack.org/cinder/latest/reference/support-matrix.html#operation_online_extend_support"&gt;https://docs.openstack.org/cinder/latest/reference/support-matrix.html#operation_online_extend_support&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Another issue noticed related to this is, since cinder only supports
extend and not shrink, we end up with extending the volume 1 GB
at a time and eventually taking more time to create large images.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;solution&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;We will introduce a new config option,
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cinder_do_extend_attached&lt;/span&gt;&lt;/code&gt; which will be a boolean option.
Operators can set it to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;true&lt;/span&gt;&lt;/code&gt; if the cinder backend they are
using supports extending attached volumes. The default value will
be &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;false&lt;/span&gt;&lt;/code&gt;.
If we have &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cinder_do_extend_attached&lt;/span&gt;&lt;/code&gt; set to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;true&lt;/span&gt;&lt;/code&gt;, we will
call the cinder &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os-extend&lt;/span&gt;&lt;/code&gt; API with microversion &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;3.42&lt;/span&gt;&lt;/code&gt; that
will allow us to extend the attached volume.
Finally, we will call the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;extend_volume&lt;/span&gt;&lt;/code&gt; method of os-brick to
instruct the kernel to resize the volume on the host.&lt;/p&gt;
&lt;p&gt;Additional efforts:&lt;/p&gt;
&lt;p&gt;To address the concern related to 1 GB resize, cinder store already
has handling of size, if correctly passed by glance, we initialize
the volume size with the image size avoiding unnecessary extend
operations. So glance needs to be updated to pass correct image
size to cinder store.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;impacts&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;None&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;alternatives&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;None&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;timeline&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;2023.1&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;link&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&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_store/+/843103"&gt;https://review.opendev.org/c/openstack/glance_store/+/843103&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/glance_store/+/868742"&gt;https://review.opendev.org/c/openstack/glance_store/+/868742&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;reviewers&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;Abhishek Kekane, Brian Rosmaita, Dan Smith, Erno Kuvaja&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;assignee&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;Rajat Dhasmana (whoami-rajat)&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
</description><pubDate>Thu, 29 Dec 2022 00:00:00 </pubDate></item><item><title>2023.1 Project Priorities</title><link>http://specs.openstack.org/openstack/glance-specs/priorities/2023.1-priorities.html</link><description>
&lt;span id="priorities"/&gt;
&lt;p&gt;TODO(pdeore): fill this in after the PTG&lt;/p&gt;
</description><pubDate>Thu, 01 Sep 2022 00:00:00 </pubDate></item><item><title>Spec Lite: Add region_name parameter to s3 store</title><link>http://specs.openstack.org/openstack/glance-specs/specs/2023.1/approved/glance_store/add-region_name-s3.html</link><description>

&lt;dl class="field-list simple"&gt;
&lt;dt class="field-odd"&gt;project&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;glance_store&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;problem&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;The current s3 driver determine region_name from amazon endpoints,
but some operators are using an s3 compatible API which is not from
amazon.
In such situation, the region_name parameter cannot be guessed from
endpoints and result beeing set to None.
When region_name=None is given to instanciate the s3 client, the
internal boto3 code is then using a default region_name which is
wrong (like us-west-1).&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;solution&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;We need to add a new parameter s3_store_region_name in glance
config so that we can use this value instead of guessing it from
s3_store_host.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;impacts&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;None&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;assignee&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;Arnaud Morin &amp;lt;&lt;a class="reference external" href="mailto:arnaud.morin%40ovhcloud.com"&gt;arnaud&lt;span&gt;.&lt;/span&gt;morin&lt;span&gt;@&lt;/span&gt;ovhcloud&lt;span&gt;.&lt;/span&gt;com&lt;/a&gt;&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
</description><pubDate>Mon, 22 Aug 2022 00:00:00 </pubDate></item><item><title>Provision for immediate caching of an image</title><link>http://specs.openstack.org/openstack/glance-specs/specs/zed/approved/glance/instant_caching.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/glance/+spec/instant_caching"&gt;https://blueprints.launchpad.net/glance/+spec/instant_caching&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Provision for immediate caching of a given image on a particular glance node.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;In Yoga we have added support for caching related operations under V2 API, but
still we need to depend on existing periodic job to cache the actual image.
This means user/deployer/admin needs to wait until next periodic job to run
for caching of an actual image. Even though default time for periodic job is
300 seconds (5 minutes) it may vary deployment wise and the user has to wait
until the actual image is cached.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;We are proposing to remove existing periodic job from glance-api and modify
existing &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PUT&lt;/span&gt; &lt;span class="pre"&gt;/v2/cache/{image_id}&lt;/span&gt;&lt;/code&gt; API which will queue an image for caching
and start caching it immediately. If any existing instant caching operation is
in progress then the latest image will be added to the queue so that it will
be picked up for caching as soon as previous operation completes. User can use
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt; &lt;span class="pre"&gt;/v2/cache&lt;/span&gt;&lt;/code&gt; API call to see the size of the queue.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Instead of modifying existing API, we can add a new POST API which will start
immediate caching of specified image. We can use existing policy &lt;cite&gt;cache_image&lt;/cite&gt;
so that user with appropriate permissions can perform this operation. To make
the policy compatible with secure RBAC we need to pass required parameters
like ImageTarget while enforcing the policy. It is recommended to keep
&lt;cite&gt;cache_image&lt;/cite&gt; operation limited to admin use only.&lt;/p&gt;
&lt;p&gt;Another alternative solution could be, instead of removing the old periodic
job, the new API should trigger the periodic job instantly to cache all the
images rather than just caching a specified image at a time. This
solution need to be thread safe as there might be a chance of existing
periodic job is already running or new periodic job will start running while
we trigger the same via API.&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;Caching is and will remain local to each glance node and as this command
will be executed remotely, operator needs to know the direct URL of
each glance node which are behind the load balancer. Operator needs to
provide this direct URL to glanceclient so that client should hit
particular node to trigger immediate caching on that node.&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;dansmith or abhishekk&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;dt&gt;Reviewers:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;cyril-roelandt/rosmaita/jokke/pdeore/mrjoshi&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 existing API (PUT /v2/cache/{image_id})&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Remove the ‘cache_prefetcher_interval’ config option and related tests.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Modify documentation, update API reference&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Tempest coverage for Caching operations&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;All new cache API should be tested using 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;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;The API documentation will need to be updated&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Need to update Cache documentation as well with new information&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://docs.openstack.org/glance/victoria/admin/cache.html"&gt;https://docs.openstack.org/glance/victoria/admin/cache.html&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
</description><pubDate>Wed, 20 Apr 2022 00:00:00 </pubDate></item><item><title>Expanding stores-info detail for other stores</title><link>http://specs.openstack.org/openstack/glance-specs/specs/zed/approved/glance/expanding-stores-detail.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/glance/+spec/expanding-stores-detail"&gt;https://blueprints.launchpad.net/glance/+spec/expanding-stores-detail&lt;/a&gt;&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;In Yoga release we added a new API (GET /v2/info/stores/detail) which exposes
the store specific details of a store.  At the moment the Discovery API only exposes
the store details and properties of the RBD backend. We want to make the API more
generic and  expose details of  other stores also.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;We will be extending the functionality of Discovery (GET /v2/info/stores/detail) API
which will expose the store specific details about the store like store type and other
specific store properties of other stores like cinder, swift, filesystem etc.
Options that can be beneficial to be exposed for different stores :&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Cinder: cinder_volume_type&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Filesystem: filesystem_store_dir, chunk_size, thin_provisioning, filesystem_store_dirs&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Swift: container, obj_size and chunk_size&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;S3: s3_store_large_object_size, s3_store_large_object_chunk_size, s3_store_thread_pools&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We will use the existing method &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;get_store_from_store_identifier&lt;/span&gt;&lt;/code&gt; which returns
the store class instance and will utilize it to fetch the store specific information
to return it via API.&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;With this new implementation, we will now be returning the “properties” value for other
stores(apart from RBD).&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;GET /v2/info/stores/detail&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The output will be as follows:&lt;/p&gt;
&lt;div class="highlight-python 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;"stores"&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;"reliable"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"rbd"&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;"Reliable RBD store"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"default"&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;"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;"pool"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"pool1"&lt;/span&gt;
                &lt;span class="s2"&gt;"chunk_size"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;65553&lt;/span&gt;
                &lt;span class="s2"&gt;"thin_provisioning"&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="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;"cheap"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"file"&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;"Cheap file store"&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;"datadir"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"fdir"&lt;/span&gt;
                &lt;span class="s2"&gt;"chunk_size"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;65553&lt;/span&gt;
                &lt;span class="s2"&gt;"thin_provisioning"&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="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;"fast"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"cinder"&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;"Fast Cinder Store"&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;"volume_type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"volume1"&lt;/span&gt;
                &lt;span class="s2"&gt;"use_multipath"&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="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;"slow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"swift"&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;"Slow Swift store"&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;"container"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"container1"&lt;/span&gt;
                &lt;span class="s2"&gt;"obj_size"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;52428&lt;/span&gt;
                &lt;span class="s2"&gt;"chunk_size"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;204800&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;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;This API does expose some additional sensitive information, but only to admins,
consistent with other things we already expose.&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;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;mrjoshi, whoami-rajat&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;Fetch details from the specific store/backed and return it in 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 Tests&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;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;Add documentation providing details about the properties exposed for each store&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://review.opendev.org/c/openstack/glance-specs/+/817391"&gt;https://review.opendev.org/c/openstack/glance-specs/+/817391&lt;/a&gt;
&lt;a class="reference external" href="https://review.opendev.org/c/openstack/glance/+/824438"&gt;https://review.opendev.org/c/openstack/glance/+/824438&lt;/a&gt;&lt;/p&gt;
&lt;/section&gt;
</description><pubDate>Tue, 29 Mar 2022 00:00:00 </pubDate></item><item><title>Zed Project Priorities</title><link>http://specs.openstack.org/openstack/glance-specs/priorities/zed-priorities.html</link><description>
&lt;span id="zed-priorities"/&gt;
&lt;p&gt;TODO(abhishekk): fill this in after the PTG&lt;/p&gt;
</description><pubDate>Tue, 15 Feb 2022 00:00:00 </pubDate></item><item><title>Spec Lite: Add ability to purge all needed rows by glance-manage script.</title><link>http://specs.openstack.org/openstack/glance-specs/specs/zed/approved/glance/purge_all_rows.html</link><description>

&lt;dl class="field-list simple"&gt;
&lt;dt class="field-odd"&gt;project&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;glance&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;problem&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;When a user wants to purge all deleted rows they use
“glance-manage db purge” and “glance-manage purge_images_table”.
A user never knows how many deleted rows are still in a table.
So they need to launch the script many times until the script reports
that 0 rows were deleted in every table. It’s inconvenient.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;solution&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;use the same notation as with our other limits on “–max-rows” when
set to -1 it would purge them all rather than the default 100 lines
or what ever specified on the command line.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;impacts&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;None&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;how&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;if “–max-rows” equals -1 the script purges deleted rows without number
limit.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;alternatives&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;None&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;timeline&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;Zed&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;link&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;&lt;a class="reference external" href="https://review.opendev.org/c/openstack/glance/+/813691"&gt;https://review.opendev.org/c/openstack/glance/+/813691&lt;/a&gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;reviewers&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;Abhishek Kekane, Cyril Roelandt&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;assignee&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;mitya-eremeev-2&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
</description><pubDate>Mon, 29 Nov 2021 00:00:00 </pubDate></item><item><title>Expose store specific information</title><link>http://specs.openstack.org/openstack/glance-specs/specs/yoga/approved/glance/expose-store-specific-info.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/glance/+spec/expose-store-specific-info"&gt;https://blueprints.launchpad.net/glance/+spec/expose-store-specific-info&lt;/a&gt;&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;When we upload a volume from cinder’s RBD backend as an image to glance’s
RBD backend, the generic code path to copy data chunk by chunk is executed,
which makes the operation very slow. This can be optimized by using COW cloning
for rbd backends and for this Cinder requires store type and rbd specific store
info from glance side.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;At the moment the Discovery (GET /v2/info/stores) API provides the list of
multiple-backend present and the default store but not the type of the stores.&lt;/p&gt;
&lt;p&gt;We will be extending the functionality of Discovery (GET /v2/info/stores) API
by adding a new API (GET /v2/info/stores/detail) which will expose the store
specific details about the store like store type and other specific store
properties.&lt;/p&gt;
&lt;p&gt;Since the store specific information is mostly intended for other services
(like cinder) or operators to consume and not for end users, this operation
will be admin only and we will introduce a new policy &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;stores_info_detail&lt;/span&gt;&lt;/code&gt;,
that will default to admin only rule, to restrict this for non-admin users.
In future, when the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;service&lt;/span&gt;&lt;/code&gt; role will be in place in keystone to facilitate
service to service interaction, this policy rule will be adjusted accordingly.&lt;/p&gt;
&lt;p&gt;We will use the existing method &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;get_store_from_store_identifier&lt;/span&gt;&lt;/code&gt; which returns
the store class instance and will utilize it to fetch the store specific information
to return it via API in a defined format. For more details see &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;We are going to add a new API &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt; &lt;span class="pre"&gt;/v2/info/stores/detail&lt;/span&gt;&lt;/code&gt; which will return
the store details like store type and store specific properties.
It will be validated by the new policy rule &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;stores_info_detail&lt;/span&gt;&lt;/code&gt; which defaults
to admin only and then the detailed info related to the stores will be returned.&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;GET /v2/info/stores/detail&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The output will be as follows:&lt;/p&gt;
&lt;div class="highlight-python 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;"stores"&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;"reliable"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"rbd"&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;"More expensive store with data redundancy"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"default"&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;"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;"pool"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"pool1"&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;"cheap"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"file"&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;"Less expensive store for seldom-used images"&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="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;We are going to add a field &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;type&lt;/span&gt;&lt;/code&gt; to specify the type of store.
Also we will add a field &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;properties&lt;/span&gt;&lt;/code&gt; which will be a JSON object type and
contain the store specific properties. For the current usecase we are only
going to add RBD store info and leave the properties for other stores as empty
JSON objects &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;{}&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;Since this optimization skips the writing of image that happens on the glance side,
it will also skip the checksum and hash value calculated in that scenario.
Due to the above case, we will add a new config option on the cinder side to
enable/disable this optimization. By default, it will be disabled.&lt;/p&gt;
&lt;p&gt;Another case is we require direct-url and image locations in the image detail
response to take benefit of any optimization in nova-glance or cinder-glance
interactions which is a security concern described in OSSN-0065.&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 optional parameter &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;--detail&lt;/span&gt;&lt;/code&gt; will be added to the stores info command on
glanceclient side.&lt;/p&gt;
&lt;p&gt;The parameter will accept boolean values. If &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;True&lt;/span&gt;&lt;/code&gt;, it will expose store specific
information else will show the non-detailed information about stores as it works currently.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Stores Detail: &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance&lt;/span&gt; &lt;span class="pre"&gt;stores-info&lt;/span&gt; &lt;span class="pre"&gt;--detail&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;
&lt;dl class="option-list"&gt;
&lt;dt&gt;&lt;kbd&gt;&lt;span class="option"&gt;--detail&lt;/span&gt;&lt;/kbd&gt;&lt;/dt&gt;
&lt;dd&gt;&lt;p&gt;With sufficient permissions, display additional information about the stores.&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&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;Uploading volume to image incase of cinder RBD to glance RBD will be
significantly improved.&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;Image size&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;2GB&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;3GB&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;5GB&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;Time without COW clone&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;1min17Sec&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;1min15Sec&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;2min49Sec&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Time with COW clone&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;1.29Sec&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;2.32Sec&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;1.63Sec&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td/&gt;
&lt;td&gt;&lt;p&gt;&lt;strong&gt;-98%&lt;/strong&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;strong&gt;-97%&lt;/strong&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;strong&gt;-99%&lt;/strong&gt;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&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="id1"&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;mrjoshi, whoami-rajat&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 an optional parameter &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;--detail&lt;/span&gt;&lt;/code&gt; in the stores-info command on the
glanceclient side.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add a new API to glance &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt; &lt;span class="pre"&gt;/v2/info/stores/detail&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create a new policy &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;stores_info_detail&lt;/span&gt;&lt;/code&gt; that will default to admin only
rule and enforce it if detail flag is passed.&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;Functional Tests&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;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;A new section for the new API &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt; &lt;span class="pre"&gt;/v2/info/stores/detail&lt;/span&gt;&lt;/code&gt; needs to be added
in the api-ref.&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://review.opendev.org/c/openstack/cinder-specs/+/810363"&gt;https://review.opendev.org/c/openstack/cinder-specs/+/810363&lt;/a&gt;&lt;/p&gt;
&lt;/section&gt;
</description><pubDate>Wed, 10 Nov 2021 00:00:00 </pubDate></item><item><title>Glance Quota API</title><link>http://specs.openstack.org/openstack/glance-specs/specs/yoga/approved/glance/quota-api.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/glance/+spec/quota-api"&gt;https://blueprints.launchpad.net/glance/+spec/quota-api&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;In the Xena cycle, Glance gained quota support. Through the use of
unified limits, it was possible to implement this without introducing
an API. However, for full functionality and a better user experience,
Glance should expose an API so that users can see their current usage
(and limit) instead of just receiving an error when they go over. This
spec outlines the addition of that API.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Glance users can now be limited by quotas set by the operator, but are
unable to see their current usage (and limits) in any way other than
the error message they receive when they go over. An API is required
to expose the limit and usage to the user.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Glance already has an information discovery API, which will be used as
a base for exposing the information: a new route for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/info/quota&lt;/span&gt;&lt;/code&gt;
will be added. Information exposed will include the limit and current
usage for each quota type for the calling user. If a quota is
disabled, then the limit for that element will be exposed as &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;-1&lt;/span&gt;&lt;/code&gt; in
accordance with Keystones “unlimited” sentinel notation.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;We could continue to have no API.&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 spec includes a single new endpoint:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;New API&lt;/strong&gt;&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;List quotas&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Common Response Codes&lt;/strong&gt;&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Success: &lt;cite&gt;200 OK&lt;/cite&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Failure: &lt;cite&gt;400 Bad Request&lt;/cite&gt; with details&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Forbidden: &lt;cite&gt;403 Forbidden&lt;/cite&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;[New API] List quotas&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;List all quotas available for the user:&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&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;v2&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;quotas&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="s2"&gt;"quotas"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;"image_size_total"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="s2"&gt;"usage"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s2"&gt;"limit"&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="s2"&gt;"image_staging_total"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="s2"&gt;"usage"&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;"limit"&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="s2"&gt;"image_count_total"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="s2"&gt;"usage"&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;"limit"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="s2"&gt;"image_count_uploading"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="s2"&gt;"usage"&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;"limit"&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="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 codes:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;200 – Upon authorization and successful request. The response body
contains the JSON payload with quota information.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;400 – Quota information is not available (likely due to
configuration or backend error)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;403 – Permission denied&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;JSON schema for the response:&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;'usage'&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;'array'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'items'&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;'additionalProperties'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'validation_data'&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;'additonalProperties'&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="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;'usage'&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;'integer'&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
                &lt;span class="s1"&gt;'limit'&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;'integer'&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;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;The other information discovery APIs do not check any policy, and none
will be added for this new quota API. It is assumed that there is no
reason to disable a user’s view of their own usage and limit
information. The former is already visible by listing current
resources and doing the math.&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 glanceclient and openstackclient change will be required to expose
this to interactive users.&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;No impact beyond the requirements for enabling quotas in general.&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;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;Implement the API with unit/functional tests&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Document the API in api-ref&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Write a tempest test to check the API&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Implement support in OpenstackClient&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Implement support in glanceclient&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Client 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;This will require a bump to an (already-released) new version of
oslo.limit in order to query the limits without active enforcement.&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 in Glance. Tempest tests against the
existing quota-enabled jobs.&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 need updating, as well as usage information for the
interactive clients.&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/glance-specs/specs/xena/approved/glance/glance-unified-quotas.html"&gt;https://specs.openstack.org/openstack/glance-specs/specs/xena/approved/glance/glance-unified-quotas.html&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
</description><pubDate>Tue, 09 Nov 2021 00:00:00 </pubDate></item><item><title>Provision to append the new metadef-tags with the existing metadef-tags</title><link>http://specs.openstack.org/openstack/glance-specs/specs/yoga/approved/glance/append-tags.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/glance/+spec/append-tags"&gt;https://blueprints.launchpad.net/glance/+spec/append-tags&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;In the Glance API we are not having the provision to append the new metadef-tags
with the existing metadef-tags. Introducing a new optional parameter would help
the user to select whether to append the tags or to go with current behaviour i.e.
overwrite the existing tags.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Our md-tag-create-multiple (POST /v2/metadefs/namespaces/{namespace_name}/tags) API
overwrites existing tags for specified namespace rather than creating new one in
addition to the existing tags. Whereas if you try to create different tags using
md-tag-create (POST /v2/metadefs/namespaces/{namespace_name}/tags/{tag_name}) it is
adding new tag in addition to existing ones.
So we should have consistency between the two APIs i.e. the ability to append
the tags in md-tag-create-multiple API.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;At the moment the glance API only overwrites the existing tags with the
newly created tags i.e. the original/default behaviour. The new behaviour suggests
to append the new tags with the existing ones.
The goal is to provide an optional header &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;X-Openstack-Append&lt;/span&gt;&lt;/code&gt; that takes boolean
values, which will default to the original behaviour. If not present, the behavior is
the same as passing &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;X-Openstack-Append:&lt;/span&gt; &lt;span class="pre"&gt;False&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;If header is present then we are going to append new tags else keep the old behavior.&lt;/p&gt;
&lt;p&gt;In addition to this we will add an optional parameter at glanceclient side
which will default to the original behaviour and if the user wants to append the
new tags it can be by changing the value of parameter to True.&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;We are going to change the API and will be adding a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;X-Openstack-Append&lt;/span&gt;&lt;/code&gt; in the header.
The rest API look like this:&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 /v2/metadefs/namespaces/{namespace_name}/tags&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Header fields:&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;X&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;Append&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;The &amp;lt;boolean&amp;gt; ‘X-Openstack-Append’ is an optional header, refers to appending the tags
to the existing tags.
It takes boolean values if True then it will append the tags ,if False it will
overwrite the tags, default value is False.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Example curl usage:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;curl -i -X POST -H "X-Auth-Token: $token" -H "X-Openstack-Append: False"
-H "Content-Type: application/json"
-d '{"tags": [{"name": "sample1"}, {"name": "sample2"}]}'
 $image_url/v2/metadefs/namespaces/{namespace_name}/tags
&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;We will add an optional parameter &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;--append&lt;/span&gt;&lt;/code&gt; to the glanceclient command
md-tag-create-multiple to provide the facility of appending the tags.
If the parameter is present then it will the append the tags to existing ones
else will overwrite the existing tags.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Create multiple tags: &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance&lt;/span&gt; &lt;span class="pre"&gt;md-tag-create-multiple&lt;/span&gt; &lt;span class="pre"&gt;&amp;lt;NAMESPACE&amp;gt;&lt;/span&gt; &lt;span class="pre"&gt;--names&lt;/span&gt; &lt;span class="pre"&gt;&amp;lt;NAMES&amp;gt;&lt;/span&gt; &lt;span class="pre"&gt;[--delim&lt;/span&gt; &lt;span class="pre"&gt;&amp;lt;DELIM&amp;gt;]&lt;/span&gt; &lt;span class="pre"&gt;--append&lt;/span&gt;&lt;/code&gt;&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&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;mrjoshi&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 boolean parameter in the header and change API
functionality as per parameter’s value&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add an optional parameter &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;--append&lt;/span&gt;&lt;/code&gt; at the client side&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add unit test coverage for checking the functionality.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add tempest test&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 unit tests coverage for testing the
functionality based on the header.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;The documentation needs to be updated with the new API behaviour.&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://bugs.launchpad.net/glance/+bug/1939169"&gt;https://bugs.launchpad.net/glance/+bug/1939169&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://review.opendev.org/c/openstack/glance/+/804966"&gt;https://review.opendev.org/c/openstack/glance/+/804966&lt;/a&gt;
&lt;a class="reference external" href="https://review.opendev.org/c/openstack/python-glanceclient/+/813591"&gt;https://review.opendev.org/c/openstack/python-glanceclient/+/813591&lt;/a&gt;&lt;/p&gt;
&lt;/section&gt;
</description><pubDate>Mon, 11 Oct 2021 00:00:00 </pubDate></item><item><title>Yoga Project Priorities</title><link>http://specs.openstack.org/openstack/glance-specs/priorities/yoga-priorities.html</link><description>
&lt;span id="yoga-priorities"/&gt;
&lt;p&gt;TODO(abhishekk): fill this in after the PTG&lt;/p&gt;
</description><pubDate>Thu, 02 Sep 2021 00:00:00 </pubDate></item><item><title>Spec Lite: Remove sqlalchemy-migrate</title><link>http://specs.openstack.org/openstack/glance-specs/specs/xena/approved/glance/remove-sqlalchemy-migrate.html</link><description>

&lt;dl class="field-list simple"&gt;
&lt;dt class="field-odd"&gt;project&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;glance&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;problem&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;The sqlalchemy-migrate library is unmaintained and has been
deprecated in favour of alembic. It is not compatible with sqlalchemy
2.0 and is issuing many warnings suggesting Python 3.10 compatibility
may be in doubt. Glance switched to alembic for new migrations during
the Ocata cycle and no longer needs to carry the old
sqlalchemy-migrate-based migrations.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;solution&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;Remove the sqlalchemy-migrate-based migrations and related tooling.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;impacts&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;None. Users coming from a pre-Ocata deployment will need to deploy a
pre-Xena glance before deploying Xena, but that’s standard practice
anyway.&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;dl class="field-list simple"&gt;
&lt;dt class="field-odd"&gt;timeline&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;Xena milestone 3&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;link&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;&lt;a class="reference external" href="https://review.opendev.org/c/openstack/glance/+/760411"&gt;https://review.opendev.org/c/openstack/glance/+/760411&lt;/a&gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;assignee&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;stephenfin&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
</description><pubDate>Tue, 13 Jul 2021 00:00:00 </pubDate></item><item><title>Spec Lite: Policy tests refactroing</title><link>http://specs.openstack.org/openstack/glance-specs/specs/xena/approved/glance/policy-tests-refactoring.html</link><description>

&lt;dl class="field-list simple"&gt;
&lt;dt class="field-odd"&gt;project&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;Glance&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;problem&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;At the moment our unit and functional tests are referring to
policy.yaml located in &lt;cite&gt;glance/tests/etc&lt;/cite&gt; of the project
repository. As now we are putting efforts into refactoring the
policy layer in glance we should be testing our defaults
except where we want to test something specifically different.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;solution&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;Instead of using policies from policy.yaml file we should be
testing our defaults except where we want to test something
specifically different.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;impacts&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;None&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;alternatives&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;None&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;timeline&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;Xena Milestone-2&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;reviewers&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;Steap, rosmaita, pdeore&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;assignee&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;abhishek-kekane, dansmith&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
</description><pubDate>Wed, 23 Jun 2021 00:00:00 </pubDate></item><item><title>Policy Layer Refactoring</title><link>http://specs.openstack.org/openstack/glance-specs/specs/xena/approved/glance/glance-policy-refactoring.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/glance/+spec/policy-refactor"&gt;https://blueprints.launchpad.net/glance/+spec/policy-refactor&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;During implementation of V2 Image API in glance an Onion layered architecture
was introduced. The reason behind implementing the layered architecture was to
avoid regression in any layer if either of the layer is modified. Glance has
a separate layer for Policy injections which is closer to database rather than
API. This spec will act as a Master specification for policy refactoring and
have several spec-lite’s to explain respective implementation details.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;The current policy enforcement occurs in Policy layer. As such, it is
conceptually tied to the objects implemented in the Glance architecture. A
problem with this design, which has only revealed itself as the v2 API has
matured, is that operators want to use policies to control who can make API
calls (as they can with most other OpenStack services). In Glance, however,
policies directly affect the objects dealt with internally by Glance, and only
indirectly affect who can make API calls. This makes it difficult for operators
to configure Glance.&lt;/p&gt;
&lt;p&gt;In addition, while implementing Secure RBAC in glance we also noticed that
certain API calls enforce multiple policies down the layer. For example
in case of &lt;cite&gt;modify_image&lt;/cite&gt; policy it enforces &lt;cite&gt;get_image&lt;/cite&gt; policy which
enforces &lt;cite&gt;get_image_location&lt;/cite&gt; policy. This can be confusing for operators
modifying the policy for &lt;cite&gt;modify_image&lt;/cite&gt; and wondering why it hasn’t taken
effect if the &lt;cite&gt;get_image&lt;/cite&gt; policy or &lt;cite&gt;get_image_policy&lt;/cite&gt; short-circuits the
operation.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;We need a better way of handling policies:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;One of the major proposals is to move the actual policy enforcement up to
the API layer so that an operator can, for example, easily restrict access
to a particular call. Most of the OpenStack projects have policy
enforcements closer to API layer, so these efforts will also put us more
in-line with the current thinking of policy enforcement.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Make &lt;cite&gt;get_*&lt;/cite&gt; policies be enforced only while showing particular resource
rather than enforcing it for each API call. For example &lt;cite&gt;get_image&lt;/cite&gt; policy
should be enforced only for showing particular image to end user and not for
other API calls such as update, delete, upload or download image.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Backward compatibility will be maintained while moving policies closer to
API layer. (NOTE: RBAC related changes are not considered here.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;At the moment our unit and functional tests are referring to policy.yaml
file from the test repo, instead our default policies should be used and
overridden as and when required.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In order to test new policy changes with RBAC we need two different CI jobs
which will run our tests with old policies as well as with the new RBAC flag
enabled.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Note: Some of the above changes will have its own spec lite to further discuss
the implementation details.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Keep it as it is and use hacks while implementing other scopes of Secure RBAC.&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 changes to the REST API, but see “Other Deployer Impact” section, below.&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;Considering experimental support added for project scope realted to Secure
RBAC, operators need to understand which policies to govern and how to
configure them properly. Also, there’s likely to be some tweaking and
testing of any custom policies during upgrade to Xena (or beyond).&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 have to be more aware of policies and where policy enforcement
must happen.&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
abhishek-kekane&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;pdeore&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;Move API specific policy checks up to the API layer&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Enforce &lt;cite&gt;get_*&lt;/cite&gt; policies at API layer only&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Enforce resource specific policies close to database layer&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Policy enforcement should be compatible with secure RBAC structure&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Tests should run using default policies and not policy.yaml&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;New CI jobs to run tempest tests with and without Secure RBAC enabled&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;As explained in Work Items section our unit and functional tests need
to use our default polices in code rather than policy.yaml file. We also
need new CI jobs to run tempest tests with and without Secure RBAC
enabled.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Policies are documented in code, so the documentation will be updated as the
refactoring occurs.&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://review.opendev.org/q/topic:%22policy-poc%22+(status:open%20OR%20status:merged"&gt;https://review.opendev.org/q/topic:%22policy-poc%22+(status:open%20OR%20status:merged&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/glance/+bug/1915582"&gt;https://bugs.launchpad.net/glance/+bug/1915582&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
</description><pubDate>Wed, 16 Jun 2021 00:00:00 </pubDate></item><item><title>Spec Lite: CLI support for new cache APIs</title><link>http://specs.openstack.org/openstack/glance-specs/specs/xena/approved/python-glanceclient/cache-api-cli.html</link><description>

&lt;dl class="field-list simple"&gt;
&lt;dt class="field-odd"&gt;project&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;python-glanceclient&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;problem&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;In Xena we are deprecating &lt;cite&gt;glance-cache-manage&lt;/cite&gt; CLI utility as
we are moving caching operations under glance-api by introducing
new API endpoints for cache related operations.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;solution&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;We need to add new CLI commands; &lt;cite&gt;cache-queue&lt;/cite&gt;, &lt;cite&gt;cache-list&lt;/cite&gt;,
&lt;cite&gt;cache-delete&lt;/cite&gt;, &lt;cite&gt;cache-delete-all&lt;/cite&gt; to support new cache APIs.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;impacts&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;APIImpact, DocImpact&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;how&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;We will add new CLI interface for &lt;cite&gt;cache-queue&lt;/cite&gt;, &lt;cite&gt;cache-list&lt;/cite&gt;,
&lt;cite&gt;cache-delete&lt;/cite&gt;, &lt;cite&gt;cache-delete-all&lt;/cite&gt; commands. As caching is
local to each glance node and most of the deployments configures glance
nodes behind the load-balancers, operator/user need to pass actual
endpoint of the glance node. Existing optional command line option
&lt;cite&gt;–os-image-url&lt;/cite&gt; will be used to provide the actual endpoint to the
client. The default value for &lt;cite&gt;–os-image-url&lt;/cite&gt; can also be set to
using &lt;cite&gt;OS_IMAGE_URL&lt;/cite&gt; environment variable. If this optional parameter
is not provided while executing above new commands or is using default
value set using &lt;cite&gt;OS_IMAGE_URL&lt;/cite&gt; environment variable all of the above
commands should exit with appropriate error message.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;alternatives&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;None&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;timeline&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;Xena Milestone 2&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;link&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;&lt;a class="reference external" href="https://review.opendev.org/c/openstack/glance-specs/+/665258"&gt;https://review.opendev.org/c/openstack/glance-specs/+/665258&lt;/a&gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;reviewers&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;dansmith, abhishek-kekane, cyril-roelandt&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;assignee&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;jokke&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
</description><pubDate>Fri, 04 Jun 2021 00:00:00 </pubDate></item><item><title>Implement Unified Keystone Quotas in Glance</title><link>http://specs.openstack.org/openstack/glance-specs/specs/xena/approved/glance/glance-unified-quotas.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/glance/+spec/glance-unified-quotas"&gt;https://blueprints.launchpad.net/glance/+spec/glance-unified-quotas&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Glance currently lacks per-tenant quota capabilities, which is
something that other OpenStack projects have had for quite some
time. Especially since Glance is a key project for a working cloud,
and because it involves consumption of expensive resources, quotas are
necessary for operators to properly restrict usage. As noted in the
recent PTG, public clouds charge for every resource, and thus
per-tenant limits may be less important. However, private clouds
generally do not bill for usage, and instead rely on pre-paid quotas
for resource sharing. This work aims to implement quotas for Glance.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Glance does not have per-tenant quotas.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;As an operator of a private cloud, I need to be able to define a
quota for a tenant to avoid them consuming unlimited resources since
I do not bill them for each one.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As an operator of a cloud, I have customers of differing sizes, and
wish to use per-tenant quotas to provide “safety valve” limits on
runaway usage. Having just one global value that applies to all
users is not powerful enough to provide reasonable limits for
tenants of varying size.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Keystone has implemented something called “unified limits,” which
allows an operator to define (in Keystone) default and per-tenant
quota limits. By default the “flat” model provides a very basic
one-tenant-one-limit structure, but more complex hierarchies are
possible. These can be set using Keystone’s client (openstackclient)
utility to register, set, and update limits per tenant.&lt;/p&gt;
&lt;p&gt;By utilizing this Keystone functionality, Glance does not need to
define new APIs and client support to allow operators to set the
limits, nor is it required to build a persistence model to store them,
clean them up, etc. Instead, Glance can query the limit values from
Keystone and compare them against current/proposed usage in order to
determine if a particular resource consumption should be
allowed. Effectively, Glance needs only &lt;em&gt;enforce&lt;/em&gt; the quotas, but it
does not need to store or manage them. Limits are fetched from
Keystone automatically and per-request by the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo_limit&lt;/span&gt;&lt;/code&gt; library,
and thus quota changes take effect immediately.&lt;/p&gt;
&lt;p&gt;Adding new quota limits is relatively easy using this model. While
more can be added in the future, this spec covers the work required to
add 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;image_size_total&lt;/span&gt;&lt;/code&gt;: A limit on the storage consumed by all the
non-deleted images for the tenant. Images with multiple locations
will count as multiple usages. Specified in Mebibytes (MiB). This
will be enforced in the image upload path, as well as the import
path which are the APIs in which a user actually consumes more
storage.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;image_stage_total&lt;/span&gt;&lt;/code&gt;: A limit on the storage consumed by all the
images in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;uploading&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;importing&lt;/span&gt;&lt;/code&gt;, and any other transient
import-related states for the tenant. In order to capture space used
by copying images, we will also include active images with a
non-zero list of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_glance_importing_to_stores&lt;/span&gt;&lt;/code&gt; items. Specified
in Mebibytes (MiB). This will be enforced in the image stage path.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;image_count_total&lt;/span&gt;&lt;/code&gt;: A limit on the total number of non-deleted
images owned by the tenant. Specified as a count of images. This
will be enforced in the image create path.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;image_count_uploading&lt;/span&gt;&lt;/code&gt;: A limit on the total number of images
currently in either the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;uploading&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;saving&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;importing&lt;/span&gt;&lt;/code&gt; and
any other transient states related to upload or import by the
tenant. In order to capture images being copied, we will include
active images with a non-zero list of
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_glance_importing_to_stores&lt;/span&gt;&lt;/code&gt; items. Specified as a count of
images. This will be enforced in the image upload and stage paths,
and will provide a limit on the number of images that can be adding
external data to the system at any given point.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Since the staging area for Glance API workers is likely to be far more
constrained than the general-purpose image storage, those quotas are
separated. An operator likely wants to give a user a large amount of
image storage, which is backed by a sophisticated and distributed
backend. However, the staging area is really “temporary space” which
is used in the process of importing images, and is likely to be far
more constrained (local disk on an API worker). By allowing a separate
quota for the staging area, an operator gains the ability to provide
many TiB of space for general image storage, while restricting users
to a small number of import operations at a time. It helps to avoid a
user staging a large amount of image data and then leaving it there
for a long period of time. If staging quota is not desired, then
setting it to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;-1&lt;/span&gt;&lt;/code&gt; in Keystone signals to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo_limit&lt;/span&gt;&lt;/code&gt; that it
should be “unlimited.” By allowing for a separate count and size
staging quota, the operator can either restrict the amount of image
data, or the number of operations in progress.&lt;/p&gt;
&lt;p&gt;For the storage-related limits, the initial revision of this will
simply enforce the quota at the beginning of the relevant long-running
storage-using operation. This has the benefit of being simple and
predictable, but does make the quota enforcement “soft” in that a user
must go over the limit before they are stopped. Existing global limits
are enforced as “hard” thresholds in cases where the user provided a
size ahead of time, and can interrupt a long-running network operation
if breached. The benefit of this is that friendly users are not
allowed to exceed their limit, although users that do not provide the
size (such as when streaming an image) still require checking the
limit after the operation is complete.  The drawback of the current
behavior is that if a user exceeds the 1TiB limit at 900GiB, they will
have wasted time and network bandwidth, only to have the entire stream
discarded. Since the global limits are intended to stop gross
over usage and be large enough for any tenant, they are unlikely to be
hit normally. The per-tenant ones described here are more likely to be
hit regularly, and thus the soft behavior is chosen. Enforcing them as
hard limits during or after a transfer could be done as a follow-on
effort.&lt;/p&gt;
&lt;p&gt;Honoring these limits will be conditional based on a configuration
option. By default limit quotas will be disabled, which will most
easily facilitate upgrades. When disabled, nothing will be different
from how it is today. When enabled, Glance will fetch limits from
Keystone, expecting the operator has registered them as prescribed,
and enforce them against a user’s usage. I think ultimately it
probably makes the most sense to make that enabled by default, and
potentially eventually ultimately remove the knob entirely. Obviously,
we can keep the knob indefinitely if that is more desirable.&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. Glance has not had quotas for
this long, so we could just not add them and rely on the global
resource limits, as they are today.&lt;/p&gt;
&lt;p&gt;Another alternative is to implement quotas in Glance itself and not
utilize the Keystone unified limits functionality. This would require
new APIs, client support, and database models. It would also run
contrary to the efforts in the wider community to move towards
defining all quota limits in Keystone.&lt;/p&gt;
&lt;p&gt;We could also decide that soft quotas are not good enough and take one
of the following paths to get hard quotas:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Start requiring API clients to declare image sizes at upload time so
that we can do the quota check accurately up front.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Refactor oslo-limit to expose the details of the limits, and use
that in a refactored Image.set_data() wrapper to halt data transfer
mid-stream when the limit is exceeded.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Either of these are candidates for future work that build on top of
the work proposed in this 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;There are no additional values that need to be stored if we do
this. We already store the image size, which is what we need to count
at enforcement time for the storage-based limits. Since Keystone
stores the actual per-tenant quota limit values, we do not need to
store those.&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 some more ways to get HTTP 413 limit errors, but
since they are already possible due to the existing limits, there is
effectively no change.&lt;/p&gt;
&lt;p&gt;A future effort should add a quota usage API to allow clients to check
consumption against their limits.&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 overall security of the system, because
resource limits can be custom-tailored to each tenant instead of
relying only on global large-enough-for-anyone limits.&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 client changes are required. Actual end users may notice a
behavioral change related to their operator being able to enforce a
smaller quota on them than previously was possible (which is the goal
of this effort).&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;Querying Keystone for the limits for a tenant is not free, and will
introduce some dependency and latency. However, this interaction
(specifically with Keystone) is in the critical path for all API usage
anyway. At least initially, a configuration option will be provided to
enable this behavior, defaulting to disabled.&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 need to define the registered and actual limits for the
Glance values in Keystone prior to enabling enforcement. This is done
by registering them in keystone with default values using the
openstack client. Quotas for individual users can be then set using a
similar mechanism. All of this can be done prior to and after enabling
enforcement on the glance side.&lt;/p&gt;
&lt;p&gt;Operators upgrading from Wallaby or earlier need not do anything
specific during the upgrade, as enforcement is off by default. If the
operator wishes to utilize quotas after upgrading, they can register
the quotas and enable glance enforcement in the config at any time.&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;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;Introduce the base infrastructure for querying and checking limits
from Keystone.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;image_size_total&lt;/span&gt;&lt;/code&gt; quota enforcement to upload and import.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;image_stage_total&lt;/span&gt;&lt;/code&gt; quota enforcement to stage.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;image_count_total&lt;/span&gt;&lt;/code&gt; quota enforcement to create.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;image_count_uploading&lt;/span&gt;&lt;/code&gt; quota enforcement to stage and
upload.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Figure out what to do about ceph snapshots which show up as zero
size.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add tempest support for limits and tests for these quotas.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Implement configuring these quotas in devstack and integrate
testing into a job.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add operator docs to explain how to enable, configure and use these
quotas.&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 will require us to add &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo_limit&lt;/span&gt;&lt;/code&gt; as a dependency.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;This will require devstack support to test&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Tempest testing will be considered required for this, as the
interaction across Keystone and Glance is key to ensuring
correctness.&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 testing will be straightforward in the
tree. Tempest testing will be provided, by setting a small limit on a
tenant and then uploading a few images to ensure we run across the
each limit.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Since per-tenant quotas in Glance do not exist yet, the docs will need
to be updated to add coverage. Operators will need to know which
limits to configure in Keystone, how to do that, as well as how to
enable enforcing in Glance. Operators will also need to understand the
soft-limit nature of the size-based quotas, and how Glance’s
willingness to accept unbounded uploads impact quota enforcement.&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;Keystone unified limit docs:
&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;li&gt;&lt;p&gt;Glance Xena PTG etherpad where this was raised again recently:
&lt;a class="reference external" href="https://etherpad.opendev.org/p/xena-glance-ptg"&gt;https://etherpad.opendev.org/p/xena-glance-ptg&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Gerrit topic for implementation and tests:
&lt;a class="reference external" href="https://review.opendev.org/q/topic:%22bp%252Fglance-unified-quotas%22+(status:open%20OR%20status:merged"&gt;https://review.opendev.org/q/topic:%22bp%252Fglance-unified-quotas%22+(status:open%20OR%20status:merged&lt;/a&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
</description><pubDate>Mon, 26 Apr 2021 00:00:00 </pubDate></item><item><title>Xena Project Priorities</title><link>http://specs.openstack.org/openstack/glance-specs/priorities/xena-priorities.html</link><description>
&lt;span id="xena-priorities"/&gt;
&lt;p&gt;TODO(abhishekk): fill this in after the PTG&lt;/p&gt;
</description><pubDate>Thu, 04 Mar 2021 00:00:00 </pubDate></item><item><title>Distributed Image Import Support</title><link>http://specs.openstack.org/openstack/glance-specs/specs/wallaby/approved/glance/distributed-image-import.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/glance/+spec/distributed-image-import"&gt;https://blueprints.launchpad.net/glance/+spec/distributed-image-import&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Glance is moving towards supporting rich operations on images, mostly
during create time, via the import mechanism. This opens the door to
things like metadata injection, format conversion, and copying between
stores. Currently in order for this to work for what the user would
consider the closest analog to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;image-upload&lt;/span&gt;&lt;/code&gt; (which is the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance-direct&lt;/span&gt;&lt;/code&gt; import method), the API nodes require access to
shared storage which is a real blocker to adoption by deployers, and
is the subject of this spec.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Currently, when images are uploaded via the import mechanism, they are
stored in a special area called “staging.” This is implemented under
the covers as a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance_store&lt;/span&gt;&lt;/code&gt; but it must be a locally-accessible
directory on the host filesystem. When using multiple API worker nodes
(as any real deployment would), the staging directories of all worker
nodes must be shared (i.e. mounted on a common NFS server) in order to
support the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance-direct&lt;/span&gt;&lt;/code&gt; import method. This is obviously a
problem for HA, performance, and a non-starter for any arrangement
where some glance API workers are located in remote sites.&lt;/p&gt;
&lt;p&gt;In order to get an image from zero to usable with a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance-direct&lt;/span&gt;&lt;/code&gt;
import, there are multiple API requests that are required. One of
these is the “staging” of the image data, which is followed by an
“import” operation which moves the data from the staging area to its
final destination(s). In a multi-node load-balanced scenario, the
“stage” operation will almost definitely hit a different worker than
the “import” operation, which will result in the latter not having
access to the staged image data in its staging store, and thus a
failure.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;The goal of the work outlined by this spec, is to allow the API
workers to keep their staging store directories local and
un-shared, but still enabling the import operation to work. In order
to do this, we will:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Record the URL by which the staging worker can be reached from the
other workers in the database, and&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Proxy the import request to the host that has it staged via that
URL if the image is not local.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Any delete request while the image is staged also needs to be
proxied, to ensure that the temporary file is deleted from the
staging directory on the appropriate node.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;With the above change, we can eliminate the need for shared storage
between the API worker nodes, allowing them to be isolated from an HA
point of view, as well as distributed geographically. It requires very
little actual change, as the non-local recipient node simply proxies
the request it receives to the node that has it staged and returns the
result. Both the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;import&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;delete&lt;/span&gt;&lt;/code&gt; operations are quick and do
not require a chained client -&amp;gt; proxy -&amp;gt; destination arrangement to
persist for long periods of time.&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. We could continue to require
shared storage for the staging area between the API nodes to support
the import feature. We could also direct users to use image uploading
instead of importing in cases where a shared directory is not
feasible.&lt;/p&gt;
&lt;p&gt;Another alternative would be to do effectively the same thing as
described here, but over RabbitMQ or some other RPC mechanism. That
has the disadvantage of needing additional supporting infrastructure
that glance does not currently require today, as well as new code to
handle sending and receiving those RPC calls and directing them to the
appropriate internal actions.&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;In order to do this, we only need to store one new piece of
information, and only for a short period of time. That is the direct
URL of the API worker node that has staged an image. When the image is
finally imported (which usually happens immediately after staging),
that URL is no longer needed (nor relevant).&lt;/p&gt;
&lt;p&gt;Initially, this implementation will use the reserved and
quota-independent &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_glance&lt;/span&gt;&lt;/code&gt; namespace to store the URL in the
image’s &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;extra_properties&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Later, when work is done to complete the usage of the staging
directory as a proper glance store, we may be able to store the URL in
the location metadata when the staging image data is registered
there. When this happens and assuming there is an appropriate
interface to use that location metadata, the plan will be to make this
implementation use that metadata store instead.&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 proxy behavior will be done with the user’s token, as presented to
the worker that the load balancer selects. No additional authorization
is added, and that token is used to make the request to the
appropriate worker on the user’s behalf. Thus, this operation is
entirely transparent from a security perspective.&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;More users will be able to use the image import functionality after
this is implemented as operators unwilling or unable to provide shared
storage between their workers will no longer need to disable
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance-direct&lt;/span&gt;&lt;/code&gt; import for their users.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;Eliminating the use of a shared NFS (or similar) storage location for
the staging store should improve performance of upload and import,
since the staging directory can be local. It also vastly reduces the
need to move a potentially very large image back and forth over the
network multiple times in the process of doing a single image import
(reduces from a minimum of four round-trips of the image data to two).&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 may wish to enable image import after upgrading to a release
that supports this, where previously they needed to disable the
feature (or just &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance-direct&lt;/span&gt;&lt;/code&gt;. They will need to configure each
API worker with an additional element indicating the direct URL by
which they can be reached, and ensure that API nodes are able to
communicate with each other in this way.&lt;/p&gt;
&lt;p&gt;Deployers that currently support import via shared storage may want to
quiesce image activity while they split the workers from the shared
storage location to local directories.&lt;/p&gt;
&lt;p&gt;Deployers wishing to keep the shared storage for image staging may
choose to do so with no impact or action required.&lt;/p&gt;
&lt;p&gt;Deployers wishing to keep the import feature (or just the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance-direct&lt;/span&gt;&lt;/code&gt; method) disabled, may also do so with no impact or
action required.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;When we move to the location-based metadata approach detailed above,
we will need to change the API from using the image
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;extra_properties&lt;/span&gt;&lt;/code&gt; dict to passing that information through to the
store routines. It is expected that this will be less than ten lines
of code.&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;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Build a mechanism by which we can use the user’s authorization
token to make an outbound call to another service&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add a configuration element allowing the operators to teach the API
workers what their externally-visible URL is.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Make the API workers record their own URL on the image during the
image &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;stage&lt;/span&gt;&lt;/code&gt; operation.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Make the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;import&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;delete&lt;/span&gt;&lt;/code&gt; operations proxy to the
appropriate URL when it is determined appropriate to do so.&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;Devstack needs support for starting additional glance workers in
order to properly test this.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Tempest needs support for looking up alternative image services in
the service catalog.&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 for the API behaviors and import tasks are sufficient, as
the changes are minimal.&lt;/p&gt;
&lt;p&gt;Functional tests for the image proxying.&lt;/p&gt;
&lt;p&gt;A set of tempest tests that stage and import/delete images on
different glance workers with separate staging directories will be
written to ensure CI coverage for this behavior in a realistic sense.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Since this just makes something work that did not before, no large
amount of documentation will need to be written. As mentioned above,
deployers will have one new config option to set on API nodes as well
as network and firewall considerations to address in order for this to
work, which will be covered in the documentation.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;Much discussion on this was done on another spec:&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/glance-specs/+/763574"&gt;https://review.opendev.org/c/openstack/glance-specs/+/763574&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The code implementation for this also has discussion relevant to the
topic:&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/glance/+/769976"&gt;https://review.opendev.org/c/openstack/glance/+/769976&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This was discussed at the Wallaby PTG in the glance sessions, under
the topic of “Cluster Awareness”:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://etherpad.opendev.org/p/glance-wallaby-ptg"&gt;https://etherpad.opendev.org/p/glance-wallaby-ptg&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This has been discussed in multiple glance meetings:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="http://eavesdrop.openstack.org/meetings/glance/2021/glance.2021-01-28-14.01.log.html#l-26"&gt;http://eavesdrop.openstack.org/meetings/glance/2021/glance.2021-01-28-14.01.log.html#l-26&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="http://eavesdrop.openstack.org/meetings/glance/2021/glance.2021-02-04-14.00.log.html#l-30"&gt;http://eavesdrop.openstack.org/meetings/glance/2021/glance.2021-02-04-14.00.log.html#l-30&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
</description><pubDate>Thu, 04 Feb 2021 00:00:00 </pubDate></item><item><title>New Image API /v2/images/{id}/tasks for task information</title><link>http://specs.openstack.org/openstack/glance-specs/specs/wallaby/approved/glance/expose_task_show_api.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/glance/+spec/messages-api"&gt;https://blueprints.launchpad.net/glance/+spec/messages-api&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The image service now supports importing images or copying existing images
in multiple glance stores using glance tasks, but there is restriction that
only one import operation or copy operation is permitted simultaneously on
an image to avoid race condition.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Task APIs are not available to normal users. In Victoria we have fixed
race condition while copying existing images in  multiple stores which uses
“task-id” to obtain lock on the image to prevent other import operations on
the same image. The additional image property “os_glance_import_task” will
be used to store “task id”. We are updating ‘message’ property of the task
which helps calculate time based on last updated time of task to burst the
lock as well as show how much data has been copied of that image. Copying
operation may take a long time and normal user can be clueless about when lock
will be busted or why his (other) requests are rejected without contacting to
the administrator.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-chage"&gt;
&lt;h2&gt;Proposed chage&lt;/h2&gt;
&lt;p&gt;Add new fields &lt;cite&gt;image_id&lt;/cite&gt;, &lt;cite&gt;request_id&lt;/cite&gt; and &lt;cite&gt;user&lt;/cite&gt; fields to tasks database
and new API &lt;cite&gt;/v2/images/{id}/tasks&lt;/cite&gt; which will fetch the tasks associated
with &lt;cite&gt;image_id&lt;/cite&gt; of that image and returns it to the user. This new API will
return all tasks associated with image which are not expired. This expiration
time is calculated when task reaches a final state of &lt;cite&gt;success&lt;/cite&gt; or &lt;cite&gt;failure&lt;/cite&gt;
using &lt;cite&gt;task_time_to_live&lt;/cite&gt; configuration parameter defined in glance-api.conf
file. If active task is not present for given image then it will return empty
list to user.&lt;/p&gt;
&lt;p&gt;The &lt;cite&gt;request-id&lt;/cite&gt; will effectively help user to find out what happened with
his request, why his request has been denied and which task is currently
being performed on the image.&lt;/p&gt;
&lt;p&gt;The &lt;cite&gt;user&lt;/cite&gt; field is an alternate to &lt;cite&gt;request_id&lt;/cite&gt; field. In general client tools
can access/generate request-ids but possibility normal users don’t have access
to the request-ids, in this case the &lt;cite&gt;user&lt;/cite&gt; field will help them to identify
their particular task and its status. So from now on the tasks will
have either &lt;cite&gt;request-id&lt;/cite&gt; or &lt;cite&gt;user&lt;/cite&gt; or both associated with it.&lt;/p&gt;
&lt;p&gt;More details on this API can be found in the REST API section of this spec.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Add new API endpoint /v2/messages/{task_id} which will return related task
information to the user. In this case user have to know task_id in advance.
To know the task_id in advance he needs to call GET API of image to figure out
whether &lt;cite&gt;os_glance_import_task&lt;/cite&gt; property is set on the image or not.&lt;/p&gt;
&lt;p&gt;Another alternative is to expose task show API to all the users. At the moment
task API’s are managed with two different policies; “tasks_api_access” and
then crud level policies such as “add_task”, “get_tasks” etc. So in this case
we first need to expose &lt;cite&gt;tasks_api_access&lt;/cite&gt; to all users (than admin) and then
need to expose individual level policies to end user. This might be confusing
and need to document carefully otherwise default access might be provided to
all task API’s by mistake.&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;This spec proposes to add &lt;cite&gt;image_id&lt;/cite&gt;, &lt;cite&gt;request-id&lt;/cite&gt; and &lt;cite&gt;user&lt;/cite&gt; fields to tasks
database table. Those will be null and does not require any migration script
to add this information to existing records.&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;strong&gt;New API&lt;/strong&gt;&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Show tasks associated with the given image, for example, information
about all active (not expired) tasks associated with the image.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Common Response Codes&lt;/strong&gt;&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Not Found: &lt;cite&gt;404 Not Found&lt;/cite&gt; with details.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;API Version&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;All URLS will be under the v2 Glance API.  If it is not explicitly specified
assume /v2/&amp;lt;url&amp;gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;[New API] Get tasks associated with image&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Show tasks associated with given image:&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&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;v2&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;images&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;image_id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;tasks&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;This API takes no query parameters and when authorized returns
tasks associated with given image. If it does not found any
active task associated with the image then it will return empty list to
the user.
Example of the valid response:&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;"tasks"&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;"task"&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;"ee22890e-8948-4ea6-9668-831f973c84f5"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s2"&gt;"image_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"dddddddd-dddd-dddd-dddd-dddddddddddd"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s2"&gt;"request-id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"rrrrrrr-rrrr-rrrr-rrrr-rrrrrrrrrrrr"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s2"&gt;"user"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"api_image_import"&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;"processing"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s2"&gt;"owner"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"64f0efc9955145aeb06f297a8a6fe402"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s2"&gt;"expires_at"&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;"created_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"2020-12-18T05:20:38.000000"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s2"&gt;"updated_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"2020-12-18T05:25:39.000000"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s2"&gt;"deleted_at"&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;"deleted"&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;"input"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="s2"&gt;"image_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"829c729b-ebc4-4cc7-a164-6f43f1149b17"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="s2"&gt;"import_req"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                        &lt;span class="s2"&gt;"method"&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;"copy-image"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
                        &lt;span class="s2"&gt;"all_stores"&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;"all_stores_must_succeed"&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;"backend"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
                        &lt;span class="s2"&gt;"fast"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="s2"&gt;"cheap"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="s2"&gt;"slow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="s2"&gt;"reliable"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="s2"&gt;"common"&lt;/span&gt;
                    &lt;span class="p"&gt;]&lt;/span&gt;
                &lt;span class="p"&gt;},&lt;/span&gt;
                &lt;span class="s2"&gt;"result"&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;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"Copied 15 MiB"&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;Response codes:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;200 – Upon authorization and successful request. The response body
contains the JSON payload with the known stores.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Example curl usage:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;curl -g -i -X GET -H "X-Auth-Token: $token"
    -H "Content-Type: application/octet-stream"
    $image_url/v2/images/{image_id}/tasks
&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;This proposal introduces a few other user impacts worth noting.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Glance client&lt;/strong&gt;
Ideally the glance client (CLI + REST client) should be updated in accordance
with this spec. Notably:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;CLI / API support for get task information from image.&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&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;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;p&gt;Implementation tasks may consist of:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Add expand script for adding new fields to &lt;cite&gt;tasks&lt;/cite&gt; database&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Modify &lt;cite&gt;tasks&lt;/cite&gt; data layer to use newly added fields&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Modify &lt;cite&gt;tasks&lt;/cite&gt; CRUD operations to use newly added fields&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add support for new API.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add python-glanceclient support&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add API documentation for new 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;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Need to add new unit tests for coverage&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;As mentioned in the ‘work items’ section, we’ll need to ensure the glance docs
are updated for:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;The new get tasks from image REST API.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Overall glance multi-store documentation to educate deployers on the
feature and how/when it’s used.&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;PoC - &lt;a class="reference external" href="https://review.opendev.org/c/openstack/glance/+/763739"&gt;https://review.opendev.org/c/openstack/glance/+/763739&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
</description><pubDate>Mon, 23 Nov 2020 00:00:00 </pubDate></item><item><title>Wallaby Project Priorities</title><link>http://specs.openstack.org/openstack/glance-specs/priorities/wallaby-priorities.html</link><description>
&lt;span id="wallaby-priorities"/&gt;
&lt;p&gt;TODO(abhishekk): fill this in after the PTG&lt;/p&gt;
</description><pubDate>Mon, 14 Sep 2020 00:00:00 </pubDate></item><item><title>Calculate virtual size of image</title><link>http://specs.openstack.org/openstack/glance-specs/specs/victoria/approved/glance/calculate-virtual-size.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/glance/+spec/calculate-virtual-size"&gt;https://blueprints.launchpad.net/glance/+spec/calculate-virtual-size&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;‘virtual_size’ should be set on image to avoid running &lt;cite&gt;qemu_img&lt;/cite&gt;
operations on consumer nodes.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Image has virtual_size field in images table but it is never set unless
we use taskflow &lt;cite&gt;introspect&lt;/cite&gt; to create image. Consumers of glance
like nova or cinder never consume image before calculating virtual
size, which means every time they call for image, they need to
perform &lt;cite&gt;qemu_img info&lt;/cite&gt; call to calculate the virtual size of the image.&lt;/p&gt;
&lt;section id="use-case"&gt;
&lt;h3&gt;Use Case:&lt;/h3&gt;
&lt;p&gt;‘virtual_size’ should be set on image to avoid running &lt;cite&gt;qemu_img&lt;/cite&gt;
operations on consumer 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;All supported sparse disk image formats (i.e. what glance calls disk_format)
simulate a larger virtual disk than the actual data that is stored, and
record that virtual size in metadata. We propose to add a handler for each of
the formats that can examine the chunks while streaming the image to extract
the relevant metadata to determine the virtual disk size.&lt;/p&gt;
&lt;p&gt;In glance, users can create images using two ways.
1) Create image API
2) Import image API&lt;/p&gt;
&lt;p&gt;With this change virtual size will be set to image even user tries to use any
of above two methods to create the image. Also images created by nova
(nova-snapshot except ‘direct-to-backend snapshot’) or cinder
(volume-upload-to-image) will be able to set the virtual size to image as well.&lt;/p&gt;
&lt;p&gt;NOTE: To start with we are going to calculate virtual size for images which
will have container-format &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;bare&lt;/span&gt;&lt;/code&gt; or other &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;uncompressed&lt;/span&gt;&lt;/code&gt; formats only.
Later as and when required or expected we will enhance it for other
container-formats.&lt;/p&gt;
&lt;p&gt;We will be performing this operation during uploading image data to glance
store, so for image import this will happen during the actual import phase
and not the stage phase.&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;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;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;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="reviewers"&gt;
&lt;h3&gt;Reviewers&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Core reviewer(s):&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;abhishek-kekane
jokke
rosmaita&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other reviewer(s):&lt;/dt&gt;&lt;dd&gt;&lt;p&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 handler for each of the disk-format&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add wrapper around chunked reader to calculate virtual size&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add unit tests for coverage&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add 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;Tempest test to verify that virtual size is set on image using glance,
nova snapshot and cinder upload-to-image operations.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Please refer to ‘Other deployer impact’&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://review.opendev.org/#/c/744234"&gt;https://review.opendev.org/#/c/744234&lt;/a&gt;&lt;/p&gt;
&lt;/section&gt;
</description><pubDate>Wed, 15 Jul 2020 00:00:00 </pubDate></item><item><title>Allow copying unonwned images by policy</title><link>http://specs.openstack.org/openstack/glance-specs/specs/victoria/approved/glance/copy-unowned-image.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/glance/+spec/copy-unowned-image"&gt;https://blueprints.launchpad.net/glance/+spec/copy-unowned-image&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Currently Glance has a mechanism which allows a user to copy images
between two (or more) backend stores. That only works for images that
they themselves own, which covers many of the use-cases for the
feature. However, considering different types of clouds, admins may
want users to be able to copy images between stores that they do not
own for the purposes of performance optimization and storage
efficiency.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Currently a user may only copy images that they own, and there is no
way to allow otherwise. This may lead to anti-pattern behavior, such
as downloading an image and re-uploading it so that it can be
copied. Further, it may prevent optimizations, such as a user
pre-copying a public image to a store for an edge site to improve boot
time, and CoW re-use.&lt;/p&gt;
&lt;p&gt;Specifically, Nova is working on a feature to automate storage
efficiency improvements, which rely on this ability in many
cases. Glance has supported multiple backend stores for some time, but
Nova (specifically the ceph/rbd image backend) can only cooperate with
Glance on a single ceph cluster. If multiple clusters are involved,
the worst-case scenario is that Nova ends up downloading the image
from Glance via HTTP and then uploads it to the ceph backing store as
a private-to-the-instance base image. This results in a loss of
fast-snapshot capability as well as massive storage inefficiency. See
&lt;a class="reference external" href="https://specs.openstack.org/openstack/nova-specs/specs/victoria/approved/rbd-glance-multistore.html"&gt;Nova spec for glance multistore capability&lt;/a&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Allow the &lt;cite&gt;copy-image&lt;/cite&gt; import method to check policy for permission
instead of hard-coding “is admin or owner” behavior. If granted by
policy, use an admin context to kick off the actual import task on
behalf of the requesting user.&lt;/p&gt;
&lt;p&gt;Because the “is admin or owner” behavior is baked deep into many
layers in Glance, enabling this requires some substantial work. As a
part of this process, the import task will coalesce all image
operations that may be delegated to a non-owner into a single location
to aid in auditing. If and only if the policy grants this permission
(which is only possible for &lt;cite&gt;copy-image&lt;/cite&gt;) then an admin-capable
&lt;cite&gt;ImageRepo&lt;/cite&gt; will be provided to the task for use in image property
manipulation.&lt;/p&gt;
&lt;p&gt;When the &lt;cite&gt;copy-image&lt;/cite&gt; operation is performed by a user other than the
owner through this mechanism, it should be clear that the ownership of
the image (and any new resources created in the process) remains
unchanged.&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;One alternative is to just say “sorry, only owned images may be
copied.”&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Another alternative is to have Nova store Glance admin credentials,
and effectively implement the policy check on their side, using an
admin user to copy the image if and when necessary.&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;No new APIs or return codes are added. There is a small implied
behavioral change in the form of users potentially being able to copy
images they could not before.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;As with any policy change, there is a potential for unintentional
granting of elevated permission to some users. Assuming the code is
correct, this is no different from other policy knobs. The default
policy for this operation will remain as “is admin or owner” so no
actual change will happen unless the operator so elects.&lt;/p&gt;
&lt;p&gt;There is also a potential impact with the use of an admin context for
the operation which has more power to inflict damange or leak
information than there would be otherwise. This effect is mitigated by
the following design points:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;The admin context is not passed to the import task, but rather used
only to grab an admin-capable &lt;cite&gt;ImageRepo&lt;/cite&gt; which is given to the
task.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;All of the related actions done as admin on behalf of the user are
confined to a single “actions” object for easy auditing.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;This is only (currently) applied to the &lt;cite&gt;copy-image&lt;/cite&gt; import method,
which means that (ideally) the maximum privilege escalation would be
copying an image that the user can already see to a new backend
store.&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;p&gt;No impact on Glance, but there is a net positive impact to the overall
system in the case where Nova is able to use this feature to co-locate
an image in the backend of a given remote site.&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;There are a number of changes to layers in the onion between the API
and the task itself. This is mostly around the optional &lt;cite&gt;admin_repo&lt;/cite&gt;
argument that may be passed through &lt;cite&gt;gateway&lt;/cite&gt;, &lt;cite&gt;proxy&lt;/cite&gt;, and down to
the task.&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 tests that validate the current behavior which provide a
measurement of the change as the feature takes shape.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Refactor the task creation code to allow passing an optional
&lt;cite&gt;admin_repo&lt;/cite&gt; from the API to the task.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add a &lt;cite&gt;context.elevated()&lt;/cite&gt; helper, like other projects have, which
keeps the user’s context mostly whole but with admin privileges.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Refactor the &lt;cite&gt;api_image_import&lt;/cite&gt; module to consolidate all image
operations that will need to be delegated to the &lt;cite&gt;admin_repo&lt;/cite&gt; if it
is passed from the API.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add a policy action for &lt;cite&gt;copy_image&lt;/cite&gt; which is the primary knob by
which an admin can enable this feature.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update documentation for the &lt;cite&gt;copy-image&lt;/cite&gt; method of &lt;cite&gt;image_import&lt;/cite&gt;
to explain the expectations of the admin, owner, and user delegate
when non-owners are allowed to do 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;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;New functional and unit tests will be added before the actual
changes are made to validate current behavior. Each patch along the
way will modify or augment those to test the new behavior and ensure
there are no regressions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Nova will ultimately gain a test job that deploys multiple stores,
including one rbd-backed store, and will initiate a &lt;cite&gt;copy-image&lt;/cite&gt;
import on behalf of a tempest ephemeral tenant that does not own the
public cirros 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;p&gt;Documentation is likely needed around the policy knob, explaining what
it does, how to use it, and why an admin may want to use it.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;/section&gt;
</description><pubDate>Thu, 02 Jul 2020 00:00:00 </pubDate></item><item><title>Make cinder driver compatible with multiple stores</title><link>http://specs.openstack.org/openstack/glance-specs/specs/victoria/approved/glance_store/multiple-cinder-backend-support.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/glance_store/+spec/multiple-cinder-backend-support"&gt;https://blueprints.launchpad.net/glance_store/+spec/multiple-cinder-backend-support&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;From Train onwards Glance is fully supporting configuring multiple glance
stores. Glance can configure to use cinder as a store using available cinder
driver of glance_store. Cinder makes available volume-types, which describe
the characteristics of volumes. Currently, the cinder glance_store can only
use one volume-type. The point of glance multi-store implemented in Train
is to give operators the ability to expose glance stores of differing
characteristics to end users. Even though all images will wind up in a single
cinder installation, it is possible for operators to expose different
categories of storage in cinder by creating different volume-types.
So when a cinder installation exposes multiple volume-types of differing
characteristics, what we want to do here is to be able to map different glance
‘stores’ to cinder volume-types.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;1. As of now cinder can configure different volume-types but glance will be able
to use only one of those available volume-types. If glance store is
set to use cinder then every time new image is created it will always be
uploaded to default volume-type unless operator has configured
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cinder_volume_type&lt;/span&gt;&lt;/code&gt; in glance-api.conf file.&lt;/p&gt;
&lt;p&gt;2. If cinder store is configured to use in glance then while creating the
image cinder store of glance creates location URL with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cinder://&lt;/span&gt;&lt;/code&gt; prefix
only. When cinder has configured multiple backends and glance has also
configured multiple cinder stores then it is difficult to analyse
the image is stored in which of the cinder store as the location url
for the image as &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cinder://&amp;lt;image_id&amp;gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;We propose that Glance be able to expose multiple cinder stores that differ
by what volume-type each store uses. These would be defined in the normal way
in the glance configuration file using the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;enabled_backends&lt;/span&gt;&lt;/code&gt; option
(see example below). Further, when using multiple glance stores, each cinder
store &lt;em&gt;must&lt;/em&gt; have the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cinder_volume_type&lt;/span&gt;&lt;/code&gt; option set.&lt;/p&gt;
&lt;p&gt;While initializing the store object, glance will validate that volume type
set using &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cinder_volume_type&lt;/span&gt;&lt;/code&gt; is exist in cinder. If it’s not then that
store will be excluded by disabling ‘add’ and ‘delete’ operations. To
connect to cinder from glance operator needs to specify
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cinder_store_auth_address&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cinder_store_user_name&lt;/span&gt;&lt;/code&gt;,
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cinder_store_password&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cinder_catalog_info&lt;/span&gt;&lt;/code&gt; for each of the store
in glance-api.conf file.&lt;/p&gt;
&lt;p&gt;Below are some multiple cinder store configuration examples.&lt;/p&gt;
&lt;p&gt;Example 1: Fresh deployment&lt;/p&gt;
&lt;p&gt;For example, if cinder has configured 2 volume types &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance-fast&lt;/span&gt;&lt;/code&gt; and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance-slow&lt;/span&gt;&lt;/code&gt; then glance configuration should 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="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="c1"&gt;# list of enabled stores identified by their property group name&lt;/span&gt;
&lt;span class="n"&gt;enabled_backends&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fast&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;cinder&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;slow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;cinder&lt;/span&gt;

&lt;span class="c1"&gt;# the default store, if not set glance-api service will not start&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;glance_store&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;default_backend&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fast&lt;/span&gt;

&lt;span class="c1"&gt;# conf props for fast store instance&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;fast&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;rootwrap_config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;etc&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;glance&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;rootwrap&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;conf&lt;/span&gt;
&lt;span class="n"&gt;cinder_volume_type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;glance&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;description&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Really&lt;/span&gt; &lt;span class="n"&gt;fast&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;expensive&lt;/span&gt; &lt;span class="n"&gt;storage&lt;/span&gt;
&lt;span class="n"&gt;cinder_catalog_info&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;volumev2&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;publicURL&lt;/span&gt;
&lt;span class="n"&gt;cinder_store_auth_address&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;http&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="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;identity&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;v3&lt;/span&gt;
&lt;span class="n"&gt;cinder_store_user_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;glance&lt;/span&gt;
&lt;span class="n"&gt;cinder_store_password&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;admin&lt;/span&gt;
&lt;span class="n"&gt;cinder_store_project_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;service&lt;/span&gt;
&lt;span class="c1"&gt;# etc..&lt;/span&gt;

&lt;span class="c1"&gt;# conf props for slow store instance&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;slow&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;rootwrap_config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;etc&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;glance&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;rootwrap&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;conf&lt;/span&gt;
&lt;span class="n"&gt;cinder_volume_type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;glance&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;slow&lt;/span&gt;
&lt;span class="n"&gt;description&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Slower&lt;/span&gt; &lt;span class="n"&gt;but&lt;/span&gt; &lt;span class="n"&gt;less&lt;/span&gt; &lt;span class="n"&gt;expensive&lt;/span&gt; &lt;span class="n"&gt;storage&lt;/span&gt;
&lt;span class="n"&gt;cinder_catalog_info&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;volumev2&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;publicURL&lt;/span&gt;
&lt;span class="n"&gt;cinder_store_auth_address&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;http&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="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;identity&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;v3&lt;/span&gt;
&lt;span class="n"&gt;cinder_store_user_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;glance&lt;/span&gt;
&lt;span class="n"&gt;cinder_store_password&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;admin&lt;/span&gt;
&lt;span class="n"&gt;cinder_store_project_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;service&lt;/span&gt;
&lt;span class="c1"&gt;# etc..&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Example 2: Upgrade from single cinder store to multiple cinder stores, if
default_volume_type is set in cinder.conf and cinder_volume_type is also set in
glance-api.conf then administrator needs to create one store in glance where
cinder_volume_type same as old glance configuration:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;# cinder.conf
The glance administrator has to find out what the default volume-type is
in the cinder installation, so he/she needs to discuss with either cinder
admin or cloud admin to identify default volume-type from cinder and then
explicitly configure that as the value of ``cinder_volume_type``.
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Example config before upgrade:&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;glance_store&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;stores&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cinder&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;
&lt;span class="n"&gt;default_store&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cinder&lt;/span&gt;
&lt;span class="n"&gt;cinder_state_transition_timeout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;300&lt;/span&gt;
&lt;span class="n"&gt;rootwrap_config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;etc&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;glance&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;rootwrap&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;conf&lt;/span&gt;
&lt;span class="n"&gt;cinder_catalog_info&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;volumev2&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;publicURL&lt;/span&gt;
&lt;span class="n"&gt;cinder_volume_type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;glance&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;old&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Example config after upgrade:&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;enabled_backends&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;old&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;cinder&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;cinder&lt;/span&gt;

&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;glance_store&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;default_backend&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;new&lt;/span&gt;

&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;rootwrap_config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;etc&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;glance&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;rootwrap&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;conf&lt;/span&gt;
&lt;span class="n"&gt;cinder_volume_type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;glance&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;description&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Newly&lt;/span&gt; &lt;span class="n"&gt;defined&lt;/span&gt; &lt;span class="n"&gt;second&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cinder&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;store&lt;/span&gt;
&lt;span class="n"&gt;cinder_catalog_info&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;volumev2&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;publicURL&lt;/span&gt;
&lt;span class="n"&gt;cinder_store_auth_address&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;http&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="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;identity&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;v3&lt;/span&gt;
&lt;span class="n"&gt;cinder_store_user_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;glance&lt;/span&gt;
&lt;span class="n"&gt;cinder_store_password&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;admin&lt;/span&gt;
&lt;span class="n"&gt;cinder_store_project_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;service&lt;/span&gt;
&lt;span class="c1"&gt;# etc..&lt;/span&gt;

&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;old&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;rootwrap_config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;etc&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;glance&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;rootwrap&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;conf&lt;/span&gt;
&lt;span class="n"&gt;cinder_volume_type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;glance&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;old&lt;/span&gt; &lt;span class="c1"&gt;# as per old cinder.conf&lt;/span&gt;
&lt;span class="n"&gt;description&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Previously&lt;/span&gt; &lt;span class="n"&gt;existing&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cinder&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;store&lt;/span&gt;
&lt;span class="n"&gt;cinder_catalog_info&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;volumev2&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;publicURL&lt;/span&gt;
&lt;span class="n"&gt;cinder_store_auth_address&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;http&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="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;identity&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;v3&lt;/span&gt;
&lt;span class="n"&gt;cinder_store_user_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;glance&lt;/span&gt;
&lt;span class="n"&gt;cinder_store_password&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;admin&lt;/span&gt;
&lt;span class="n"&gt;cinder_store_project_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;service&lt;/span&gt;
&lt;span class="c1"&gt;# etc..&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Operator can decide on the basis of deployment strategy which volume type
they wants to use by coordinating with cinder admin or cloud operator.&lt;/p&gt;
&lt;p&gt;We also propose to modify location url for cinder and use
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;store&lt;/span&gt; &lt;span class="pre"&gt;identifier&lt;/span&gt;&lt;/code&gt; in location url so that user or operator will
identify in which cinder store of glance image is stored. The new
location URL should looked like &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cinder://store-name/image-id&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;For legacy images stored in cinder backend we will modify the lazy loading
mechanism of glance which will update the location URL of existing images
as per new format. The lazy loading operation is a check before
GET API call which traverse through image location and based on location URI
it identifies in which glance store image data is stored and updates
that information in location metadata. This mechanism is also useful
in a way that if in future operator decides to change the name of the
glance store or retire one of the configured store by migrating the
images to new stores.&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 security impact is same as it was with single store but we’re just
pointing it out here; The image-volume is stored in the configured
project &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cinder_store_project_name&lt;/span&gt;&lt;/code&gt; and can be accessed with configured
user &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cinder_store_user_name&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;There could be a potential risk if someone was able to get a hold of
these credentials and access the image-volumes. Worst case is someone
could alter the image-volumes if they had permission to perform any cinder
operation on it such as retype, attach etc.&lt;/p&gt;
&lt;p&gt;Care will have to be taken to ensure it isn’t accessible by normal
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;After upgrade from single cinder store to use multiple cinder stores first
image-list or first get call for image will take additional time as we are
performing the lazy loading operation to update legacy image location url
to use new image location urls. Subsequent get or list calls will perform
as they were performing earlier.&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 be aware of different volume types available in cinder. They
can either use &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;type-list&lt;/span&gt;&lt;/code&gt; command of cinder client or coordinate with cinder
admin and decide which volume-type of cinder should be configured in
glance-api.conf.&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;p&gt;Primary assignee:
* whoami-rajat
* abhishek-kekane&lt;/p&gt;
&lt;dl class="simple"&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="reviewers"&gt;
&lt;h3&gt;Reviewers&lt;/h3&gt;
&lt;p&gt;Core reviewer(s):&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;jokke&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;rosmaita&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;smcginnis&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;Modify cinder driver initialization to set new cinder location url&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Modify usage of cinder location url&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Modify lazy loading mechanism to update legacy image location URLs&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;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;Appropriate unit and functional tests to ensure the changes to glance function
correctly. Aslo we could add a job which will run tests using cinder stores in
glance.&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 need to ensure that glance/glance_store docs are updated for:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Usage of cinder volume types as cinder stores of glance.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We should also document that, if cinder store is used as glance
backend, Only the Image Service API should be used to manipulate images.
Manipulating image data directly via the Block Storage Service API is not
supported and may lead to adverse consequences, including data loss.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How to upgrade from single cinder store to multiple cinder stores.&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;
</description><pubDate>Thu, 28 May 2020 00:00:00 </pubDate></item><item><title>Victoria Project Priorities</title><link>http://specs.openstack.org/openstack/glance-specs/priorities/victoria-priorities.html</link><description>
&lt;span id="victoria-priorities"/&gt;
&lt;p&gt;TODO(abhishekk): fill this in after the PTG&lt;/p&gt;
</description><pubDate>Mon, 06 Apr 2020 00:00:00 </pubDate></item><item><title>Spec Lite: Deprecate admin_role</title><link>http://specs.openstack.org/openstack/glance-specs/specs/ussuri/approved/glance/spec-lite-deprecate-admin_role.html</link><description>

&lt;dl class="field-list simple"&gt;
&lt;dt class="field-odd"&gt;project&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;glance&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;problem&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;Glance has a configuration option that grants complete admin access
to anyone with a particular role.  This is confusing because it
overrides any settings in the policy configuration file.  Further,
the default value is ‘admin’, which is likely to be an actual role
defined in any OpenStack cloud.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;solution&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;Deprecate the ‘admin_role’ configuration option in Ussuri and
remove it during the Victoria development cycle.  Additionally,
change the default setting to something that would never match
any actual role, for example,
‘__NOT_A_ROLE_07697c71e6174332989d3d5f2a7d2e7c_NOT_A_ROLE__’.
That way, the ‘admin_role’ would only be effective if an
operator configured it on purpose, and this “backdoor” will
be effectively closed immediately.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;impacts&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;Possibly documentation (though our policy docs are woefully out
of date).&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
</description><pubDate>Tue, 24 Mar 2020 00:00:00 </pubDate></item><item><title>Spec Lite: Deprecate Checksum Computation</title><link>http://specs.openstack.org/openstack/glance-specs/specs/ussuri/approved/glance/spec-lite-deprecate-checksum.html</link><description>

&lt;dl class="field-list simple"&gt;
&lt;dt class="field-odd"&gt;project&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;glance&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;problem&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;The glance ‘checksum’ image property contains an MD5 hash of image
data.  MD5 has not been considered secure for some time, and in
order to comply with various security standards, an implementation
of the MD5 algorithm may not be available on glance nodes.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;solution&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;Announce that Glance will no longer populate the ‘checksum’ on new
images beginning with the Victoria release.  Instead, operators
should rely on the secure “multihash” feature that was introduced
in Rocky.  The ‘checksum’ property will remain on legacy images.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;impacts&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;None.&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;dl class="field-list"&gt;
&lt;dt class="field-odd"&gt;how&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;In Ussuri: release note.  In Victoria: Remove the code that uses MD5.
(This will affect primarily the glance_store drivers.)&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;alternatives&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;We could check to see if the algorithm is available, and if it
is, compute the MD5.  But this seems pointless as the secure
multihash is already being computed for all new images.&lt;/p&gt;
&lt;p&gt;We could remove the ‘checksum’ entirely, but this would require
a migration to the multihash.  For at least some backends, this
would mean downloading the image data for each legacy image to
do the computation, which could take a very long time.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;timeline&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;Deprecation and release note in Ussuri; removal in Victoria.&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
</description><pubDate>Wed, 19 Feb 2020 00:00:00 </pubDate></item><item><title>Spec Lite: Deprecate allow_additional_image_properties</title><link>http://specs.openstack.org/openstack/glance-specs/specs/ussuri/approved/glance/deprecate-allow-custom-props.html</link><description>

&lt;dl class="field-list simple"&gt;
&lt;dt class="field-odd"&gt;project&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;glance&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;problem&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;allow_additional_image_properties&lt;/span&gt;&lt;/code&gt; configuration option
was originally introduced to prevent users from flooding the
image_properties table with junk.  Given that we now have the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;image_property_quota&lt;/span&gt;&lt;/code&gt; option,
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;allow_additional_image_properties&lt;/span&gt;&lt;/code&gt; is unnecessary.  Further,
if an operator were to set it False, all sorts of stuff would
break as multiple OpenStack services (for example, Cinder, Nova)
currently write/rely on custom image properties.  Of course, in
such a case, an operator would have to change the option to
True to get everything working again; but the point is that
if this setting is always True, then it is unnecessary and
polluting the code with unnecessary branch points.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;solution&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;Deprecate the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;allow_additional_image_properties&lt;/span&gt;&lt;/code&gt; in Ussuri
scheduled for removal in the V development cycle, consistent with
the standard OpenStack deprecation policy.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;impacts&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;None.  Operators who really want to use this option can instead
set &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;image_property_quota&lt;/span&gt;&lt;/code&gt; to 0.  (‘0’ means zero; a negative
value means ‘unlimited’ for this option.)&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;assignee&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;rosmaita (or anyone who would like to address this low-hanging
fruit)&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
</description><pubDate>Mon, 16 Dec 2019 00:00:00 </pubDate></item><item><title>Deleting image from single store</title><link>http://specs.openstack.org/openstack/glance-specs/specs/ussuri/approved/glance/delete-image-from-single-store.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/glance/+spec/delete-from-store"&gt;https://blueprints.launchpad.net/glance/+spec/delete-from-store&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;New API feature to remove image from single store instead of whacking the
whole image.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Currently only way to remove image from single store is by exposing known
problematic locations API and utilize that to remove the location. With
multiple-stores support there is definitely more user oriented use-cases
for removing image from specific store.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Introduce new “/v2/stores” endpoint to Images API v2 to provide safe way to
delete images from the specific store.&lt;/p&gt;
&lt;p&gt;New API call:
‘DELETE /v2/stores/&amp;lt;StoreID&amp;gt;/&amp;lt;ImageID&amp;gt;’&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;We could consider utilizing the current “v2/images/&amp;lt;ImageID&amp;gt;” endpoint and
append the store ID at the end of that. The risk with this approach is that
it’s way too easy for the API user to make a mistake dropping the StoreID and
accidentally delete the whole image instead of just removing it from single
store.&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 API endpoint “v2/stores/&amp;lt;StoreID&amp;gt;/&amp;lt;ImageID&amp;gt;” that accepts only DELETE
http method.&lt;/p&gt;
&lt;p&gt;The request will fail if this is the only location indicating that the
user should delete the image instead.&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 have any know security impacts.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;Notification of image being removed from the store can be considered.&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-glanceclient will have feature to support this API call.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;This feature has no know performance impacts.&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;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;jokke&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 for glance-api service&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Testing for the new feature&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;python-glanceclient support&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Documentation needs to be updated including the new workflow&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 change will need 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;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;
</description><pubDate>Mon, 09 Dec 2019 00:00:00 </pubDate></item><item><title>Ussuri Project Priorities</title><link>http://specs.openstack.org/openstack/glance-specs/priorities/ussuri-priorities.html</link><description>
&lt;span id="ussuri-priorities"/&gt;
&lt;p&gt;The Ussuri review priorities were discussed at the Shanghai PTG. The
preliminary list was maintained on the &lt;a class="reference external" href="https://etherpad.openstack.org/p/Glance-Ussuri-PTG-planning"&gt;Shanghai PTG etherpad&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This list is an estimate of what the Glance project team can accomplish
during the Ussuri cycle based on our developers’ estimates of how much
time they can commit to Glance.&lt;/p&gt;
&lt;p&gt;The following list is roughly indicates milestonewise priorities.&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;Priority Item&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Owner(s)&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Spec(s)&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Target release milestone&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;Remove native ssl support&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;a class="reference external" href="https://launchpad.net/~jokke"&gt;Erno Kuvaja&lt;/a&gt;&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;M1&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Import image in multiple stores&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;a class="reference external" href="https://launchpad.net/~yebinama"&gt;Grégoire Unbekandt&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;a class="reference external" href="https://review.opendev.org/669201"&gt;multiple image import&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;M2&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Copy existing image in multiple stores&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;a class="reference external" href="https://launchpad.net/~abhishek-kekane"&gt;Abhishek Kekane&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;a class="reference external" href="https://review.opendev.org/694724"&gt;copy image in multiple stores&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;M2&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;S3 driver for glance_store&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;a class="reference external" href="https://launchpad.net/~nao-shark"&gt;Naohiro Sameshima&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;a class="reference external" href="https://review.opendev.org/687390"&gt;s3 driver&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;M2&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;remove sheepdog driver from glance_store&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;a class="reference external" href="https://launchpad.net/~abhishek-kekane"&gt;Abhishek Kekane&lt;/a&gt;&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;M2&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Permanent solution for Subunit parser error&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;a class="reference external" href="https://launchpad.net/~abhishek-kekane"&gt;Abhishek Kekane&lt;/a&gt;&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;M2&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Nova - snapshot/backup upload to multiple stores&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;a class="reference external" href="https://launchpad.net/~abhishek-kekane"&gt;Abhishek Kekane&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;a class="reference external" href="https://review.opendev.org/641210"&gt;nova snapshot&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;M2&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Cinder - volume upload to multiple stores&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;a class="reference external" href="https://launchpad.net/~abhishek-kekane"&gt;Abhishek Kekane&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;a class="reference external" href="https://review.opendev.org/695630"&gt;cinder uploadtoimage&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;M2&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Cluster awareness of glance API nodes&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;a class="reference external" href="https://launchpad.net/~jokke"&gt;Erno Kuvaja&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;a class="reference external" href="https://review.opendev.org/664956"&gt;cluster awareness&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;M2&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;remove registry code from glance&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;a class="reference external" href="https://launchpad.net/~abhishek-kekane"&gt;Abhishek Kekane&lt;/a&gt;&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;M2&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Delete image from single store&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;a class="reference external" href="https://launchpad.net/~jokke"&gt;Erno Kuvaja&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;a class="reference external" href="https://review.opendev.org/698018"&gt;delete store from image&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;M2&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;image-import.conf parsing issue with uwsgi&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Unassigned&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;M2&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Multiple cinder store support in glance_store&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;a class="reference external" href="https://launchpad.net/~abhishek-kekane"&gt;Abhishek Kekane&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;a class="reference external" href="https://review.opendev.org/695152"&gt;cinder glance_store&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;M3&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Image encryption&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;a class="reference external" href="https://launchpad.net/~josei"&gt;Josephine Seifert&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;a class="reference external" href="https://review.opendev.org/609667"&gt;image encryption&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;M3&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Tempest work&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;a class="reference external" href="https://launchpad.net/~abhishek-kekane"&gt;Abhishek Kekane&lt;/a&gt;&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;M3&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;section id="important-dates"&gt;
&lt;h2&gt;Important dates&lt;/h2&gt;
&lt;p&gt;This is an abbreviated list focused on dates relevant to Glance.  See
&lt;a class="reference external" href="https://releases.openstack.org/ussuri/schedule.html"&gt;Ussuri Release Schedule&lt;/a&gt; for the complete list for OpenStack.&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;R-22&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Dec 13&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;U-1 milestone&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;R-13&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Feb 14&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;U-2 milestone&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;R-6&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;April 03&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;glance_store Ussuri release (final release for non-client libraries)&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;R-5&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;April 22&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;U-3 milestone&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Glance feature freeze&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;python-glanceclient Ussuri release (final release for client libraries);&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;R-3&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;April 24&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;RC-1 release and &lt;strong&gt;string freeze&lt;/strong&gt;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;R-1&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;May 08&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;final RCs&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;R-0&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;May 15&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;strong&gt;Ussuri release&lt;/strong&gt;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Tue, 26 Nov 2019 00:00:00 </pubDate></item><item><title>Copy existing image in multiple stores</title><link>http://specs.openstack.org/openstack/glance-specs/specs/ussuri/approved/glance/copy-existing-image.html</link><description>

&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;p&gt;Despite the Image service supports several back ends for storing virtual
machine image, there is no way at the moment to copy existing image bits
into multiple stores and avoid the operator to manually copy data and update
image locations.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;At the moment, if cloud provider decided to upgrade their cloud to Train
release to use the ability of glance of configuring multiple stores, then
there is no way to replicate/copy existing image bits to newly added
stores. As a result, operators today need to perform a number of manual steps
in order to replicate/copy image bits on glance stores despite using the
‘enabled_backends’ configuration option.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;Example&lt;/p&gt;
&lt;p&gt;An operator upgrades his existing setup of OpenStack cloud to configure
different sites, each with their local glance stores which nova hosts
are accessing directly (Ceph).&lt;/p&gt;
&lt;p&gt;This operator use multiple stores support and want its images to be
available in each store to prevent the images to be downloaded through
glance each time a new virtual machine is created and let Nova use COW.&lt;/p&gt;
&lt;p&gt;For this purpose, he need to manually copy existing images data in
store2 to storeN and register these others locations URL using the
glance API.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Since glance supports multi stores, it should propose a feature to copy
existing image data into these stores at once to facilitate operators’ work.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;This spec depends on &lt;cite&gt;Ability to import an image in multiple stores&lt;/cite&gt; [1]
to copy the image in multiple stores. In addition to above changes and
existing import methods &lt;cite&gt;glance-direct&lt;/cite&gt; and &lt;cite&gt;web-download&lt;/cite&gt;, this spec
proposes to introduce additional import method &lt;cite&gt;copy-image&lt;/cite&gt;.&lt;/p&gt;
&lt;p&gt;If the image from which data needs to be copied in multiple stores is not
in active state then the API should reject the request. If image exists
then it will be copied to staging area. Once copying to staging task is
completed, import task will import the data to all the specified stores. In
case of any failure during copying existing data to staging area or
successful completion of copying/importing data to specified store, image
data from the staging area will be removed.&lt;/p&gt;
&lt;p&gt;Introduce one additional Task which will be internal plugin and allow
us to copy the existing image to staging area. To copy the existing image
into staging area, we will first give preference to &lt;cite&gt;default_backend&lt;/cite&gt; of
that specific glance-api node. If image is not associated with
&lt;cite&gt;default_backend&lt;/cite&gt; then we will iterate through all the available backends
of that specific glance-api node to copy(download) image from that location
to staging area. Failure mechanism will be same as dependent
spec &lt;cite&gt;Ability to import an image in multiple stores&lt;/cite&gt; [1].&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;If ‘all_stores’ boolean field is specified, the API should reject
the request.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If an unavailable image is specified, the Api should reject the request.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If an unavailable store is specified, the Api should reject the request.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If image is already present at specified location, the Api should reject
the request.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If base image is deleted while copying the data to new stores, then the
copying process will be terminated and copied data will be removed as well.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If ‘all_stores_must_succeed’ is set to ‘true’ (default behavior) and an
error occurs during the upload in at least one store, the request should
be rejected, the data will be deleted from stores where copying is done
(not staging), and the state of the image remains the same.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If ‘all_stores_must_succeed’ is set to ‘false’, the request will fail
(data deleted from stores, …) only if the upload fails on all stores
specified by the user. In case of a partial success, the locations added
to the image will be the stores where the data has been correctly uploaded.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In case of failures or successful completion of copying/importing data
to specified stores, image data from staging will be removed.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Users will be able to follow copying/importing operation progress by
looking at 2 reserved image custom properties:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;os_glance_importing_to_stores: This property contains the list of stores
that has not yet been processed. At the beginning of the copy/import flow,
it will be filled with the stores provided in the request. Each
time a store is fully handled, it will be removed from the list. This
property will be emptied at the end of the process even if an error occurs
and there are still remaining stores.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;os_glance_failed_import: Each time an import in a store fails, it is added
to this list. This property is emptied at the beginning of the copy/import
flow.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Image locations will be updated each time an upload/copy in a store succeed
(with information from this store).&lt;/p&gt;
&lt;p&gt;Current location strategies modules should not be affected by theses changes as
we don’t change the behavior of the image locations. It is currently possible
to do the same by patching an image and specify a list of locations.&lt;/p&gt;
&lt;p&gt;In the same vein, as it is already an option to choose a store when using
import workflow, there is no need to add a new policy to restrict the
copying of image in multiple stores.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Continue copying images manually to different stores and update the locations
using Locations API.&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 spec proposes the following API changes:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Modified APIs&lt;/strong&gt;&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Import an image.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Common Response Codes&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Normal http response code: 202&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;202: &lt;cite&gt;Accepted&lt;/cite&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Expected error http response codes: 400, 401, 404, 409, 410&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;400: &lt;cite&gt;Bad Request&lt;/cite&gt; with details.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;401: &lt;cite&gt;Unauthorized&lt;/cite&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;404: &lt;cite&gt;Not Found&lt;/cite&gt; (image doesn’t exist or is not owned by the caller)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;409: &lt;cite&gt;Conflict&lt;/cite&gt; (image is not in appropriate status)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;410: &lt;cite&gt;Gone&lt;/cite&gt; (Image deleted while operation in progress)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;API Version&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;This change will require minor version bump.
All URLS will be under the v2 Glance API.  If it is not explicitly specified
assume /v2/&amp;lt;url&amp;gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;[Modified API] Import image to the store&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Import image to the store:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;  POST /v2/images/{image_id}/import

If present, copy this image in multiple stores specified using `stores`
option.
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Example curl usage:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;curl -i -X POST -H "X-Auth-Token: $token"
     -H "Content-Type: application/json"
     -d '{"method":{"name":"copy-image"},
          "stores": ["ceph1", "ceph2"],
          "allow_failure": false}'
     $image_url/v2/images/{image_id}/import
&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;Notification will be sent for each of the successful copy of image.&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;As we’ll write data in multiple stores, this will increase the IO from the
glance nodes in accordance of the number of stores specified.
From the user point of view, the import workflow will also take more time
depending on the stores where the copying 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;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;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;p&gt;Primary assignee:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;abhishekk&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="reviewers"&gt;
&lt;h3&gt;Reviewers&lt;/h3&gt;
&lt;p&gt;Core reviewer(s):&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;jokke&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;rosmaita&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;Implementation tasks may consist of:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Write new internal plugin to copy image data in staging area&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;Appropriate unit and functional tests to ensure the changes to glance function
correctly. The major testing item is to ensure that if the copy taskflow fails,
data will be deleted only from the new stores, not from the stores where image
is already in and image status does not change.&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 need to ensure the glance docs are updated for:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;New body field for image import.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;New import method for image import.&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;[1] &lt;a class="reference external" href="https://review.opendev.org/#/c/669201"&gt;https://review.opendev.org/#/c/669201&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;PoC - &lt;a class="reference external" href="https://review.opendev.org/696457"&gt;https://review.opendev.org/696457&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
</description><pubDate>Mon, 18 Nov 2019 00:00:00 </pubDate></item><item><title>Re-support S3 Driver as Glance Store Backend</title><link>http://specs.openstack.org/openstack/glance-specs/specs/ussuri/approved/glance_store/re-support-s3-driver.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/glance/+spec/re-support-s3-driver"&gt;https://blueprints.launchpad.net/glance/+spec/re-support-s3-driver&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Glance store had supported S3 backend until version Mitaka, and it has already
been removed (in Newton &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;) due to lack of maintainers. However, there seems
to exist a certain number of operators who want to use S3 for the glance
backend because S3 is a major storage and there is a lot of S3 compatible
storage. So, I propose revive the S3 driver and support again as a member of
glance store drivers &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;.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;There seems to exist a certain number of operators who want to use S3 or S3
compatible storage for the glance backend, but glance doesn’t support S3 store
anymore so there is no way to use the S3 backend for them.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Revive the S3 Store Driver that was used until Mitaka, and support multiple
store configuration &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;The following configurations would be added to glance_store section of
glance-api.conf::&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;s3_store_host&lt;/span&gt;
  &lt;span class="n"&gt;The&lt;/span&gt; &lt;span class="n"&gt;host&lt;/span&gt; &lt;span class="n"&gt;where&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;S3&lt;/span&gt; &lt;span class="n"&gt;server&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;listening&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;item&lt;/span&gt; &lt;span class="n"&gt;accepts&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;string&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="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="n"&gt;s3&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;region&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;amazonaws&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="n"&gt;s3&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;region&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;amazonaws&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;https&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="n"&gt;s3&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;region&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;amazonaws&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;com&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt;
  &lt;span class="n"&gt;my&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nb"&gt;object&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="n"&gt;com&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="n"&gt;my&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nb"&gt;object&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="n"&gt;com&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;https&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="n"&gt;my&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nb"&gt;object&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="n"&gt;com&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;s3_store_access_key&lt;/span&gt;
  &lt;span class="n"&gt;The&lt;/span&gt; &lt;span class="n"&gt;S3&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt; &lt;span class="n"&gt;token&lt;/span&gt; &lt;span class="n"&gt;access&lt;/span&gt; &lt;span class="n"&gt;key&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;item&lt;/span&gt; &lt;span class="n"&gt;accepts&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;

&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;s3_store_secret_key&lt;/span&gt;
  &lt;span class="n"&gt;The&lt;/span&gt; &lt;span class="n"&gt;S3&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt; &lt;span class="n"&gt;token&lt;/span&gt; &lt;span class="n"&gt;secret&lt;/span&gt; &lt;span class="n"&gt;key&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;item&lt;/span&gt; &lt;span class="n"&gt;accepts&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;

&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;s3_store_bucket&lt;/span&gt;
  &lt;span class="n"&gt;The&lt;/span&gt; &lt;span class="n"&gt;S3&lt;/span&gt; &lt;span class="n"&gt;bucket&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;be&lt;/span&gt; &lt;span class="n"&gt;used&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;store&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;Glance&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;This&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="n"&gt;accepts&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;s3_store_create_bucket_on_put&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt;
  &lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&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;created&lt;/span&gt; &lt;span class="n"&gt;automatically&lt;/span&gt; &lt;span class="n"&gt;even&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;bucket&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;exist&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
  &lt;span class="n"&gt;It&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;desirable&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;have&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;DNS&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;compliant&lt;/span&gt; &lt;span class="n"&gt;naming&lt;/span&gt; &lt;span class="n"&gt;convention&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;

&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;s3_store_create_bucket_on_put&lt;/span&gt;
  &lt;span class="n"&gt;A&lt;/span&gt; &lt;span class="n"&gt;boolean&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;determine&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;S3&lt;/span&gt; &lt;span class="n"&gt;bucket&lt;/span&gt; &lt;span class="n"&gt;should&lt;/span&gt; &lt;span class="n"&gt;be&lt;/span&gt; &lt;span class="n"&gt;created&lt;/span&gt; &lt;span class="n"&gt;on&lt;/span&gt; &lt;span class="n"&gt;upload&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;it&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;exist&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;an&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="n"&gt;should&lt;/span&gt; &lt;span class="n"&gt;be&lt;/span&gt; &lt;span class="n"&gt;returned&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;user&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;item&lt;/span&gt; &lt;span class="n"&gt;accepts&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;

&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;s3_store_bucket_url_format&lt;/span&gt;
  &lt;span class="n"&gt;The&lt;/span&gt; &lt;span class="n"&gt;S3&lt;/span&gt; &lt;span class="n"&gt;calling&lt;/span&gt; &lt;span class="nb"&gt;format&lt;/span&gt; &lt;span class="n"&gt;used&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;determine&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;bucket&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="n"&gt;Either&lt;/span&gt; &lt;span class="s1"&gt;'auto'&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="s1"&gt;'path'&lt;/span&gt;
  &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="s1"&gt;'virtual'&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;used&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
  &lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="s1"&gt;'path'&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;style&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;endpoint&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="nb"&gt;object&lt;/span&gt; &lt;span class="n"&gt;looks&lt;/span&gt; &lt;span class="n"&gt;like&lt;/span&gt; &lt;span class="s1"&gt;'https://s3.amazonaws.com/bucket/example.img'&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="s1"&gt;'https://my-object-storage.com/bucket/example.img'&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
  &lt;span class="n"&gt;And&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="s1"&gt;'virtual'&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;style&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;endpoint&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="nb"&gt;object&lt;/span&gt; &lt;span class="n"&gt;looks&lt;/span&gt; &lt;span class="n"&gt;like&lt;/span&gt; &lt;span class="s1"&gt;'https://bucket.s3.amazonaws.com/example.img'&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="s1"&gt;'https://bucket.my-object-storage.com/example.img'&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;you&lt;/span&gt; &lt;span class="n"&gt;do&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;follow&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;DNS&lt;/span&gt; &lt;span class="n"&gt;naming&lt;/span&gt; &lt;span class="n"&gt;convention&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;g&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="n"&gt;that&lt;/span&gt; &lt;span class="n"&gt;includes&lt;/span&gt; &lt;span class="s1"&gt;'.'&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;bucket&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;you&lt;/span&gt; &lt;span class="n"&gt;can&lt;/span&gt; &lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="n"&gt;objects&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;path&lt;/span&gt; &lt;span class="n"&gt;style&lt;/span&gt;&lt;span class="p"&gt;,&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;virtual&lt;/span&gt; &lt;span class="n"&gt;style&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;

&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;s3_store_large_object_size&lt;/span&gt;
  &lt;span class="n"&gt;What&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;MB&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;should&lt;/span&gt; &lt;span class="n"&gt;S3&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt; &lt;span class="n"&gt;chunking&lt;/span&gt; &lt;span class="n"&gt;image&lt;/span&gt; &lt;span class="n"&gt;files&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;do&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;multipart&lt;/span&gt;
  &lt;span class="n"&gt;upload&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;S3&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;item&lt;/span&gt; &lt;span class="n"&gt;accepts&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;positive&lt;/span&gt; &lt;span class="n"&gt;integer&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;

&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;s3_store_large_object_chunk_size&lt;/span&gt;
  &lt;span class="n"&gt;What&lt;/span&gt; &lt;span class="n"&gt;multipart&lt;/span&gt; &lt;span class="n"&gt;upload&lt;/span&gt; &lt;span class="n"&gt;part&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;MB&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;should&lt;/span&gt; &lt;span class="n"&gt;S3&lt;/span&gt; &lt;span class="n"&gt;use&lt;/span&gt; &lt;span class="n"&gt;when&lt;/span&gt; &lt;span class="n"&gt;uploading&lt;/span&gt; &lt;span class="n"&gt;parts&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;size&lt;/span&gt; &lt;span class="n"&gt;must&lt;/span&gt; &lt;span class="n"&gt;be&lt;/span&gt; &lt;span class="n"&gt;greater&lt;/span&gt; &lt;span class="n"&gt;than&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;equal&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="mi"&gt;5&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;Note&lt;/span&gt; &lt;span class="n"&gt;that&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;maximum&lt;/span&gt; &lt;span class="n"&gt;possible&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="n"&gt;image&lt;/span&gt; &lt;span class="n"&gt;divisions&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;000.&lt;/span&gt;

&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;s3_store_thread_pools&lt;/span&gt;
  &lt;span class="n"&gt;The&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="n"&gt;thread&lt;/span&gt; &lt;span class="n"&gt;pools&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;perform&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;multipart&lt;/span&gt; &lt;span class="n"&gt;upload&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;S3&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;item&lt;/span&gt; &lt;span class="n"&gt;accepts&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;positive&lt;/span&gt; &lt;span class="n"&gt;integer&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;As a result, operator can configure multiple stores including S3 as shown
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="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="c1"&gt;# list of enabled stores identified by their property group name&lt;/span&gt;
&lt;span class="n"&gt;enabled_backends&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fast&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;s3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cheap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;s3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;reliable&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;

&lt;span class="c1"&gt;# the default store, if not set glance-api service will not start&lt;/span&gt;
&lt;span class="n"&gt;default_backend&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fast&lt;/span&gt;

&lt;span class="c1"&gt;# conf props for file system store instance&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;reliable&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;filesystem_store_datadir&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&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;images&lt;/span&gt;&lt;span class="o"&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;description&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Reliable&lt;/span&gt; &lt;span class="n"&gt;filesystem&lt;/span&gt; &lt;span class="n"&gt;store&lt;/span&gt;
&lt;span class="c1"&gt;# etc..&lt;/span&gt;

&lt;span class="c1"&gt;# conf props for s3 store instance&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;fast&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;s3_store_host&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;https&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="n"&gt;s3&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;amazonaws&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;com&lt;/span&gt;
&lt;span class="n"&gt;s3_store_access_key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;access&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="k"&gt;for&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;s3_store_secret_key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;secret&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="k"&gt;for&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;s3_store_bucket&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;bucket&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;fast&lt;/span&gt;
&lt;span class="c1"&gt;# etc..&lt;/span&gt;

&lt;span class="c1"&gt;# conf props for s3 store instance&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;cheap&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;s3_store_host&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;https&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="n"&gt;my&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nb"&gt;object&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="n"&gt;com&lt;/span&gt;
&lt;span class="n"&gt;s3_store_access_key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;access&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;cheap&lt;/span&gt;
&lt;span class="n"&gt;s3_store_secret_key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;secret&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;cheap&lt;/span&gt;
&lt;span class="n"&gt;s3_store_bucket&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;bucket&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;cheap&lt;/span&gt;
&lt;span class="c1"&gt;# etc..&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&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;This change will have to be explicitly configured in the store options.&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;nao-shark&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 configurations to glance-api.conf (s3_store_host, s3_store_access_key,
s3_store_secret_key, s3_store_bucket, etc).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Revive the S3 driver and unit test that were used until Mitaka,
and support multiple store configuration.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Documentation on how to use and configure S3 backend.&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;Test uploading of an image to the S3 backend.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Then test downloading of the image again.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Test delete the image.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Test configure multiple s3 drivers.&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 documentation should be expanded to describe how to enable and use the S3
store.&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;Newton Series Release Notes
&lt;a class="reference external" href="https://docs.openstack.org/releasenotes/glance/newton.html"&gt;https://docs.openstack.org/releasenotes/glance/newton.html&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;Glance Store Drivers
&lt;a class="reference external" href="https://docs.openstack.org/glance_store/latest/user/drivers.html"&gt;https://docs.openstack.org/glance_store/latest/user/drivers.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="#id3"&gt;3&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;multi-store backend support
&lt;a class="reference external" href="https://specs.openstack.org/openstack/glance-specs/specs/rocky/implemented/glance/multi-store.html"&gt;https://specs.openstack.org/openstack/glance-specs/specs/rocky/implemented/glance/multi-store.html&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;/aside&gt;
&lt;/section&gt;
</description><pubDate>Wed, 09 Oct 2019 00:00:00 </pubDate></item><item><title>Spec Lite: Add new container format</title><link>http://specs.openstack.org/openstack/glance-specs/specs/train/approved/glance/add-new-container-format.html</link><description>

&lt;dl class="field-list simple"&gt;
&lt;dt class="field-odd"&gt;project&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;glance&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;problem&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;Compression method using hardware to accelerate has already been
implemented in cinder project. A new container format ‘compressed’
needs to be added to container format list in glance to support
this.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;solution&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;A new container format ‘compressed’ option needs to be added to the
default container_format configuration list.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;impacts&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;New container format option&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;dl class="field-list simple"&gt;
&lt;dt class="field-odd"&gt;how&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;If users chose to upload volume using compression method, cinder will do
compression and then upload to glance. The uploaded image’s metadata will be
‘compressed’ in container_format so that it can be correctly processed after
downloaded. Volume disk_format will not be changed by this compression
process.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Glance will not handle the compression and decompression progress, which
means glance will not check if it is a vaild compressed image. Whoever is to
upload or download the image is responsible for compression or
decompression.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Uploaded image will not be automatically compressed if simply changing the
container_format as ‘compressed’. Compression or decompression happens when
image is uploading from volume or downloading to a volume.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Glance will not identify what format the compressed image really is. In
glance’s view, it is just a blob. Image consumer (such as cinder) will
identify the real format such as gzip, rar or other format.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;other impact&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;Nova cannot currently handle images in a compressed container format.
We propose patching Nova to reject such images:
&lt;a class="reference external" href="https://review.opendev.org/#/c/673407/"&gt;https://review.opendev.org/#/c/673407/&lt;/a&gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;timeline&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;Include in train release&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;link&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;&lt;a class="reference external" href="https://review.opendev.org/#/c/652275/"&gt;https://review.opendev.org/#/c/652275/&lt;/a&gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;assignee&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;ZhengMa&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
</description><pubDate>Fri, 12 Jul 2019 00:00:00 </pubDate></item><item><title>Ability to import an image in multiple stores</title><link>http://specs.openstack.org/openstack/glance-specs/specs/ussuri/approved/glance/import-multi-stores.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/glance/+spec/import-multi-stores"&gt;https://blueprints.launchpad.net/glance/+spec/import-multi-stores&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Despite the Image service supports several back ends for storing virtual
machine image, the import workflow only allow to push image data in one
store. The goal of this spec is to allow this workflow to import image data
into multiple stores and avoid the operator to manually copy data and update
image locations.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;At the moment, the import workflow only allow to push image data in one
store. As a result, operators today need to perform a number of manual steps
in order to replicate image bits on backend glance stores despite using the
‘enabled_backends’ configuration option.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;Example&lt;/p&gt;
&lt;p&gt;An operator provides an Openstack cloud with different sites, each
with their local stores which nova hosts are accessing directly (Ceph).&lt;/p&gt;
&lt;p&gt;This operator use multiple stores support and want its images to be
available in each store to prevent the images to be downloaded through
glance each time a new virtual machine is created and let Nova use COW.&lt;/p&gt;
&lt;p&gt;For this purpose, when creating a new image, he needs to use the import
workflow to store image data in store. Since the image is now in status
“ACTIVE”, he can’t use the import workflow anymore and need to manually
upload data in store2 to storeN and register these others locations URL
using the glance API.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Since glance supports multi stores, it should propose a feature to upload
image data into these stores at once to facilitate operators’ work.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;This spec proposes the following high level feature to support multiple
stores import:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Enhance the image import API to support targeting a list of stores for the
image bits.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The idea is to provide a new ‘stores’ array field in the json payload where
the user will list all stores he wants to import its data in (example:
[‘ceph_fast’, ‘ceph_cheap’]).&lt;/p&gt;
&lt;p&gt;If an unavailable store is submitted, the Api should reject the request.&lt;/p&gt;
&lt;p&gt;If user or operator wants to import the image to all the enabled stores then
it might be difficult or overhead to specify all the stores in the list.
For that purpose a boolean field ‘all_stores’ will be provided.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;If set to false (default behavior), we use the logic previously described.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If set to true, the data will be imported to the set of stores you may
consume from this particular deployment of Glance (ie: the same set of stores
returned to a call to /v2/info/stores on the glance-api the request hits).
This can’t be used simultaneously with the ‘stores’ parameter.
If user submits both, the Api should reject the request.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Another boolean field, ‘all_stores_must_succeed’, will be added in the payload
to specify which error behavior the user wants to be applied:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;If this field is set to ‘true’ (default behavior) and an error occurs
during the upload in at least one store, the request should be rejected, the
data deleted from stores (not staging), and the state of the image remains
the same.
The status of the image will be set to ‘ACTIVE’ only  when the request is
fully executed and successful.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If this field is set to ‘false’, the request will fail (data deleted from
stores, …) only if the upload fails on all stores specified by the user.
In case of a partial success, the locations added to the image will be the
stores where the data has been correctly uploaded.
The status of the image will be set to ‘ACTIVE’ as soon as an upload in
one store is fully executed and successful.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Image locations will be updated each time an upload in a store succeed (with
informations from this store).&lt;/p&gt;
&lt;p&gt;Users will be able to follow task progress by looking at 2 reserved image
properties:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;os_glance_importing_to_stores: This property contains a list of stores that
has not yet been processed. At the beginning of the import flow, it will
be filled with the stores provided in the request. Each time a store is
fully handled, it will be removed from the list.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;os_glance_failed_import: Each time an import in a store fails, it is added
to this list. This property is emptied at the beginning of the import flow.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If the image is deleted during the process of the request, import to
remaining stores will not be processed and already uploaded data should be
deleted.&lt;/p&gt;
&lt;p&gt;Current location strategies modules shouldn’t be affected by theses changes as
we don’t change the behavior of the image locations. It is currently possible
to do the same by patching an image and specify a list of locations.&lt;/p&gt;
&lt;p&gt;In the same vein, as it is already an option to choose a store when using
import workflow, there is no need to add a new policy to restrict the import in
multiple stores.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;An alternative to this solution would be to allow to import data on an image
with status ‘ACTIVE’.
This will be the subject of another 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;This spec proposes the following API changes:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Modified APIs&lt;/strong&gt;&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Import an image.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Common Response Codes&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Normal http response code: 202&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;202: &lt;cite&gt;Accepted&lt;/cite&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Expected error http response codes: 400, 401, 403, 404, 409, 410&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;400: &lt;cite&gt;Bad Request&lt;/cite&gt; with details.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;401: &lt;cite&gt;Unauthorized&lt;/cite&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;404: &lt;cite&gt;Not Found&lt;/cite&gt; (image doesn’t exist or is not owned by the caller)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;409: &lt;cite&gt;Conflict&lt;/cite&gt; (image is not in appropriate status)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;410: &lt;cite&gt;Gone&lt;/cite&gt; (image deleted while operation in progress)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;API Version&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;This change will require minor version bump.
All URLS will be under the v2 Glance API.  If it is not explicitly specified
assume /v2/&amp;lt;url&amp;gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;[Modified API] Import image to the store&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Import image to the store:&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;POST&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;v2&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;images&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;image_id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;This modifies the existing REST API to add three new optional body fields.
For backwards compatibility, if the ‘stores’ parameter is not specified, the
header ‘X-Image-Meta-Store’ is evaluated.
If neither parameter i.e. ‘X-Image-Meta-Store’ header and ‘stores’ are
specified then the store configured as default (e.g. default_backend) is used
to upload the image to.
If both parameters are supplied, or ‘all_stores’ parameter is set to true and
‘X-Image-Meta-Store’ header or ‘stores’ are set, the request will be rejected
as Bad Request (ie: http 400).&lt;/p&gt;
&lt;p&gt;New body fields:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;stores – (String Array)
If present contains the list of store id to import the image binary data to.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;all_stores – (Boolean, default to false)
If set to true, the data will be imported in all configured stores.
If set to false, ‘stores’ and/or ‘X-Image-Meta-Store’ are evaluated.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;all_stores_must_succeed – (Boolean, default to true)
If set to false, the task will fail only if import fails in all specified
stores.
If set to true, the task will fail if import fails in one of the mentioned
store.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Changed response codes:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;400 – If the ‘stores’ field is present, but specifies a list of store id
with at least one id that doesn’t exist or is read-only (like http).
Or, if any two or more of the three ‘all_stores’:’true’, ‘stores’,
‘X-Image-Meta-Store’ are specified.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Example curl usage:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;curl -i -X POST -H "X-Auth-Token: $token"
     -H "Content-Type: application/json"
     -d '{"method":{"name":"glance-direct"},
          "stores": ["ceph1", "ceph2"],
          "all_stores_must_succeed": false}'
     $image_url/v2/images/{image_id}/import
&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;When going through the image import workflow, the payload sent during
notification stages already contains a field “backend” which contains the
store specified by the user when using multiple backend support.
Notifications should be sent for each store asked by the user containing
the status of the upload to that particular store.
The new properties will be added to the notification payload.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;Example&lt;/p&gt;
&lt;p&gt;An operator calls the import image api with the following parameters:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;curl -i -X POST -H "X-Auth-Token: $token"
     -H "Content-Type: application/json"
     -d '{"method": {"name":"glance-direct"},
          "stores": ["ceph1", "ceph2"],
          "all_stores_must_succeed": false}'
    $image_url/v2/images/{image_id}/import
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The upload fails for ‘ceph2’ but succeed on ‘ceph1’. Since the parameter
‘all_stores_must_succeed’ has been set to ‘false’, the task ends
successfully and the image is now active.&lt;/p&gt;
&lt;p&gt;Notifications sent by glance should look like (payload is truncated for
clarity):&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;"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;"event_type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"image.prepare"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"timestamp"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"2019-08-27 16:10:30.066867"&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;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"importing"&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;"example"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s2"&gt;"backend"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"ceph1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s2"&gt;"os_glance_importing_to_stores"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"ceph1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"ceph2"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
                &lt;span class="s2"&gt;"os_glance_failed_import"&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;"message_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"1c8993ad-e47c-4af7-9f75-fa49596eeb10"&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="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;"event_type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"image.upload"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"timestamp"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"2019-08-27 16:11:30.058812"&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;"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="s2"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"example"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s2"&gt;"backend"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"ceph1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s2"&gt;"os_glance_importing_to_stores"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"ceph2"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
                &lt;span class="s2"&gt;"os_glance_failed_import"&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;"message_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"8b8993ad-e47c-4af7-9f75-fa49596eeb11"&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="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;"event_type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"image.prepare"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"timestamp"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"2019-08-27 16:10:30.066867"&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;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"importing"&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;"example"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s2"&gt;"backend"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"ceph2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s2"&gt;"os_glance_importing_to_stores"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"ceph2"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
                &lt;span class="s2"&gt;"os_glance_failed_import"&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;"message_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"1c8993ad-e47c-4af7-9f75-fa49596eeb10"&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="s2"&gt;"priority"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"ERROR"&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;"image.upload"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"timestamp"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"2019-08-27 16:11:30.058812"&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;"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="s2"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"example"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s2"&gt;"backend"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"ceph2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s2"&gt;"os_glance_importing_to_stores"&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_glance_failed_import"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"ceph2"&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;"message_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"8b8993ad-e47c-4af7-9f75-fa49596eeb11"&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;/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;&lt;strong&gt;Glance client&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The glance client (CLI + REST client) must be updated in accordance with this
spec. Notably:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;CLI / API support for specifying a list of store id on import.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;CLI / API support for specifying all_stores_must_succeed option on import.&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;As we’ll write data in multiple stores, this will increase the IO from the
glance nodes in accordance of the number of stores specified.
From the user point of view, the import workflow will also take more time
depending on the stores where the upload are 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;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;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;p&gt;Primary assignee:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;yebinama&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="reviewers"&gt;
&lt;h3&gt;Reviewers&lt;/h3&gt;
&lt;p&gt;Core reviewer(s):&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;jokke&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;Implementation tasks may consist of:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Image import with a list of stores supplied.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add python-glanceclient support&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;Appropriate unit and functional tests to ensure the changes to glance 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;We’ll need to ensure the glance docs are updated for:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;New body fields for image import.&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/667132/"&gt;https://review.opendev.org/#/c/667132/&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
</description><pubDate>Thu, 04 Jul 2019 00:00:00 </pubDate></item><item><title>Cache API</title><link>http://specs.openstack.org/openstack/glance-specs/specs/xena/approved/glance/cache-api.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/glance/+spec/cache-api"&gt;https://blueprints.launchpad.net/glance/+spec/cache-api&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Managing split deployments is currently a bit difficult and sometimes require
operators to run commands on multiple nodes. Introducing a cache API would make
managing such deployments easier.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Adding new API endpoints related to caching would prove beneficial in two ways:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Along with the planned work on cluster awareness, this would make it easier to
manage split deployments (multiple glance-api nodes on different locations)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Users would have to deal with fewer commands since the
glance-cache-prefetcher is now part of glance-api as a periodic job and
glance-cache-manage will now be part of python-glanceclient.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;The main change this specification describes is the extension of the Glance API
to handle cache-related operations. The goal is to have an API that can replace
the “glance-cache-manage” tool. These are the operations we would like to
support:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;List cached,queued images&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Delete cached, queued images&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Delete all cached and queued images using single API call&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Queue image for prefetching&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;At the moment to enable the glance caching in the deployment operator needs
to configure two different middleware, &lt;cite&gt;cache&lt;/cite&gt; and &lt;cite&gt;cachemanage&lt;/cite&gt;. &lt;cite&gt;cache&lt;/cite&gt;
middleware is responsible for configuring cache resources such as cache
directory, initializing cache driver etc. whereas &lt;cite&gt;cachemanage&lt;/cite&gt; middleware
used to deal with actually caching resources via glance-api. As caching
now will be part of glance V2 API, we would like to deprecate &lt;cite&gt;cachemanage&lt;/cite&gt;
middleware and remove it as per &lt;cite&gt;deprecation and removal&lt;/cite&gt; policy. The newly
added cache endpoints will be &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;EXPERIMENTAL&lt;/span&gt;&lt;/code&gt; in this cycle and will be
marked as stable in following cycle.&lt;/p&gt;
&lt;p&gt;In addition to above proposed change this will introduce three new policies
&lt;cite&gt;cache_image&lt;/cite&gt;, &lt;cite&gt;cache_list&lt;/cite&gt; and &lt;cite&gt;delete_cache&lt;/cite&gt; so that user with appropriate
permissions can perform these operations. We will also deprecate the existing
&lt;cite&gt;manage_image_cache’ policy in favor of new policies. To make the new
policies compatible with secure RBAC we need to ensure to pass required
parameters like ImageTarget while enforcing the new policies. It is recommended
to keep `cache_image&lt;/cite&gt;, &lt;cite&gt;cache_list&lt;/cite&gt; and &lt;cite&gt;delete_cache&lt;/cite&gt; operations limited to
admin use only.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;If we do nothing about cluster awareness and we do not provide an easy-to-use
API for cache management, operators could probably write homemade solutions to
aggregate data from multiple nodes, but this would be error-prone and not
user-friendly.&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 spec proposes the following new endpoints:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;New API&lt;/strong&gt;&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;List cached and queued images&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Delete a cached or queued image&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Delete all cached or queued images&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Queue image for caching&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Common Response Codes&lt;/strong&gt;&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Create Success: &lt;cite&gt;201 Created&lt;/cite&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Delete Success: &lt;cite&gt;204 No Content&lt;/cite&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Failure: &lt;cite&gt;400 Bad Request&lt;/cite&gt; with details.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Forbidden: &lt;cite&gt;403 Forbidden&lt;/cite&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;[New API] List cached or queued images&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;List all images cached or queued for caching on this node:&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&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;v2&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;cache&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="s2"&gt;"cached_images"&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;"d75b9181-e1ce-45b4-8147-fb66fc4ea82f"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
         &lt;span class="s2"&gt;"last_accessed"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;1560451015.977297&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
         &lt;span class="s2"&gt;"last_modified"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;1560451015.977297&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
         &lt;span class="s2"&gt;"size"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;12345&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
         &lt;span class="s2"&gt;"hits"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
         &lt;span class="s2"&gt;"checksum"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"6788146b9d3fddc8dd03d86bfe9239b0"&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
   &lt;span class="p"&gt;],&lt;/span&gt;
   &lt;span class="s2"&gt;"queued_images"&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;"d75b9181-e1ce-45b4-8147-fb66fc4ea82f"&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;Response codes:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;200 – Upon authorization and successful request. The response body
contains the JSON payload with the cached and queued images.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;[New API] Delete a queued or cached image&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Delete a specific image from the cache:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;DELETE /v2/cache/​{image_id}​
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Response codes:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;204 – The image was deleted&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;403 – Permission denied&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;[New API] Delete all queued or cached images&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Delete all queued or cached 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;DELETE&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;v2&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;cache&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Response codes:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;204 – The cache was purged&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;403 – Permission denied&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;[New API] Queue an image for caching&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Pre-cache an image:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;PUT /v2/cache/​{image_id}​
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Response codes:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;202 – The request has been accepted, the image will be queued for caching&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;403 – Permission denied&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;404 – Image not found&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;As described in proposed change section either existing policies or
new policies will be enforced to avoid security breach.&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 glance client should be updated, with new commands:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;glance cache-list&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;glance cache-image &amp;lt;IMAGE-ID&amp;gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;glance cache-delete &amp;lt;IMAGE-ID&amp;gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;glance cache-delete-all&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Provision will be made to pass direct URL (host:port) to these commands
which will direct the call to particular glance node. Implementation
details for the same will be described in specific glance-client spec.&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;Caching will be local to each glance node and as these commands will be
executed remotely, operator needs to know the direct URL of each glance
node which are behind the load balancer. Operator need to provide this
direct URL to glanceclient so that client should hit particular node
to retrieve the cache information of that node.&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;jokke&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;cyril-roelandt&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;Deprecate &lt;cite&gt;cachemanage&lt;/cite&gt; middleware&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add new cache endpoint (/v2/cache)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Make new policies compatible with secure RBAC&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add python-glanceclient support&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Deprecate glance-cache-manage&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Deprecate glance-cache-prefetcher&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Modify documentation, update API reference&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Devstack support to enable cache on remote node&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;The new API endpoints should be tested using 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;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;The API documentation will need to be updated&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Need to update Cache documentation as well with new commands&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://docs.openstack.org/glance/victoria/admin/cache.html"&gt;https://docs.openstack.org/glance/victoria/admin/cache.html&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
</description><pubDate>Wed, 26 Jun 2019 00:00:00 </pubDate></item><item><title>Spec Lite: Lazy update stores information</title><link>http://specs.openstack.org/openstack/glance-specs/specs/train/approved/glance/spec-lite-lazy-update-stores-info.html</link><description>

&lt;dl class="field-list"&gt;
&lt;dt class="field-odd"&gt;project&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;glance&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;problem&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;In Rocky multiple backend support is added as experimental feature.
The location object will have the ‘store_id’ (Store name) stored as
a metadata attribute which helps to identify in which store the
image is located. Glance API service has information about all
configured stores in a global map.&lt;/p&gt;
&lt;p&gt;After enabling/upgrading glance-api to use multiple stores feature,
existing images will not have a stores information associated with
them. As a result if existing image is requested for download then
it will search that image in all configured stores which will cause
a performance overhead.&lt;/p&gt;
&lt;p&gt;All configured stores are stored in memory, if operator change the
store name in configuration file and restart the glance-api service
there is no way to update the new name to existing images which has
store information associated with them.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;solution&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;Add a decorator to get image call which will retrieve the location
object from image and then from location URL it will fetch the store
information which is stored in the location map. Once location url
is matched with the url from the global map, it will check if
location metadata has existing store associated with it and then
store name will be added/updated to the location metadata.&lt;/p&gt;
&lt;p&gt;If user/operator uses GET call to show a single image or list
all the images the particular decorator will update the store
information to single or all images available depending upon
the request. There will be slight impact on performance on list
call as it will revisit the location call for each of the image
in the list.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;alternatives&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;None, carry on using current mechanism.&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;impacts: DocImpact&lt;/p&gt;
&lt;dl class="field-list simple"&gt;
&lt;dt class="field-odd"&gt;timeline&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;Include in Train release.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;link&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;None&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;assignee&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;abhishekk&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
</description><pubDate>Wed, 22 May 2019 00:00:00 </pubDate></item><item><title>Spec Lite: Add location url prefix attribute to each store</title><link>http://specs.openstack.org/openstack/glance-specs/specs/train/approved/glance_store/spec-lite-location-uri-prefix.html</link><description>

&lt;dl class="field-list"&gt;
&lt;dt class="field-odd"&gt;project&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;glance_store&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;problem&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;In multiple store implementation, glance has added new metadata
‘store’ to location object, so that it will be easy to identify
the store that particular image is uploaded. When operator
upgrades glance node to use multiple stores, then
existing images does not have store information associated with
it. So if user wants to download any such particular image, then
as it does not have ‘store’ associated with it, the said image will
be searched in all the configured stores. This may cause the
performance overhead.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;solution&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;To overcome this, we propose to add new attribute ‘_url_prefix’
to each of the store object. When glance-api service starts it
stores a global map in the memory which includes store object,
scheme and location_class for each of the store.&lt;/p&gt;
&lt;p&gt;Sample of location map stored in the memory:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;{
    'file_2': {
        'store': &amp;lt;glance_store._drivers.filesystem.Store object&amp;gt;,
        'store_entry': 'file',
        'location_class': &amp;lt;class 'glance_store._drivers.filesystem.StoreLocation'&amp;gt;
    },
    'file_1': {
        'store': &amp;lt;glance_store._drivers.filesystem.Store&amp;gt;,
        'store_entry': 'file',
        'location_class': &amp;lt;class 'glance_store._drivers.filesystem.StoreLocation'&amp;gt;
    }
}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;At the time of initialization of each store, a location url will
be retrieved using each stores configuration and assigned to
‘_url_prefix’ attribute of each store object. Whenever any GET call
to image (before upgrading to multiple stores) is made, the location
url of that image will be matched with ‘_url_prefix’ and equivalent
store information will be updated to that image’s location metadata.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;alternatives&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;None, carry on using current mechanism.&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;impacts: DocImpact&lt;/p&gt;
&lt;dl class="field-list simple"&gt;
&lt;dt class="field-odd"&gt;timeline&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;Include in Train release.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;link&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;None&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;assignee&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;abhishekk&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
</description><pubDate>Tue, 21 May 2019 00:00:00 </pubDate></item><item><title>Train Project Priorities</title><link>http://specs.openstack.org/openstack/glance-specs/priorities/train-priorities.html</link><description>
&lt;span id="train-priorities"/&gt;
&lt;p&gt;Top priorities for Glance in Train cycle are:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Release glance_store 1.0.0&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Getting multi-store moved away from Experimental&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Removing dependencies to registry from cache tooling&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Cleaning up deprecations&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Cluster awareness:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Image import call rerouting to the node that has access to image in staging&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Centralized cache management via API endpoint:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Listing cached images across cluster&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Precaching images&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Copy/Remove images cross multi-store&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Distributed Store Discovery&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;On top of these housekeeping and feature items the community will prioritize
bugfixes and reviews as appropriate.&lt;/p&gt;
</description><pubDate>Fri, 17 May 2019 00:00:00 </pubDate></item><item><title>Spec Lite: ‘all’ visibility image filter</title><link>http://specs.openstack.org/openstack/glance-specs/specs/stein/implemented/glance/all-visibility-image-filter.html</link><description>

&lt;dl class="field-list simple"&gt;
&lt;dt class="field-odd"&gt;project&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;glance&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;problem&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;When deployments use community images these community images are
not returned when doing an image list.
Currently murano and other projects use a property to determine
if the image should be used. It is not possible to filter on
all images with the specific property. Sahara also shares this
issue. Horizon currently also needs to show all images that a
user can boot from in the boot intance view and this cannot be
done without 2 requests to glance.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;solution&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;We need to add a new visibility called ‘all’ which will return
all images that are available to the user.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;impacts&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;None&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;how&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;We will add the ability to list images with visibility=’all’ to
return all images. This will require a bump in the api version.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;alternatives&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;The other option is to make 2 requests to glance each time
you want to list all images or filter by all images which
is inefficiant&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;assignee&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;sorrison&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
</description><pubDate>Thu, 16 May 2019 00:00:00 </pubDate></item><item><title>Spec Lite: Add description field to image</title><link>http://specs.openstack.org/openstack/glance-specs/specs/stein/implemented/glance/spec-lite-add-description-field-to-image.html</link><description>

&lt;dl class="field-list"&gt;
&lt;dt class="field-odd"&gt;project&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;glance&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;problem&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;Currently there is not a dedicated image property to record the
description of an image. In most of our customer environments,
users typically upload multiple images. Because of the large
number of users, it is difficult to distinguish the purpose of
an image through the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;name&lt;/span&gt;&lt;/code&gt; field (possibly with duplicate names).&lt;/p&gt;
&lt;p&gt;For example: Nova and Cinder have the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;description&lt;/span&gt;&lt;/code&gt; field,
and the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;description&lt;/span&gt;&lt;/code&gt; field allows you to record the specific
purpose of the object.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;solution&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;Add &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;description&lt;/span&gt;&lt;/code&gt; field as a “common image property” to image.
This way it will appear in the image schema (good for
interoperability purposes) but will be stored as a user-defined
image property (so will not require any database changes).
You can set &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;--property&lt;/span&gt;&lt;/code&gt; to add &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;description&lt;/span&gt;&lt;/code&gt; properties when
executing the CLI.&lt;/p&gt;
&lt;p&gt;This is an exception to the Glance policy that new image properties
should be prefixed with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_&lt;/span&gt;&lt;/code&gt;. It’s not necessary for this spec
for the following reasons.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Under this proposal, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;description&lt;/span&gt;&lt;/code&gt; will be stored as a user
specified (“custom”) image property in the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;image_properties&lt;/span&gt;&lt;/code&gt;
database table.  Because it is not stored as a new column in
the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;images&lt;/span&gt;&lt;/code&gt; table, it will not block the display of any
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;description&lt;/span&gt;&lt;/code&gt; property on currently existing images.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It’s to be expected that a property named &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;description&lt;/span&gt;&lt;/code&gt; will
in fact contain some kind of description of the image it’s a
property of.  Thus we do not expect that there will be an
inconsistency between any existing &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;description&lt;/span&gt;&lt;/code&gt; image
properties and the description of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;description&lt;/span&gt;&lt;/code&gt; that will
appear in the image schema.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Using the name &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;description&lt;/span&gt;&lt;/code&gt; is consistent with the other
services (for example, Nova and Cinder) that recognize
description metadata on resources.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;CLI execution example:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;$ openstack image create \
    --property description='This is a test image file.' \
    --file cirros-0.3.4-x86_64-disk.img \
    --disk-format qcow2 \
    --container-format bare \
    test_image
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;alternatives&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;Do nothing, given that users can already create such a property.
This alternative, however, has the disadvantage that it does not
provide a guideline for local practices to conform with, which
in turn makes interoperability problematic.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;timeline&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;Include in Stein release.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;link&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;&lt;a class="reference external" href="https://review.openstack.org/620433"&gt;https://review.openstack.org/620433&lt;/a&gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;reviewers&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;Brian Rosmaita&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;assignee&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;Brin Zhang&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
</description><pubDate>Thu, 16 May 2019 00:00:00 </pubDate></item><item><title>Spec Lite: Embed validation data with image locations</title><link>http://specs.openstack.org/openstack/glance-specs/specs/stein/implemented/glance/spec-lite-locations-with-validation-data.html</link><description>

&lt;dl class="field-list"&gt;
&lt;dt class="field-odd"&gt;project&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;glance&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;problem&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;A new image using the HTTP store may have its &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;locations&lt;/span&gt;&lt;/code&gt;
initialised using the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;add&lt;/span&gt;&lt;/code&gt; or &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;replace&lt;/span&gt;&lt;/code&gt; operation in an HTTP
PATCH request, but there is currently no way to provide values for
accompanying checksum and multihash values.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;solution&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;Allow embedding of values for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;checksum&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_hash_algo&lt;/span&gt;&lt;/code&gt;
and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_hash_value&lt;/span&gt;&lt;/code&gt; in a new write-only JSON object named
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;validation_data&lt;/span&gt;&lt;/code&gt;, along with the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;url&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;metadata&lt;/span&gt;&lt;/code&gt; for an
image location. These values will be used to populate the
corresponding image properties.&lt;/p&gt;
&lt;p&gt;New values for any of these items will only be accepted if the image
status is &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;queued&lt;/span&gt;&lt;/code&gt; and the corresponding image property is not
already populated. To allow idempotency, this object may be included
when adding or replacing locations for an image which is in
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;active&lt;/span&gt;&lt;/code&gt; status or/and already has the corresponding properties
populated, but the supplied values must exactly match the existing
ones.&lt;/p&gt;
&lt;p&gt;The object may be included in one or more of the items in
a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;locations&lt;/span&gt;&lt;/code&gt; list, but values must be consistent across all
instances.&lt;/p&gt;
&lt;p&gt;Although the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;validation_data&lt;/span&gt;&lt;/code&gt; object will be optional,
if it is present, the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_hash_algo&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_hash_value&lt;/span&gt;&lt;/code&gt; items
will be required, to force adoption of multihash. Since multihash
will be the default mechanism for clients in the Stein release,
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;checksum&lt;/span&gt;&lt;/code&gt; will be optional, but included to accommodate legacy
consumers that have not yet implemented multihash. The consumer
is expected know to to populate &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;checksum&lt;/span&gt;&lt;/code&gt; only if their
deployment requires it.&lt;/p&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_hash_algo&lt;/span&gt;&lt;/code&gt; must match the Glance server’s
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;DEFAULT.hashing_algorithm&lt;/span&gt;&lt;/code&gt; configuration option.  Whilst it seems
redundant to require an input with only one acceptable value, this
is required to ensure that the user knows which algorithm is
required. The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;checksum&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_hash_value&lt;/span&gt;&lt;/code&gt; cannot be verified
(since the Glance server does not have a copy of the image data),
but they will be validated as hexadecimal values of the correct size
for the respective algorithms.&lt;/p&gt;
&lt;p&gt;Any violations of the above rules will result in a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;HTTPConflict&lt;/span&gt;&lt;/code&gt;
exception (HTTP status 409).&lt;/p&gt;
&lt;p&gt;The following will be added to the properties for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;locations&lt;/span&gt;&lt;/code&gt;
items in the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;images&lt;/span&gt;&lt;/code&gt; schema:&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;'validation_data'&lt;/span&gt;&lt;span class="p"&gt;:&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="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="s1"&gt;'Values to be used to populate the corresponding '&lt;/span&gt;
        &lt;span class="s1"&gt;'image properties. If the image status is not '&lt;/span&gt;
        &lt;span class="s1"&gt;'"queued" or/and the image properties are already '&lt;/span&gt;
        &lt;span class="s1"&gt;'populated, any supplied values must exactly match '&lt;/span&gt;
        &lt;span class="s1"&gt;'existing ones.'&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;'writeOnly'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;True&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;'checksum'&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;'minLength'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'maxLength'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;32&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_hash_algo'&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;'maxLength'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;64&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_hash_value'&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;'maxLength'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;128&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_hash_algo'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'os_hash_value'&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;Support will also be added to the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;add_location()&lt;/span&gt;&lt;/code&gt; method and the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;location-add&lt;/span&gt;&lt;/code&gt; shell command in python-glanceclient.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;alternatives&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;Implement an import method to directly register images for use
with the HTTP store (without requiring use of HTTP PATCH).&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;timeline&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;Include in Stein release. Need approval ASAP, so I can proceed with
a private backport for my Rocky upgrades (v1 API removed).&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;link&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;&lt;a class="reference external" href="https://review.openstack.org/597368"&gt;https://review.openstack.org/597368&lt;/a&gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;assignee&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;imacdonn&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
</description><pubDate>Thu, 16 May 2019 00:00:00 </pubDate></item><item><title>Spec Lite: Add glance-cache-manage utility using v2 API</title><link>http://specs.openstack.org/openstack/glance-specs/specs/stein/implemented/glance/spec-lite-readding-glance-cache-manage-for-v2.html</link><description>

&lt;dl class="field-list"&gt;
&lt;dt class="field-odd"&gt;project&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;glance&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;problem&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;In Rocky, the v1 dependant glance-cache-manage command was removed
while removing Images API v1 entry points. As a part of Edge
computing glance cache needs to be enabled on far-edge nodes
via Split Control plane where glance-cache-manage utility will be
essential to queue image for prefetching, to list &amp;amp; delete images
from Image Cache.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;solution&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;In Stein, as per Edge computing architecture, glance cache will be
enabled on far-edge nodes. Hence it will be good to add
glance-cache-manage utility using v2 API in glance. This utility
will have the following commands and the same interface as Queens
glance-cache-manage utility [0] insofar as possible,
[0] &lt;a class="reference external" href="https://docs.openstack.org/glance/queens/cli/glancecachemanage.html"&gt;https://docs.openstack.org/glance/queens/cli/glancecachemanage.html&lt;/a&gt;&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;1. Queue the image with identifier &amp;lt;IMAGE_ID&amp;gt; for caching,

   $ glance-cache-manage --host=&amp;lt;HOST&amp;gt; queue-image &amp;lt;IMAGE_ID&amp;gt;

2. List all images currently cached

   $ glance-cache-manage --host=&amp;lt;HOST&amp;gt; list-cached

3. List all images currently queued for caching.

   $ glance-cache-manage --host=&amp;lt;HOST&amp;gt; list-queued

4. Delete an image from the cache

   $ glance-cache-manage --host=&amp;lt;HOST&amp;gt; delete-cached-image &amp;lt;IMAGE_ID&amp;gt;

5. Remove all images from the cache

   $ glance-cache-manage --host=&amp;lt;HOST&amp;gt; delete-all-cached-images

6. Deletes an queued image from the cache

   $ glance-cache-manage --host=&amp;lt;HOST&amp;gt; delete-queued-image &amp;lt;IMAGE_ID&amp;gt;

7. Remove all images from the cache queue

   $ glance-cache-manage --host=&amp;lt;HOST&amp;gt; delete-all-queued-images
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;alternatives&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;None&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;impacts&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;DocImpact&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;timeline&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;Include in Stein release.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;link&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;None&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;assignee&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;pdeore&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
</description><pubDate>Thu, 16 May 2019 00:00:00 </pubDate></item><item><title>Running Glance on Windows</title><link>http://specs.openstack.org/openstack/glance-specs/specs/stein/implemented/glance/windows-support.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/glance/+spec/windows-support"&gt;https://blueprints.launchpad.net/glance/+spec/windows-support&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The goal is to allow Glance services to run on Windows, which enables Hyper-V
OpenStack deployments to take full advantage of Microsoft storage solutions.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;At the moment, Glance services cannot be run on Windows. To bring some context,
there are OpenStack deployments that rely on Hyper-V compute nodes along with
other Microsoft technologies.&lt;/p&gt;
&lt;p&gt;In terms of storage, the most commonly used SDS solution is Storage Spaces
Direct (S2D) along with highly available Scale-Out File Server (SoFS) SMB
shares.&lt;/p&gt;
&lt;p&gt;One issue is that the Linux cifs driver currently provides limited HA SMB share
support (most versions can’t even connect to HA shares, there’s no Witness
service support, automatic failover was recently added).&lt;/p&gt;
&lt;p&gt;That being considered, most deployers have to use a separate storage backend
for their Glance images (e.g. Swift, Ceph, etc).&lt;/p&gt;
&lt;p&gt;Allowing Glance to run on Windows will allow deployers to benefit more from
their S2D backends, commonly used for storing VM disks (currently handled by
Nova as root images or Cinder as attachable volumes). In particular, this will
be useful for hyper-converged deployments, where having to deploy yet another
storage backend may not be desired.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Getting Glance services to run on Windows is not that difficult. There are just
a few things that we need to change:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;avoid forking, not available on Windows&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;avoid unavailable signals&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;avoid renaming/deleting in-use files&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;avoid using binaries that aren’t available on Windows&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;avoid having eventlet monkey-patch the os module as this will cause
subprocess.Popen to fail&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;avoid missing features or libraires (e.g. xattr)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;some small differences in path handling (‘/’ will be handled as a relative
path)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;avoid connecting to ‘0.0.0.0’, use ‘127.0.0.1’ instead. This mostly applies
to the functional tests&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All the above points are covered in less than 150 LOC (a few hundred more if we
count the tests as well), without affecting the Linux behavior.&lt;/p&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os-win&lt;/span&gt;&lt;/code&gt; library will be used for most of the Windows low-level
operations, which is an official OpenStack project.&lt;/p&gt;
&lt;p&gt;The main goal is to use the filesystem driver along with SMB shares or
Cluster Shared Volumes (CSV).&lt;/p&gt;
&lt;p&gt;IIS will not be supported initially, using eventlet wsgi instead (which happens
to be the recommended way of deploying Glance at the moment).&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;For Hyper-V deployments, the alternative is to keep running Glance on separate
Linux hosts, having to deploy an additional storage backend or go with the
limited HA SMB share support that’s currently available on Linux.&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;Performance wise, there shouldn’t be any big differences. Spinning up new
processes may be a bit slower on Windows, for which reason the functional
tests may take longer to complete.&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;Glance will now be able to run on Windows. Not much changes config wise.&lt;/p&gt;
&lt;p&gt;Keep in mind that we’re mainly targeting the file store for the beginning
(which is the main reason we want Glance to run on Windows).&lt;/p&gt;
&lt;p&gt;Glance will prefferably run as a Windows service. In general, we provide MSI
packages that simplify installing and configuring OpenStack services (e.g.
Nova, Neutron agent, Cinder, etc), which can also be run unattendedly.&lt;/p&gt;
&lt;p&gt;We intend to provide Juju charms as well that will allow deploying Glance
on Windows.&lt;/p&gt;
&lt;p&gt;One thing to note is that &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os-win&lt;/span&gt;&lt;/code&gt; currently supports Windows Sever 2012 or
above.&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 keep in mind that Glance is supposed to be portable.&lt;/p&gt;
&lt;p&gt;Judging from past experience, this hasn’t been a problem with other
OpenStack projects. Glance doesn’t use too many platform specific libraries
or binaries, so it should be fine.&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;lpetrut&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;p&gt;This work has been divided in 3 patches:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;a small patch that allows Glance services to run on Windows&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;an additional one that allows multiple processes to be used by API services&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;a patch that allows all Glance unit and functional tests to run on Windows&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A few small changes were needed on &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os-win&lt;/span&gt;&lt;/code&gt; as well, exposing some low-level
Windows primitives.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;We rely on &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os-win&lt;/span&gt;&lt;/code&gt;, which is an official OpenStack library that exposes
low-level Windows functionality. It’s currently used by a few other OpenStack
projects, such as Nova, Cinder, Ceilometer, networking-hyperv, etc.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;The already existing tests provide enough coverage. Still, the unit and
functional tests will need some small changes in order to be able to run on
Windows (currently relying on some Linux specific functionality).&lt;/p&gt;
&lt;p&gt;We intend to provide 3rd party CI testing. For the record, we’re currently
voting on Nova, Cinder and Neutron patches, running tests against Hyper-V.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;The documentation should be updated to point out the fact that Glance is now
Windows compatible, along with some installing and configuration guide.&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.microsoft.com/en-us/windows-server/failover-clustering/sofs-overview"&gt;SOFS Overview&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://support.microsoft.com/en-nz/help/2709568/new-smb-3-0-features-in-the-windows-server-2012-file-server"&gt;SMB3 Overview&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/os-win"&gt;os_win repo&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://github.com/torvalds/linux/blob/v4.20/Documentation/filesystems/cifs/TODO"&gt;linux cifs module missing features&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
</description><pubDate>Thu, 16 May 2019 00:00:00 </pubDate></item><item><title>Spec Lite: Show Store Info</title><link>http://specs.openstack.org/openstack/glance-specs/specs/stein/implemented/python-glanceclient/spec-lite-show-store-info.html</link><description>

&lt;dl class="field-list simple"&gt;
&lt;dt class="field-odd"&gt;project&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;python-glanceclient&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;problem&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;In multi-store environment, user may want to know which backend store
images are stored in. But currently store info (store id) can only be
showed in command “glance image-show” which can only show one image.
It’s not convenient when want to know the store info of a list of
images.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;solution&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;This spec aims to add –include-stores option to image-list, command
like “glance image-list –include-stores”. As store id is the same
in most of production environment, so it’s not good to list this
info in -v, otherwise the store id column will be the same value and
it’s a bit redundant.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;impacts&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;None&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;timeline&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;S-1&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;assignee&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;LiangFang&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
</description><pubDate>Thu, 16 May 2019 00:00:00 </pubDate></item><item><title>Barbican secret deletion support</title><link>http://specs.openstack.org/openstack/glance-specs/specs/train/approved/glance/barbican-secret-deletion-support.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/glance/+spec/barbican-secret-deletion-support"&gt;https://blueprints.launchpad.net/glance/+spec/barbican-secret-deletion-support&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The Block Storage Service (Cinder) offers end users the ability to create
images from encrypted volume types.  When it does this, Cinder stores a secret
in Barbican in a 1-1 relation to the image and puts the Barbican ID of the
secret as an image property, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cinder_encryption_key_id&lt;/span&gt;&lt;/code&gt;.  When a user deletes
such an image, the Barbican secret is no longer applicable to any resource, but
it persists in Barbican.  As a result, deployers have a situation where useless
secrets are piling up in Barbican.  This would be mitigated if Glance deleted
the unique Barbican secret of an image at the time of image deletion.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Cinder would like Glance to delete a resource (the Barbican secret) that Glance
has not created.  Given that most deployments allow users to set custom image
properties, it’s possible for a user to put the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cinder_encryption_key_id&lt;/span&gt;&lt;/code&gt;
metadata on any image, which could result in the premature deletion of an
in-use key since the 1-1 relation between Barbican secret ID and Glance image
has been broken.  Hence Glance is reluctant to implement functionality that
could result in end user data loss.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Add the Glance common image property &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cinder_encryption_key_deletion_policy&lt;/span&gt;&lt;/code&gt;.
At this time, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cinder_encryption_key_id&lt;/span&gt;&lt;/code&gt; will also be added as a common image
property.  Since the common image properties are stored in the image_properties
table, they must have a JSON type of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;string&lt;/span&gt;&lt;/code&gt;.  As common image properties,
they will be added to the default &lt;strong&gt;schema-image.json&lt;/strong&gt; file 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="s2"&gt;"cinder_encryption_key_id"&lt;/span&gt;&lt;span class="p"&gt;:&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;"Identifier in the OpenStack Key Management Service for the encryption key for the Block Storage Service to use when mounting a volume created from this image"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"string"&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="s2"&gt;"cinder_encryption_key_deletion_policy"&lt;/span&gt;&lt;span class="p"&gt;:&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;"States the condition under which the Image Service will delete the object associated with the 'cinder_encryption_key_id' image property.  If this property is missing, the Image Service will take no action"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s2"&gt;"enum"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="s2"&gt;"on_image_deletion"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"do_not_delete"&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 class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;Note: The common image properties are interoperability suggestions but are
not mandatory features of Glance.  As such, there is no guarantee that a
particular Glance installation will allow them to be listed in the
image-schema response.  Thus, we cannot rely on schema-validation of the
value for this property.  Note that this does not affect Cinder writing
these properties to images (as long as the Glance configuration option
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;allow_additional_image_properties&lt;/span&gt;&lt;/code&gt; is True, which is its default value).&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 should seriously consider deprecating the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;allow_additional_image_properties&lt;/span&gt;&lt;/code&gt; configuration option during this
cycle.  I believe it was originally introduced to prevent users from
flooding the image_properties table with junk and it predated the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;image_property_quota&lt;/span&gt;&lt;/code&gt; option.  Now that we have the latter option, it’s
really unnecessary, and if an operator were to set it False, all sorts of
stuff would break as multiple OpenStack services currently write/rely on
custom 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;There’s a bug someone asked me about in IRC once (I can’t find it in
Launchpad, it may not have been filed) that an operator can modify
/etc/schema-image.json to include arbitrary properties (which was that
file’s original purpose) and assign them JSON types other than ‘string’.
The type is enforced by image create/update but you get a 500 because it has
to be a string in the database (but the API won’t accept a string if the
schema says it’s boolean or something).  We should document that these
things &lt;em&gt;must&lt;/em&gt; be strings.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;The presence of this property with the appropriate value gives Glance explicit
permission to delete the key, even though Glance has not created it.  When this
property is present on an image with the value ‘on_image_deletion’, Glance will
search the image’s properties for the property &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cinder_encryption_key_id&lt;/span&gt;&lt;/code&gt;.
If it exists, Glance will make a request to Barbican to delete the secret whose
ID is the value of the image property.&lt;/p&gt;
&lt;p&gt;Because &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cinder_encryption_key_deletion_policy&lt;/span&gt;&lt;/code&gt; is a custom image property,
it can be added/deleted/updated by the image owner.  Hence, if the image owner
has a reason to preserve a key, permission to delete can be revoked by changing
the value to ‘do_not_delete’ or by simply deleting the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cinder_encryption_key_deletion_policy&lt;/span&gt;&lt;/code&gt; property.&lt;/p&gt;
&lt;p&gt;Error conditions:&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;cinder_encryption_key_id&lt;/span&gt;&lt;/code&gt; is not present on the image, image deletion
will not be affected by the presence of
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;delete_encryption_key_on_image_deletion:&lt;/span&gt; &lt;span class="pre"&gt;on_image_deletion&lt;/span&gt;&lt;/code&gt;.&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;cinder_encryption_key_id&lt;/span&gt;&lt;/code&gt; indicates a nonexistent Barbican ID, this
should be logged, but will not affect image deletion.&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;cinder_encryption_key_deletion_policy&lt;/span&gt;&lt;/code&gt; has a value other than
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;on_image_deletion&lt;/span&gt;&lt;/code&gt; or &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;do_not_delete&lt;/span&gt;&lt;/code&gt;, Glance will do the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;take no action with respect to the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cinder_encryption_key_id&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;delete the image&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;&lt;p&gt;Do nothing and leave it up to the end user to explicitly delete the secret
from Barbican.  This is problematic for the Cinder workflow, which has kept
secret management hidden from the user, hence the user may not be aware
until sometime after the image has been deleted (and its metadata gone) that
the Barbican secret can be deleted, and the secret ID is no longer
available.  Since it’s impossible to know for any secret whether anything
might be holding a reference to it, the user can’t simply go to Barbican and
determine what secrets are no longer in use.  So this is not a really a
viable alternative.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Leave the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cinder_encryption_key_id&lt;/span&gt;&lt;/code&gt; as the only metadatum, and have
its presence be sufficient for Glance to delete the secret upon image
deletion.  This has the drawback that an end user who’s using the Cinder
feature in a nonstandard way has no way to prevent Glance from deleting
a Barbican secret that may still be in use.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Do not make &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cinder_encryption_key_deletion_policy&lt;/span&gt;&lt;/code&gt; a common image
property, but instead let it be a regular custom image property, similar
to the custom image properties that are recognized by the Nova scheduler.
Because of the data loss possibility posed by automatic secret deletion,
it would be better to have its function clearly documented in the image
schema, rather than leaving this to documentation only.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Make &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cinder_encryption_key_deletion_policy&lt;/span&gt;&lt;/code&gt; a boolean instead of an
enumerated string type.  Unfortunately, it cannot actually be a boolean
type because it must be stored as a string, which is confusing for tooling
developers because its value would be &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;"true"&lt;/span&gt;&lt;/code&gt;, not the JSON &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;true&lt;/span&gt;&lt;/code&gt;
value.  Additionally, an image-show response containing:&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;cinder_encryption_key_deletion_policy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;on_image_deletion&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;is self-documenting with respect to what this image property means.&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.  A common image property appears in the image schema, but is stored in
the image_properties table with the custom image properties.&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 impact on the security of Glance.  This arguably makes the Cinder-Glance
volume-to-image functionality more secure.  It no longer leaves a user in
the position of having to clear out a bunch of excess secrets from Barbican,
one of which may actually be in use.  Additionally, it doesn’t require a
user to manually delete a key (the user might delete the wrong one).&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 Cinder workflow is designed to hide key handling from the user; this
is consistent with that design.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;Glance will need to make a call to Barbican as part of the image delete
process.&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 will be a bonus to deployers who will no longer have to worry about
useless Barbican secrets piling up.&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;brian-rosmaita or abhishek-kekane&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;Modify the image schema to include the new common image property and
to make the current property Cinder uses, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cinder_encryption_key_id&lt;/span&gt;&lt;/code&gt;,
an official common image property.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Implement the code to delete the secret in Barbican upon image deletion.&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;Since the scenario we’re interested in is whether Glance can delete a secret
from Barbican under certain conditions, a tempest test could be implemented
that creates a secret, puts the appropriate metadata on an image, deletes the
image and verifies that the Barbican secret is/is not deleted.&lt;/p&gt;
&lt;p&gt;If there’s an existing tempest test that actually creates an image of an
encrypted volume in Glance, then we could piggyback on that to verify that key
deletion occurs.  This, of course, would have to wait until Cinder has
implemented putting the new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cinder_encryption_key_deletion_policy&lt;/span&gt;&lt;/code&gt; flag on
images created from encrypted volumes.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Document the new properties along with the rest of the common image properties.&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 discussion: &lt;a class="reference external" href="https://etherpad.openstack.org/p/cinder-train-ptg-planning"&gt;https://etherpad.openstack.org/p/cinder-train-ptg-planning&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
</description><pubDate>Thu, 02 May 2019 00:00:00 </pubDate></item><item><title>Replace Snet Config with Endpoint Config</title><link>http://specs.openstack.org/openstack/glance-specs/specs/kilo/replace-snet-config-with-endpoint-config.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/glance/+spec/replace-snet-config-with-endpoint-config"&gt;https://blueprints.launchpad.net/glance/+spec/replace-snet-config-with-endpoint-config&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The snet option forces the deployer to name the desired endpoint after
the public endpoint.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;The snet option forces the deployer to name the desired endpoint after
the public endpoint. In order to switch between multiple internal
networks, names have to be changed.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Instead of constructing a URL with a prefix from what is returned by
auth, specify the full URL via configuration (e.g.
&lt;a class="reference external" href="https://www.example.com/v1/not_a_container"&gt;https://www.example.com/v1/not_a_container&lt;/a&gt;). The location of an object
is obtained by appending the container and object to the configured URL.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Only use auth v2. Store and retrieve multiple internal endpoints from the
catalog. This is the preferred approach and requires migrating code that is
using v1 to v2 which is a much larger and completely separate effort.
Furthermore, a configurable endpoint could still be useful for overriding
catalog.&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;Configuration options will change:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Removed config option: “swift_enable_snet”. The default value of
“swift_enable_snet” was False [1]. The comments indicated not to change this
default value unless you are Rackspace [2].&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Added config option “swift_store_endpoint”. The default value of
“swift_store_endpoint” is None, in which case the storage url from the auth
response will be used. If set, the configured endpoint will be used. Example
values: “swift_store_endpoint” = “&lt;a class="reference external" href="https://www.example.com/v1/not_a_container"&gt;https://www.example.com/v1/not_a_container&lt;/a&gt;”&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://github.com/openstack/glance/blob/fd5a55c7f386a9d9441d5f1291ff6a92f7e6cc1b/etc/glance-api.conf#L525"&gt;https://github.com/openstack/glance/blob/fd5a55c7f386a9d9441d5f1291ff6a92f7e6cc1b/etc/glance-api.conf#L525&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/glance/blob/fd5a55c7f386a9d9441d5f1291ff6a92f7e6cc1b/etc/glance-api.conf#L520"&gt;https://github.com/openstack/glance/blob/fd5a55c7f386a9d9441d5f1291ff6a92f7e6cc1b/etc/glance-api.conf#L520&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&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;jesse-j-cook&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="reviewers"&gt;
&lt;h3&gt;Reviewers&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Core reviewer(s):&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;nikhil-komawar&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other reviewer(s):&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;johngarbutt
ben-roble&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 code to use endpoint config&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Remove snet prefix 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;Verify auth works&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Verify configured endpoint is reached&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 new endpoint configuration option.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Remove documentation for snet configuration option.&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;&lt;a class="reference external" href="https://review.openstack.org/#/c/139726/"&gt;https://review.openstack.org/#/c/139726/&lt;/a&gt;&lt;/p&gt;
&lt;/section&gt;
</description><pubDate>Thu, 27 Dec 2018 00:00:00 </pubDate></item><item><title>Spec Lite: Add periodic job to prefetch images into cache</title><link>http://specs.openstack.org/openstack/glance-specs/specs/train/approved/glance/spec-lite-cache-prefetcher.html</link><description>

&lt;dl class="field-list simple"&gt;
&lt;dt class="field-odd"&gt;project&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;glance&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;problem&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;During Queens release glance registry is marked as deprecated and
will be removed during Train cycle. Glance cache-prefetcher utility
uses glance registry to cache the images.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;solution&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;In Train, as per Edge computing architecture, glance cache will be
enabled on far-edge nodes. As of now glance-cache-prefetcher is
dependent on registry which is deprecated and due for removal.
In order to remove the dependency on registry, we are proposing
to add a new periodic job to glance-api service which will run
as per interval set using ‘cache_prefetcher_interval’
configuration option and fetch images which are queued for
caching in cache directory. This new periodic job will only run
if cache is enabled by the operator.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;alternatives&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;None&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;impacts&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;DocImpact&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;timeline&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;Include in Train release.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;link&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;None&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;assignee&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;abhishekk&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
</description><pubDate>Thu, 27 Dec 2018 00:00:00 </pubDate></item><item><title>Ocata Review Priorities</title><link>http://specs.openstack.org/openstack/glance-specs/priorities/ocata-priorities.html</link><description>
&lt;span id="ocata-priorities"/&gt;
&lt;p&gt;Here are the Ocata review priorities.&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;Priority Item&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Owner(s)&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Spec(s)&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;OpenStack “Community” Goal&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://launchpad.net/~abhishek-kekane"&gt;Abhishek Kekane&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://launchpad.net/~abashmak"&gt;Alexander Bashmakov&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/td&gt;
&lt;td&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://bugs.launchpad.net/python-glanceclient/+bug/1639487"&gt;eliminate oslo incubated code&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Community Images&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://launchpad.net/~timothy-symanczyk"&gt;Timothy Symanczyk&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://launchpad.net/~dharini-chandrasekar"&gt;Dharini Chandrasekar&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/td&gt;
&lt;td&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://specs.openstack.org/openstack/glance-specs/specs/newton/approved/glance/community_visibility.html"&gt;community images&lt;/a&gt;&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;Image Import Refactor&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://launchpad.net/~jokke"&gt;Erno Kuvaja&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://launchpad.net/~cyril-roelandt"&gt;Cyril Roelandt&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/td&gt;
&lt;td&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="http://specs.openstack.org/openstack/glance-specs/specs/mitaka/approved/image-import/image-import-refactor.html"&gt;image import refactor&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Rolling Upgrades&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://launchpad.net/~hemanth-makkapati"&gt;Hemanth Makkapati&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://launchpad.net/~abashmak"&gt;Alexander Bashmakov&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/td&gt;
&lt;td&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://specs.openstack.org/openstack/glance-specs/specs/ocata/approved/glance/rolling-upgrades.html"&gt;rolling upgrades&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://specs.openstack.org/openstack/glance-specs/specs/ocata/approved/glance/database-strategy-for-rolling-upgrades.html"&gt;database strategy&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://specs.openstack.org/openstack/glance-specs/specs/ocata/approved/glance/alembic-migrations.html"&gt;alembic migrations&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;section id="important-dates"&gt;
&lt;h2&gt;Important dates&lt;/h2&gt;
&lt;p&gt;This is an abbreviated list focused on dates relevant to Glance.  See
&lt;a class="reference external" href="https://releases.openstack.org/ocata/schedule.html"&gt;Ocata Release Schedule&lt;/a&gt;
for the complete list for OpenStack.&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;Milestone&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Week of&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;What&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;R-15&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;November 7&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Glance spec proposal freeze&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;R-14&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;November 14&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;O-1 milestone&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;R-13&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;November 21&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;strong&gt;Glance spec freeze&lt;/strong&gt;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;R-10&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;December 12&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;O-2 milestone&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;R-9 through R-7&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;December 19 through January 6&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;expect team to be half-strength (at best) due to holidays&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;R-5&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;January 16&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;glance_store Ocata release (final release for non-client libraries)&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;R-4&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;January 23&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;O-3 milestone, &lt;strong&gt;Glance feature freeze&lt;/strong&gt;, python-glanceclient Ocata
release (final release for client libraries)&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;R-3&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;January 30&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;RC-1 release and &lt;strong&gt;string freeze&lt;/strong&gt;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;R-1&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;February 13&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;final RCs&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;R-0&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;February 20&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;strong&gt;Ocata release&lt;/strong&gt;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Mon, 12 Nov 2018 00:00:00 </pubDate></item><item><title>Pike Review Priorities</title><link>http://specs.openstack.org/openstack/glance-specs/priorities/pike-priorities.html</link><description>
&lt;span id="pike-priorities"/&gt;
&lt;p&gt;Here are the Pike review priorities.  Due to the Pike cycle Glance personnel
situation, this list is reduced from what was published on the &lt;a class="reference external" href="https://etherpad.openstack.org/p/glance-pike-ptg-roadmap-prelim"&gt;PTG etherpad&lt;/a&gt;.
Thus in this cycle we’re introducing a category of &lt;em&gt;untargeted&lt;/em&gt; specs.  These
specs have been reviewed, approved, and are sufficiently detailed that they
could be implemented by new contributors, but given the current personnel
situation, we cannot realistically include them as priorities for the Pike
release.&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;Priority Item&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Owner(s)&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Spec(s)&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 Import Refactor&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;a class="reference external" href="https://launchpad.net/~jokke"&gt;Erno Kuvaja&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;a class="reference external" href="https://specs.openstack.org/openstack/glance-specs/specs/mitaka/approved/image-import/image-import-refactor.html"&gt;image import refactor&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;OpenStack Pike “Community” Goal 1&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;was &lt;a class="reference external" href="https://launchpad.net/~abashmak"&gt;Alexander Bashmakov&lt;/a&gt;, seeking new owner&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;a class="reference external" href="https://specs.openstack.org/openstack/glance-specs/specs/pike/approved/glance/lite-specs.html#community-goal-support-python-3-5"&gt;support python 3.5&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;OpenStack Pike “Community” Goal 2&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;a class="reference external" href="https://launchpad.net/~treinish"&gt;Matthew Treinish&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;a class="reference external" href="https://specs.openstack.org/openstack/glance-specs/specs/pike/approved/glance/lite-specs.html#community-goal-control-plane-api-endpoints-deployment-via-wsgi"&gt;control plane API endpoints deployment via WSGI&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;section id="important-dates"&gt;
&lt;h2&gt;Important dates&lt;/h2&gt;
&lt;p&gt;This is an abbreviated list focused on dates relevant to Glance.  See
&lt;a class="reference external" href="https://releases.openstack.org/pike/schedule.html"&gt;Pike Release Schedule&lt;/a&gt;
for the complete list for OpenStack.&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;Milestone&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Week of&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;What&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;R-22&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;March 27&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Glance spec proposal freeze&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;R-20&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;April 10&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;P-1 milestone&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;R-19&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;April 17&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;virtual midcycle meeting; &lt;strong&gt;Glance spec freeze&lt;/strong&gt;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;R-16&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;May 8&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;OpenStack Summit/Forum&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;R-12&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;June 5&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;P-2 milestone&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;R-6&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;July 17&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;glance_store Pike release (final release for non-client libraries)&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;R-5&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;July 24&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;P-3 milestone; &lt;strong&gt;Glance feature freeze&lt;/strong&gt;;
python-glanceclient Pike release (final release for client libraries);
Pike community goals completion&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;R-3&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;August 7&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;RC-1 release and &lt;strong&gt;string freeze&lt;/strong&gt;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;R-1&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;August 21&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;final RCs&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;R-0&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;August 28&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;strong&gt;Pike release&lt;/strong&gt;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Mon, 12 Nov 2018 00:00:00 </pubDate></item><item><title>Queens Review Priorities</title><link>http://specs.openstack.org/openstack/glance-specs/priorities/queens-priorities.html</link><description>
&lt;span id="queens-priorities"/&gt;
&lt;p&gt;The Queens review priorities were discussed at the Denver PTG and refined
during the spec review process early in the Queens cycle.  The preliminary
list was maintained on the &lt;a class="reference external" href="https://etherpad.openstack.org/p/glance-queens-ptg-roadmap"&gt;Denver PTG etherpad&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This list is an estimate of what the Glance project team can accomplish
during the Queens cycle based on our developers’ estimates of how much
time they can commit to Glance.  If additional resources become available,
it’s possible that some of the &lt;a class="reference internal" href="../specs/untargeted/index.html"&gt;&lt;span class="doc"&gt;Untargeted Approved Specifications&lt;/span&gt;&lt;/a&gt; could be
added to Queens.&lt;/p&gt;
&lt;p&gt;The following list is roughly in priority order (highest to lowest).&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;Priority Item&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Owner(s)&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Spec(s)&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 Import Refactor&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;a class="reference external" href="https://launchpad.net/~jokke"&gt;Erno Kuvaja&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;a class="reference external" href="https://specs.openstack.org/openstack/glance-specs/specs/mitaka/approved/image-import/image-import-refactor.html"&gt;image import refactor&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Inject Metadata Automatically&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;a class="reference external" href="https://launchpad.net/~abhishek-kekane"&gt;Abhishek Kekane&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;a class="reference external" href="https://specs.openstack.org/openstack/glance-specs/specs/queens/approved/glance/inject-automatic-metadata.html"&gt;inject metadata automatically&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Secure Hash Algorithm Support&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;a class="reference external" href="https://launchpad.net/~smcclymont"&gt;Scott McClymont&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;a class="reference external" href="https://specs.openstack.org/openstack/glance-specs/specs/queens/approved/glance/multihash.html"&gt;multihash&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Fix OSSN-0075&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;a class="reference external" href="https://launchpad.net/~brian-rosmaita"&gt;Brian Rosmaita&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;a class="reference external" href="https://review.openstack.org/#/c/468179/"&gt;fix ossn-0075&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Glanceclient: Switch to Turn Off Schema Validation&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;unassigned&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;a class="reference external" href="https://specs.openstack.org/openstack/glance-specs/specs/queens/approved/python-glanceclient/no-schema-validation.html"&gt;validation switch&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Refactor Glance Scrubber&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;a class="reference external" href="https://launchpad.net/~wangxiyuan"&gt;Xiyuan Wang&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;a class="reference external" href="https://specs.openstack.org/openstack/glance-specs/specs/queens/approved/glance/lite-spec-scrubber-refactor.html"&gt;refactor glance scrubber&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Remove the Images API v1&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;a class="reference external" href="https://launchpad.net/~brian-rosmaita"&gt;Brian Rosmaita&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;a class="reference external" href="https://specs.openstack.org/openstack/glance-specs/specs/queens/approved/glance/remove-v1.html"&gt;remove v1&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Actually Deprecate the Glance Registry&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;a class="reference external" href="https://launchpad.net/~jokke"&gt;Erno Kuvaja&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;a class="reference external" href="https://specs.openstack.org/openstack/glance-specs/specs/queens/approved/glance/deprecate-registry.html"&gt;deprecate glance registry&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Glanceclient: Deprecate Images API v1 Support&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;a class="reference external" href="https://launchpad.net/~brian-rosmaita"&gt;Brian Rosmaita&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;a class="reference external" href="https://specs.openstack.org/openstack/glance-specs/specs/queens/approved/python-glanceclient/deprecate-v1-support.html"&gt;deprecate v1 support&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;OpenStack Queens “Community” Goal&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;a class="reference external" href="https://launchpad.net/~lbragstad"&gt;Lance Bragstad&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;a class="reference external" href="https://specs.openstack.org/openstack/glance-specs/specs/queens/approved/glance/spec-lite-policy-and-docs-in-code.html"&gt;policy in code&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;section id="important-dates"&gt;
&lt;h2&gt;Important dates&lt;/h2&gt;
&lt;p&gt;This is an abbreviated list focused on dates relevant to Glance.  See
&lt;a class="reference external" href="https://releases.openstack.org/queens/schedule.html"&gt;Queens Release Schedule&lt;/a&gt; for the complete list for OpenStack.&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;Milestone&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Week of&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;What&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;R-22&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Sept 25&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Glance spec proposal freeze (Thursday 28 Sept 13:00 UTC)&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;R-21&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Oct 2&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;strong&gt;Glance spec freeze&lt;/strong&gt; (Friday 6 Oct 23:59 UTC)&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;R-19&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Oct 16&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Q-1 milestone&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;R-16&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Nov 6&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Sydney Summit/Forum (expect low activity)&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;R-12&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Dec 4&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Q-2 milestone&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;R-9&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Dec 25&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Holidays (expect low activity)&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;R-8&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Jan 1&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Holidays (expect low activity)&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;R-6&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Jan 8&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;glance_store Queens release (final release for non-client libraries)&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;R-5&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Jan 22&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Q-3 milestone&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Glance feature freeze&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;python-glanceclient Queens release (final release for client libraries);&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;remove Images API v1&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;remove Registry API v1&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Queens community goal completion&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;R-3&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Feb 5&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;RC-1 release and &lt;strong&gt;string freeze&lt;/strong&gt;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;R-1&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Feb 19&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;final RCs&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;R-0&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Feb 26&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;strong&gt;Queens release&lt;/strong&gt;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Mon, 12 Nov 2018 00:00:00 </pubDate></item><item><title>Spec Lite: Rethinking our filesystem access</title><link>http://specs.openstack.org/openstack/glance-specs/specs/train/approved/glance/spec-lite-rethinking-filesystem-access.html</link><description>

&lt;dl class="field-list"&gt;
&lt;dt class="field-odd"&gt;project&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;glance&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;problem&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;Glance use filesystem in quite a few places with various mechanisms.
Tasks and staging operation introduced as a part of import image
workflow are consuming glance_store by overriding the configs and
initializing the store via internal functions.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;solution&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;In Rocky multiple backend support is added as experimental feature.
We should use this to reserve certain stores for these operations.
As a part of this we will deprecate work_dir and node_staging_uri
configuration options and reserve two filesystem stores
‘os_glance_tasks_store’ and ‘os_glance_staging_store’, which can
be used to get rid of initializing store via internal functions.
These stores will be &lt;em&gt;hard-coded&lt;/em&gt; in glance for the time being
and injected to enabled_backends config option to load when
glance_store will be initialized at the time of glance-api service
starts. Operator needs to insure that these stores will not be
included in enabled_backends config option in glance-api.conf.&lt;/p&gt;
&lt;p&gt;These reserved stores will be injected only if &lt;em&gt;multiple backends
are enabled&lt;/em&gt; i.e. enabled_backends config option is defined in
glance-api.conf. If multiple backend is not enabled then
node_staging_uri and work_dir config options will work as it is.&lt;/p&gt;
&lt;p&gt;Sample code to show how these config options will be injected and
used:&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;reserved_stores&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s1"&gt;'os_glance_staging_store'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'file'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'os_glance_tasks_store'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'file'&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;enabled_backends&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="n"&gt;enabled_backends&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;enabled_backends&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;enabled_backends&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;reserved_stores&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Then operators need to ensure to have below sections defined in
glance-api.conf:&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;os_glance_tasks_store&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;filesystem_store_datadir&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&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;glance&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;tasks_work_dir&lt;/span&gt;

&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;os_glance_staging_store&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;filesystem_store_datadir&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&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;glance&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;staging&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;NOTE: The path for filesystem_store_datadir for
‘os_glance_tasks_store’ and ‘os_glance_staging_store’ should be
different from actual path if file backend is used. The
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_glance_*&lt;/span&gt;&lt;/code&gt; prefix is reserved for glance and cannot be used
by operators to name their stores.&lt;/p&gt;
&lt;p&gt;‘os_glance_tasks_store’ and ‘os_glance_staging_store’ will be
excluded from ‘stores-info’ call and will not be accepted as
a ‘backend’ option in create image calls.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;alternatives&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;None, carry on using current mechanism.&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;impacts: DocImpact&lt;/p&gt;
&lt;dl class="field-list simple"&gt;
&lt;dt class="field-odd"&gt;timeline&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;Include in Train release.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;link&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;None&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;assignee&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;abhishekk&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
</description><pubDate>Thu, 27 Sep 2018 00:00:00 </pubDate></item><item><title>Stein Project Priorities</title><link>http://specs.openstack.org/openstack/glance-specs/priorities/stein-priorities.html</link><description>
&lt;span id="stein-priorities"/&gt;
&lt;p&gt;TODO: fill this in after the PTG&lt;/p&gt;
</description><pubDate>Thu, 16 Aug 2018 00:00:00 </pubDate></item><item><title>Mitigate OSSN-0075</title><link>http://specs.openstack.org/openstack/glance-specs/specs/rocky/implemented/glance/mitigate-ossn-0075.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/glance/+spec/mitigate-ossn-0075"&gt;https://blueprints.launchpad.net/glance/+spec/mitigate-ossn-0075&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;OpenStack Security Note &lt;a class="reference external" href="https://wiki.openstack.org/wiki/OSSN/OSSN-0075"&gt;OSSN-0075&lt;/a&gt;, “Deleted Glance image IDs may be
reassigned”, was made public on 13 September 2016.  The current situation is
that due to a lack of agreement of how to fix it, we’ve left operators in a bad
state: our advice is that soft-deleted rows in the ‘images’ table in the Glance
database should &lt;em&gt;not&lt;/em&gt; be purged from the database, yet at the same time, the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance-manage&lt;/span&gt;&lt;/code&gt; tool deletes such rows without warning.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Briefly, the problem is that Glance has always allowed a user with permission
to make the image-create call the option of specifying an image_id.  If the
specified image_id clashed with an existing image_id, the image-create
operation would fail; otherwise, the specified image_id would be applied to the
new image.  Consistency is enforced by a uniqueness constraint on the ‘id’
column in the ‘images’ table in the database.  Since Glance database entries
are soft-deleted, a proposed image_id will be checked against all image_ids
that were assigned since the last purge of the ‘images’ table.&lt;/p&gt;
&lt;p&gt;As described in &lt;a class="reference external" href="https://wiki.openstack.org/wiki/OSSN/OSSN-0075"&gt;OSSN-0075&lt;/a&gt;, this problem becomes a security exploit when (a)
a popular public or community image is deleted, (b) the database is purged,
and (c) a user creates a new image with that same image_id.  Users consuming an
image by image_id, which is the way Nova and Cinder consume images, may then
wind up booting virtual machines using an image different from the one they
intend to use.&lt;/p&gt;
&lt;p&gt;Note that the new image would have its own data and checksum that would be
different from the original data and checksum, but there would be no way for
Nova, for instance, to know that these had changed.  Were someone to boot a
server using the image_id, Nova would receive image data and then verify the
checksum against whatever checksum Glance has recorded as associated with the
image, which would be the &lt;em&gt;new&lt;/em&gt; checksum.&lt;/p&gt;
&lt;p&gt;The idea that once an image goes to ‘active’ status, the (image_id, image data,
checksum) will not change is called &lt;em&gt;image immutability&lt;/em&gt;.  It’s important to
note that image immutability is required for Glance or else it cannot function
as an image catalog.  If each consumer had to keep track of the image_id &lt;em&gt;and&lt;/em&gt;
checksum &lt;em&gt;and&lt;/em&gt; other essential properties in order to verify the downloaded
data, then there’d be no point in having Glance maintain this information.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;The primary use case for allowing end-users to specify an image_id at the
time of image creation is to make it easy to find the “same” image data
(that is, the data is bit-for-bit identical although it’s stored in
different locations) in different regions of a cloud.  It’s important to
note that the “sameness” of images in different regions is &lt;em&gt;not&lt;/em&gt; guaranteed
by Glance.  (A Glance installation can guarantee the immutability of images
within its own region, but it has no way of knowing what’s happening in
other regions.)  Thus, under the current situation, when an end user relies
on the image_id as the guarantor that they’re getting the “same” data in
different cloud regions, the end user is actually relying upon the
trustworthiness of the &lt;em&gt;image owner&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;This is a separate issue from &lt;a class="reference external" href="https://wiki.openstack.org/wiki/OSSN/OSSN-0075"&gt;OSSN-0075&lt;/a&gt; and is independent of whether or
not the Glance database is ever purged.  We point it out as something for
operators to keep in mind.  To be clear about the issue, here’s an example.
Suppose that a cloud operator puts an image with image_id A in regions R, S,
T, though for some reason the operator does not put that image in region U.
Any cloud user in region U could create an image with image_id A in
region U.  The image could then be made available to some target user by
image sharing, or with the entire cloud by giving it ‘community’ visibility.&lt;/p&gt;
&lt;p&gt;An operator can avoid this scenario by creating an image record with
image_id A in region U and not uploading any data to it.  The image will
remain in ‘queued’ status, and if the visibility is not changed to ‘public’
or ‘community’, the image will not appear in any end user’s image-list
response.&lt;/p&gt;
&lt;p&gt;There is also room for end user education here, namely, that image
consumers should &lt;em&gt;not&lt;/em&gt; rely solely upon image_id to guarantee that they are
receiving the same image data in cross-region scenarios.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Through discussions with operators, it’s clear that the ability to set the
image_id on image creation is being used out in the field, so we can’t simply
block this ability.  At the same time, we must allow the database to be
occasionally purged, as there is evidence that for large deployments, having a
large number of soft-deleted rows in the ‘images’ table affects the response
time of the image-list API call.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Modify the current &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance-manage&lt;/span&gt; &lt;span class="pre"&gt;db&lt;/span&gt; &lt;span class="pre"&gt;purge&lt;/span&gt;&lt;/code&gt; command so that it will not purge
the images table.&lt;/p&gt;
&lt;p&gt;Introduce a new command, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance-manage&lt;/span&gt; &lt;span class="pre"&gt;db&lt;/span&gt; &lt;span class="pre"&gt;purge-images-table&lt;/span&gt;&lt;/code&gt; to purge the
images table.  The new command will take the same options as the current purge,
namely, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;--age-in-days&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;--max-rows&lt;/span&gt;&lt;/code&gt;.  The rationale for this being a
new command (rather than a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;--force&lt;/span&gt;&lt;/code&gt; option to the current command) is
twofold: (1) it’s likely that the age-in-days used will be different for the
images table, and (2) given that purging the images table has a security
impact, having it as a completely separate command emphasizes this.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;&lt;p&gt;Introduce a policy governing whether or not a user is allowed to specify
the image_id at the time of image creation.  The downside of this proposal
is twofold:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;it breaks backward compatibility given that this ability has been allowed
up to now in both the v1 and v2 versions of the Image API&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;it breaks interoperability in that end uses will have the ability in some
clouds but not in others&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A further problem with this proposal is that if the cross-region use of
a particular image_id is denied to end users, they will have to use some
other piece of image metadata for this purpose.  Since cinder and nova both
use the image_id when services are requested, user workflows will have to
change to introduce an extra call to the image service to find the image
record before the image_id to pass to cinder or nova is determined.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Instead of introducing a new column in the images table, introduce a new
single-column table with a uniqueness constraint to record “used” UUIDs.
The image-create operation would try to insert a proposed UUID into this
table instead of the ‘images’ table and fail as it currently does if the
uniqueness constraint were violated.  This “used” UUID table would &lt;em&gt;never&lt;/em&gt;
be purged, but the glance-manage tool could continue to purge all other
tables.&lt;/p&gt;
&lt;p&gt;This alternative has the advantage of not impacting the image-list call.  It
would eventually introduce a small delay into the image-create operation,
but that’s probably acceptable.&lt;/p&gt;
&lt;p&gt;The downside is that this proposal introduces an unpurgable table that is
unbounded in size.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A variation on alternative #2: instead of a single-column table, have at
least a deleted_at column in addition to the image_id.  This table would not
be touched by the “normal” &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance-manage&lt;/span&gt;&lt;/code&gt; database purge operation.
Rather, an additional purge operation could be introduced for this table
that would purge rows that were, say, 5 years old from the table.&lt;/p&gt;
&lt;p&gt;A problem with this suggestion is that a determined attacker could
nonetheless flood the “used” image_ids table.  This is possible because
while it might make sense to limit the number of existing images a user
owns, it doesn’t make sense to limit the number of deleted images a user
owns.  For example, an end user who creates an image of some important
server every day, but only keeps around a week’s worth, will accumulate many
deleted images (multiplied by the number of servers this is being done for),
but this is perfectly legitimate behavior.  So I’m not sure how flooding the
“used” image_id table could be prevented, except by something like
rate-limiting, though that would have to be set in such a way as not to
impact legitimate use cases.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Introduce a new field, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;preserve_id&lt;/span&gt;&lt;/code&gt;, for use in the images table.  This
field will be for internal Glance use only and will not be exposed through
the API.  This field will be null by default and will be set true whenever
the ‘visibility’ field of an image is set to ‘public’ or ‘community’.  There
will be no way to unset the value of the field.  In addition to this, modify
the glance-manage tool so that it will never delete an entry from the images
table that has &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;preserve_id&lt;/span&gt;&lt;/code&gt; == True.&lt;/p&gt;
&lt;p&gt;As with alternatives 2 and 3, the database table will continue to grow, but
this growth is constrained by keeping only rows relevant to the OSSN-0075
exploit.  On the other hand, all an attacker has to do is read this spec to
realize that by creating image records with community visibilty, the images
table can still be flooded with spurious image records.  Thus this strategy
is too easily defeated to be worth implementing, especially as it might give
operators a false sense of security.&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;This change will enhance security by providing operators with a means of
mitigating the exploit described in &lt;a class="reference external" href="https://wiki.openstack.org/wiki/OSSN/OSSN-0075"&gt;OSSN-0075&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;The images table will grow indefinitely, though the associated tables
(image_properties, image_tags, image_members, image_locations) can be purged by
the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance-manage&lt;/span&gt;&lt;/code&gt; tool.&lt;/p&gt;
&lt;p&gt;The images table can be partially purged at appropriate intervals.&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 have to monitor Glance for abnormal usage patterns and take
appropriate action.&lt;/p&gt;
&lt;p&gt;Additionally, operators should be made aware of the cross-region version of the
OSSN-0075 exploit (as discussed in the Note in the Problem Description
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&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;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;brian-rosmaita&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Other contributors:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;undetermined&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;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Modify the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance-manage&lt;/span&gt;&lt;/code&gt; tool:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;The current behavior is that it purges all tables of soft-deleted rows.
Change the behavior so that the images table is not purged by default.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add a new command to purge the images table.  It should take the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;--age-in-days&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;--max-rows&lt;/span&gt;&lt;/code&gt; options just like the current purge
command.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;update operator documentation&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;release note&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;No new dependencies.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Appropriate unit tests to ensure the changes to glance and the glance-manage
tool 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;The Glance Administrator Guide will need to be updated.&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://wiki.openstack.org/wiki/OSSN/OSSN-0075"&gt;OSSN-0075&lt;/a&gt;: &lt;cite&gt;Deleted Glance image IDs may be reassigned&lt;/cite&gt;.&lt;/p&gt;
&lt;/section&gt;
</description><pubDate>Tue, 07 Aug 2018 00:00:00 </pubDate></item><item><title>multi-store backend support</title><link>http://specs.openstack.org/openstack/glance-specs/specs/rocky/implemented/glance/multi-store.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/glance/+spec/multi-store"&gt;https://blueprints.launchpad.net/glance/+spec/multi-store&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The Image service supports several back ends for storing virtual machine
image namely Block Storage service (cinder), Filesystem (a directory on
a local file system), HTTP, Ceph RBD, Sheepdog, Object Storage service
(swift) and VMware ESX. As of now operator can configure single backend
on a per scheme basis but it’s not possible to configure multiple backends
for same or different stores. For example if a cloud deployment has
multiple ceph deployed glance will not be able to use all those backends
at once.&lt;/p&gt;
&lt;p&gt;Consider the following use cases for providing multi-store backend support:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Deployer might want to provide different level of costing for different
tiers of storage, i.e. One backend for    SSDs and another for
spindles. Customer may choose one of those based on his need.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Old storage is retired and deployer wants to have all new images being
added to new storage and old storage will be operational until data
is migrated.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Operator wants to differentiate the images from images added by user.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Different hypervisors provided from different backends (For
example, Ceph, Cinder, VMware etc.).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Each site with their local backends which nova hosts are accessing
directly (Ceph) and users can select the site where image will be stored.&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;At the moment glance only supports a single store per scheme. So for example,
if an operator wanted to configure the Ceph store (RBD) driver for
2 backend Ceph servers (1 per store), this is not possible today without
substantial changes to the store driver code itself. Even if the store driver
code was changed, the operator today would still have no means to upload or
download image bits from a targeted store without using direct image URLs.&lt;/p&gt;
&lt;p&gt;As a result, operators today needs to perform a number of manual steps
in order to replicate or target image bits on backend glance stores. For
example, in order to replicate a existing image’s bits to secondary storage
of the same type / scheme as the primary:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;It’s a manual out-of-band task to copy image bits to secondary storage.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The operator must manage store locations manually; there is no way to
query the available stores to back an image’s bits in glance.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The operator must remember to register secondary location URL using
the glance API.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Constructing the location URL by hand is error prone as some URLs are
lengthy and complex. Moreover they require knowledge of the backing store
in order to construct properly.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Also consider the case when a glance API consumer wants to download the image
bits from a secondary backend location which was added out-of-band. Today
the consumer must use the direct location URL which implies the consumer
needs the logic necessary to translate that direct URL into a connection
to the backend.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;This spec proposes the following high level features to support multiple
stores of the same scheme/type:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Support in the glance-api.conf and supporting logic to configure, manage
and use multiple stores of the same or different type/scheme.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Enhance the image upload API to (optionally) support targeting a backend
store for the image bits.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Enhance image download code to download image from any of the enabled
backends.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Enhance the image import API to (optionally) support targeting a backend
store to download the image bits from.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Additional metadata attribute(s) added to an image locations’ metadata
properties related to backing stores.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A new REST API to list all configured stores known to the glance service.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;** Config/glance-store changes**&lt;/p&gt;
&lt;p&gt;In order to have multi-store support of same or different type/scheme
we propose to deprecate ‘stores’, ‘default_store’ config option and
add a new config option &lt;cite&gt;enabled_backends&lt;/cite&gt; under DEFAULT section,
‘default_backend’ option under ‘glance_store’ section and
‘description’ option under each section of desired store of
glance-api.conf. Operator can use &lt;cite&gt;enabled_backends&lt;/cite&gt; to specify comma
separated key:value of storage backends and its store type and then
each backends will have a different section to specify related configuration
options. If ‘default_backend’ is not explicitly set then appropriate
exception will be raised which will prevent the service from starting.&lt;/p&gt;
&lt;p&gt;The reason for deprecating ‘default_store’ config option is that glance
verifies the default store at the time of service start and if it is not
one of the listed store (file, http, rbd, swift, cinder, vmware or sheepdog)
then it raises the error and prevents the service from start. This validation
has been done using ‘choices’ attribute of ConfigOption object itself. After
enabling support of multi-store it’s difficult to have this kind of
validation check using ‘choices’ attribute will be difficult as
default_store name will be store identifier and not actual store.&lt;/p&gt;
&lt;p&gt;Consider the following example snippet of glance-api.conf which configures
3 stores for 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;DEFAULT&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="c1"&gt;# list of enabled stores identified by their property group name&lt;/span&gt;
&lt;span class="n"&gt;enabled_backends&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fast&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;rbd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cheap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;rbd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;reliable&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;

&lt;span class="c1"&gt;# the default store, if not set glance-api service will not start&lt;/span&gt;
&lt;span class="n"&gt;default_backend&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fast&lt;/span&gt;

&lt;span class="c1"&gt;# conf props for file system store instance&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;reliable&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;filesystem_store_datadir&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&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;images&lt;/span&gt;&lt;span class="o"&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;description&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Reliable&lt;/span&gt; &lt;span class="n"&gt;filesystem&lt;/span&gt; &lt;span class="n"&gt;store&lt;/span&gt;
&lt;span class="c1"&gt;# etc..&lt;/span&gt;

&lt;span class="c1"&gt;# conf props for ceph store instance&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;fast&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;rbd_store_ceph_conf&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;opt&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;ceph1&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;ceph&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;conf&lt;/span&gt;
&lt;span class="n"&gt;description&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;access&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;rbd&lt;/span&gt; &lt;span class="n"&gt;store&lt;/span&gt;
&lt;span class="c1"&gt;# etc..&lt;/span&gt;

&lt;span class="c1"&gt;# conf props for ceph store instance&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;cheap&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;rbd_store_ceph_conf&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;opt&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;ceph2&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;ceph&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;conf&lt;/span&gt;
&lt;span class="n"&gt;description&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Less&lt;/span&gt; &lt;span class="n"&gt;expensive&lt;/span&gt; &lt;span class="n"&gt;rbd&lt;/span&gt; &lt;span class="n"&gt;store&lt;/span&gt;
&lt;span class="c1"&gt;# etc..&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The example above is for Ceph, but it could apply to any storage backend. As
shown in the example above the ‘enabled_backends’ property is a comma delimited
list of store identifiers which are setup for glance. Each of the store
identifiers defines a property group name which itself contains the store
specific properties used to configure the store instance and a store type
which will be used to register configuration options related to that store
under the new configuration section defined using store identifiers. Under
the covers the store identifier (aka id) maps to the store class used for
the instance.&lt;/p&gt;
&lt;p&gt;While ‘stores’ and ‘default_store’ are available an operator can leave the
‘enabled_backends’ property unset in which case multi-store support is not
“enabled” and glance will work as-is. Once these config options are removed
operator at least need to set one store in the ‘enabled_backends’ or else
glance-api service will fail to start.&lt;/p&gt;
&lt;p&gt;In order to accommodate multiple stores of the same scheme, the scheme_map
used to index stores must also index by store identifier per scheme. The
store identifier is (implicitly) the name of the conf group given in
the glance-api.conf (e.g. reliable, fast and cheap from the example
conf given above).&lt;/p&gt;
&lt;p&gt;Consider the following indexing approach:&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;scheme_map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;scheme&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;store_id&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Where ‘scheme’ is the scheme(s) supported by the store implementation and
‘store_id’ is the identifier for the store.&lt;/p&gt;
&lt;p&gt;To maintain backward compatibility with old store API’s while they are not
deprecated we also propose to add new store api’s like add, get, delete
etc. to glance_store. The old store api’s will be removed when the
deprecation period for ‘stores’ and ‘default_store’ config option is over.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;API to list stores&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;To accommodate the management and discovery of known glance stores, glance
should also provide a REST API which permits users to list all stores
configured for glance. This is a read-only list of glance stores
which includes the store identifier, description for each store and a flag
which will tell whether a store is default or not.&lt;/p&gt;
&lt;p&gt;NOTE: The list of glance stores is based on the glance-api.conf with respect to
store configuration. Operators will not be able to configure new stores using
the API. So in order to show the description in the response as mentioned
earlier we propose to add new config option ‘description’ to each store
with some default description and operator can set it as per their need.&lt;/p&gt;
&lt;p&gt;As discussed herein, the store identifier can be used to address a particular
instance of a store for applicable operations such as image upload and
image import.&lt;/p&gt;
&lt;p&gt;We propose the new REST resource be located at the following URI:&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;v2&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;stores&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;More details on this API can be found in the REST API section of this spec.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Image upload API&lt;/strong&gt;
The existing image upload API permits an operator to upload image bits to
the glance service. However today this API does not provide a means for
the operator to target a specific store to back the image bits on
(technically the v1 API allows you to specify a store scheme to target).
This spec proposes the API be enhanced to permit an operator to specify
which store will back the image bits being uploaded.&lt;/p&gt;
&lt;p&gt;We propose a header field be used as a means to transport
the identifier of the store to back the image bits. Again the identifier
under the covers is the property group name of the respective glance
store driver. When the image upload API is used to upload image bits, the
glance logic will determine if the target store is specified, and if so
the image bits will be added to the target store.&lt;/p&gt;
&lt;p&gt;If no store is targeted in the upload request, the ‘default_backend’
is used to back the image bits.&lt;/p&gt;
&lt;p&gt;Using this scheme operators will be able to specify which store they want
an image bits to be backed on during an upload operation. We propose the
‘X-Image-Meta-Store’ header be used as the means to transport a target
store identifier.&lt;/p&gt;
&lt;p&gt;More details on this API can be found in the REST API section of this spec.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Image download&lt;/strong&gt;
If cloud get upgraded to use multi-store support from the single store
then glance need to deal with the locations from old stores to new
stores. For example, if operator is using rbd (say ceph) backend
and now he has upgraded the environment and introduced two additional
rbd stores as ceph1 and ceph2 with default store as ‘ceph1’ then
somehow glance must be able to download the images from old stores
(ceph).&lt;/p&gt;
&lt;p&gt;With multiple backends available, Glance needs some enhancements
so it can fulfill the current image download API contract. The
download request will traverse through all the configured backends
to look for the image. As we are adding store information in location
metadata, at first it will look the image in the store which is set
in the location metadata. If location metadata is not set then
as per example from the config section above, if the location
is rbd://&amp;lt;something&amp;gt;, then it will search the image in all available
ceph stores i.e. ‘fast’ and ‘cheap’ in this case. This way user will be
able to download his image from the old store even after cloud is
upgraded to use multiple stores.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Image import API&lt;/strong&gt;
The existing image import API allows end users to import image from the
staging area into glance backend. However today this API does not provide
a means for the end user to target a specific store to import the image.
This spec proposes the API be enhanced to permit an end user to specify
which store will back the image being imported.&lt;/p&gt;
&lt;p&gt;We propose a header field be used as a means to transport the identifier
of the store to import the image. Again the identifier under the covers
is the property group name of the respective glance store driver. When
the image import API is used to import the image, the glance logic will
determine if the target store header is specified, and if so the image
will be imported to the target store.&lt;/p&gt;
&lt;p&gt;If no store is targeted in the import request, the ‘default_backend’ is
used to import the image.&lt;/p&gt;
&lt;p&gt;Using this scheme end users will be able to specify which store they want
an image to be imported during an import operation. We propose the
‘X-Image-Meta-Store’ header be used as the means to transport a target
store identifier.&lt;/p&gt;
&lt;p&gt;More details on this API can be found in the REST API section of this spec.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Store locations metadata attributes&lt;/strong&gt;
In the current glance API, a consumer of the glance API has no way to correlate
an image location with its respective store other than by inspecting the
image’s location URL. While this may work fine for many use cases, a more
user friendly relation is needed in a multi-store environment; user’s need
an explicit relation between an image location and its respective store
(e.g. what store is this location backed on).&lt;/p&gt;
&lt;p&gt;This spec proposes that when image bits are added with the image upload API,
the core glance logic is responsible for adding a metadata attribute to the
image location URL to reflect the backing store’s identifier. For example,
if a user uploads an image to the ‘ceph1’ store in our example above,
once the image bits are uploaded, the image location URL is added and in the
URL’s metadata a property with the store’s identifier is added to the location
metadata object.&lt;/p&gt;
&lt;p&gt;With the store identifier in the image location URL metadata, we can expose it
to the end user with a new attribute as ‘store’ in the image response so that
it can be used for subsequent operations or within the API consumers logic.&lt;/p&gt;
&lt;p&gt;The new image response with store attribute will 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="s2"&gt;"size"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1234&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="s2"&gt;"store"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"reliable"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="s2"&gt;"checksum"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1234567890&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;"Import image"&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="n"&gt;active&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;Two major alternatives come to mind with respect to a multi-store approach in
glance; multi-store using a service per store and per driver multi-store
support.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Per store service&lt;/strong&gt;
In the service per store approach, each of the configured store instances would
run as a separate process/service. As a result each service would have its
own AMQP/RPC interface, own PID, etc.. To route requests to store services,
we’d use a scheduler which itself is another process / service. This is the
same approach used in cinder multi-backend support.&lt;/p&gt;
&lt;p&gt;Although the service per store approach may be a longer term goal for glance,
today we haven’t seen enough justification from our consumer base to justify
the major refactoring/changes which are required to move glance to this
model.&lt;/p&gt;
&lt;p&gt;Therefore this spec proposes the multi-store approach outlined within this
spec - let’s get an initial approximation multi-store working and gage
our next steps based on consumer feedback in the community.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Per driver support&lt;/strong&gt;
Another potential approach would be to push the multi-store logic down within
each glance store driver’s implementation. For example the store driver
itself could contain logic to multiplex with multiple backends.&lt;/p&gt;
&lt;p&gt;While this approach would work, it would require each store driver’s
implementation to change and would result in suboptimal reuse of code.&lt;/p&gt;
&lt;p&gt;This spec proposes a multi-store approach which has little or no impact
to each store driver; they can be used as-is in a multi-store implementation.
By pushing the logic to support multiple stores of the same scheme up into
the core of glance, we get maximal reuse and store driver implementations
needn’t be concerned with such logic.&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;This spec does not propose any changes to the data model. Rather the approach
herein can maintain all new stateful data either in memory or within the
existing schema used by glance. However store identifier will be stored as
a metadata in the location object.&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 spec proposes the following API changes:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;New API&lt;/strong&gt;&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;List all stores known to the glance service.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Modified APIs&lt;/strong&gt;&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Import an image.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Upload an image file.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Get image details.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Common Response Codes&lt;/strong&gt;&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Create Success: &lt;cite&gt;201 Created&lt;/cite&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Modify Success: &lt;cite&gt;200 OK&lt;/cite&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Delete Success: &lt;cite&gt;204 No Content&lt;/cite&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Failure: &lt;cite&gt;400 Bad Request&lt;/cite&gt; with details.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Forbidden: &lt;cite&gt;403 Forbidden&lt;/cite&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;API Version&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;All URLS will be under the v2 Glance API.  If it is not explicitly specified
assume /v2/&amp;lt;url&amp;gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;[New API] List stores&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;List all stores known to the glance service:&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&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;v2&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;stores&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;This API takes no query parameters and when authorized returns a listing of all
stores known to the glance service. The stores known to glance are those which
have been configured in the glance-api.conf and have been loaded during glance
startup. The response body payload is JSON and contains a JSON object per
store. Each store JSON object contains the store’s identifier (id),
description and if a particular store is a default store the it will
have a flag telling store is default. 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="p"&gt;{&lt;/span&gt;
   &lt;span class="s2"&gt;"stores"&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;"reliable"&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;"Reliable filesystem store"&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;"fast"&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;"Fast access to rbd store"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
         &lt;span class="s2"&gt;"default"&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="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;"cheap"&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;"Less expensive rbd store"&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;Response codes:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;200 – Upon authorization and successful request. The response body
contains the JSON payload with the known stores.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;[Modified API] Create image&lt;/strong&gt;
We propose to add an ‘OpenStack-image-store-ids’ header to the image-create
response which would have the available stores. Using this user can decide
which store he needs to upload/import his image and wouldn’t have to make
a separate get-stores call.&lt;/p&gt;
&lt;section id="new-response-headers"&gt;
&lt;h4&gt;New response headers&lt;/h4&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;OpenStack-image-store-ids&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;The value of this header will be a comma-separated list of stores
available.  For example,&lt;/p&gt;
&lt;p&gt;OpenStack-image-store-ids: fast, cheap, reliable&lt;/p&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;[Modified API] Upload image binary data&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Get image binary data:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;PUT /v2/images/​{image_id}​/file
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;This modifies the existing REST API to support a new header field which is
optional and if present specifies the store id to upload the image data to.
For backwards compatibility, if the header is not specified the store
specified as the default (e.g. default_store) is used to upload the image
to.&lt;/p&gt;
&lt;p&gt;New header fields:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;X-Image-Meta-Store – If present contains the store id to upload the image
binary data to.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;New / changed response codes:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;400 – If the X-Image-Meta-Store header is present, but specifies a
store id for a store that doesn’t exist by that id.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Example curl usage:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;curl -i -X PUT -H "X-Auth-Token: $token" -H "X-Image-Meta-Store:
    ceph1" -H "Content-Type: application/octet-stream"
    -d @/home/glance/ubuntu-12.10.qcow2
    $image_url/v2/images/{image_id}/file
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;[Modified API] Get image details&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Get the details for a specified image:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;GET /v2/images/​{image_id}​
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Although this spec does not impose any changes on the glance API layer, this
call will now shows the location’s store id. In case if there are multiple
locations, then all locations will be displayed as comma separated list. The
new image response with store attribute will 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="s2"&gt;"size"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1234&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="s2"&gt;"store"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"reliable"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="s2"&gt;"checksum"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1234567890&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;"Import image"&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="n"&gt;active&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;[Modified API] Import image to the backend&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Import image to the backend:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;POST /v2/images/​{image_id}​/import
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;This modifies the existing REST API to support a new header field which is
optional and if present specifies the store id to import the image data to.
For backwards compatibility, if the header is not specified the store
specified as the default (e.g. default_store) is used to import the image
to.&lt;/p&gt;
&lt;p&gt;New header fields:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;X-Image-Meta-Store – If present contains the store id to upload the image
binary data to.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;New / changed response codes:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;400 – If the X-Image-Meta-Store header is present, but specifies a
store id for a store that doesn’t exist by that id.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Example curl usage:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;curl -i -X PUT -H "X-Auth-Token: $token" -H "X-Image-Meta-Store:
    ceph1" -H "Content-Type: application/json"
    -d '{"method":{"name":"glance-direct"}}'
    $image_url/v2/images/{image_id}/import
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&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;Need to add ‘stores’ field in the notification response as one of the use
case of this proposal is offering different price tiers for storage which
will help systems which consumes notifications to perform the billing.&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 introduces a few other user impacts worth noting.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Glance client&lt;/strong&gt;
Ideally the glance client (CLI + REST client) should be updated in accordance
with this spec. Notably:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;CLI / API support for listing glance stores.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;CLI / API support for specifying a store id on upload/import.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Configuration&lt;/strong&gt;
Deployers will need to be aware of the configuration aspects for glance
multi-store. From a conf point of view, configuring multi-store for glance
will look very much (from a high level) like configuring cinder for
multi-backend. The conf file specifics will need to be documented.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;A very little hit on the performance of downloading the image from the old
stores. For example, if existing user is using single rbd (say ceph)
backend and now he has upgraded the environment and introduced two
additional rbd stores as ceph1 and ceph2 with default store as ‘ceph1’
then if image which needs to be download from old store (ceph) will
take some time as it needs to be looked in all the enabled backends.&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;Once merged, glance multi-store is not enabled unless the deployer
configures the enabled_backends property in glance-api.conf and thus is backwards
compatible out-of-the-box. When multi-store is disabled, v2 API users can
use the list stores API and will retrieve a list of the current
stores configured (of course only 1 store per scheme).&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;abhishek-kekane&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;p&gt;Implementation tasks may consist of:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Conf support for multi-store.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Multi-store loading and indexing.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;List stores API.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Location URL metadata store id on upload.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add new ‘store’ attribute in image response.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Image upload with store targeting.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Image import with store targeting.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Multi-store delete and other store access codepaths.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add python-glanceclient support&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 new tempest tests to verify multi-store support&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;As mentioned in the ‘work items’ section, we’ll need to ensure the glance docs
are update for:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;The new list stores REST API.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;New header field for image upload.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;New header field for image import.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;New store id in image response.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Overall glance multi-store documentation to educate deployers on the
feature and how it’s used.&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/150967"&gt;https://review.openstack.org/#/c/150967&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
</description><pubDate>Tue, 07 Aug 2018 00:00:00 </pubDate></item><item><title>Secure Hash Algorithm Support</title><link>http://specs.openstack.org/openstack/glance-specs/specs/rocky/implemented/glance/multihash.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/glance/+spec/multihash"&gt;https://blueprints.launchpad.net/glance/+spec/multihash&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This spec provides a future-proof mechanism for providing a
secure SHA512 hash for each image.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;The hash of an image can be obtained from the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;checksum&lt;/span&gt;&lt;/code&gt; field in the
image metadata. Currently, this checksum field holds a md5 hexdigest
value. While md5 can still be used to verify data integrity against
unintentional corruption, it should not be used to verify data integrity
against tampering. A more collision-resistant hashing algorithm should
be used for broader data integrity coverage.&lt;/p&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 two new fields to the image metadata. The
proposed keys for this change would be &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_hash_algo&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_hash_value&lt;/span&gt;&lt;/code&gt;.
The proposed value is a hash value that is formatted as a sha512 hexdigest.
The hexdigest will be obtained using the current python hashlib library.
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_hash_algo&lt;/span&gt;&lt;/code&gt; will be sha3_512 and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_hash_value&lt;/span&gt;&lt;/code&gt; will be the hex. At this
point in time, the config will default to sha3_512, but this change
will allow us to alter allowed hashing algorithms at any time. The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_hash_algo&lt;/span&gt;&lt;/code&gt;
field will also allow for users to dynamically pass this value to their python code.
We will leave MD5 calculations and checksums for backwards compatibility.&lt;/p&gt;
&lt;p&gt;Adding a new image will set all of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;checksum&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_hash_algo&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_hash_value&lt;/span&gt;&lt;/code&gt;
fields.&lt;/p&gt;
&lt;p&gt;Requesting the image metadata of an image without the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_hash_algo/os_hash_value&lt;/span&gt;&lt;/code&gt;
value set, will result in a null for the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_hash_algo/os_hash_value&lt;/span&gt;&lt;/code&gt; field in the
metadata response.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;&lt;p&gt;Update the value of the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;checksum&lt;/span&gt;&lt;/code&gt; field with the hexdigest of a
different hashing algorithm. This will likely break client-side
checksum verification code.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add only the new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_hash_value&lt;/span&gt;&lt;/code&gt; field. While it is a simpler change, it
is a less future proof approach because it ties the sha512 algorithm to the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_hash_value&lt;/span&gt;&lt;/code&gt; property in the same way that the md5 algorithm is tied to the
current &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;checksum&lt;/span&gt;&lt;/code&gt; property. When a sha512 collision is produced, there will
have to be a new spec in to add yet another checksum field.&lt;/p&gt;
&lt;p&gt;The approach described in this spec of using an additional &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_hash_algo&lt;/span&gt;&lt;/code&gt; field
will allow changing the hash algorithm without adding a new field or breaking
the API contract. All we’ll have to do is update the algorithm used and put
its name in the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_hash_algo&lt;/span&gt;&lt;/code&gt; property, and then any image consumer will know
how to interpret what’s in the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_hash_value&lt;/span&gt;&lt;/code&gt; property.&lt;/p&gt;
&lt;p&gt;It is worth noting that the Glance implementation of image signature validation
gives us a precedent for having a value in one property (&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;img_signature&lt;/span&gt;&lt;/code&gt;) and
the name of the algorithm used in another property
(&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;img_signature_hash_method&lt;/span&gt;&lt;/code&gt;) &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;. Thus the proposal in this spec is
completely consistent with a related Glance workflow.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use the hexdigest of a different algorithm. Tests using hashlib’s
sha256 and sha512 algorithms consistently yielded faster times for
sha512 (SEE: Performance impact). The implementation of the sha512
algorithm within hashlib demonstrates reasonable performance and
should be considered collision-resistant for many years.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Implement a single &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;multihash&lt;/span&gt;&lt;/code&gt; field in the image metadata in which we calculate
the SHA512 value. The single field will contain the coded algorithm name and hash &lt;a class="footnote-reference brackets" href="#id3" id="id2" 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;.
The advantage is that it is only one field being added to the data model and schema.
However, having only one field would make it difficult to use the hash quickly as
the end user would be required to decode what algorithm is being used before verifying
the hash.&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;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Triggers: None&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Expand: Two new columns (&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_hash_algo&lt;/span&gt;&lt;/code&gt; &amp;amp; &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_hash_value&lt;/span&gt;&lt;/code&gt;) with type string/varchar
(defaulting to null) will be added to the images table. We will create an
index similar to the one on &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;checksum&lt;/span&gt;&lt;/code&gt; as well.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Migrate: None&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Contract: None&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Conflicts: None&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;Two new fields (&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_hash_algo&lt;/span&gt;&lt;/code&gt; &amp;amp; &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_hash_value&lt;/span&gt;&lt;/code&gt;) will exist in requests for the image
metadata.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;A new more collision-resistant hash will be returned in addition to the
current checksum.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notification-impact"&gt;
&lt;h3&gt;Notification 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;New image uploads (and the first download of previously uploaded images)
will take an additional amount of time to calculate the sha512 checksum:&lt;/p&gt;
&lt;p&gt;5G binary blob of random data:
* md5: ~9s
* sha256: ~22s
* sha512: ~14s
* 1Gbps line speed upload: 42s&lt;/p&gt;
&lt;p&gt;1.5G Ubuntu 16.04 cloud image:
* md5: ~2.9s
* sha256: ~7.2s
* sha512: ~4.6s
* 1Gbps line speed upload: 12s&lt;/p&gt;
&lt;p&gt;555M Debian 8 cloud image:
* md5: ~1.0
* sha256: ~2.5
* sha512: ~1.6
* 1Gbps line speed upload: 4.5s&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Note: SHA512 has been selected and should have minimal impact on overall upload time
with regards to the entire process.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Test Code:&lt;/p&gt;
&lt;div class="highlight-python notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="ch"&gt;#!/usr/bin/env python3&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;hashlib&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;time&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;runtime&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="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;wrapper&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;start&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;time&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="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Time elapsed: &lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s2"&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;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;start&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;wrapper&lt;/span&gt;


&lt;span class="nd"&gt;@runtime&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;checksum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;algorithm&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;algorithms&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"md5"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;hashlib&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;md5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                  &lt;span class="s2"&gt;"256"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;hashlib&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sha256&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                  &lt;span class="s2"&gt;"512"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;hashlib&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sha512&lt;/span&gt;&lt;span class="p"&gt;,&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;filename&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"rb"&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;f&lt;/span&gt;&lt;span class="p"&gt;:&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;algorithms&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;algorithm&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;chunk&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;iter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;65536&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;):&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;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s2"&gt;: &lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s2"&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;algorithm&lt;/span&gt;&lt;span class="p"&gt;,&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;hexdigest&lt;/span&gt;&lt;span class="p"&gt;()))&lt;/span&gt;

&lt;span class="n"&gt;checksum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"fake.img"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"512"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;checksum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"fake.img"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"256"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;checksum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"fake.img"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"md5"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;checksum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"fake.img"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"256"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;checksum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"fake.img"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"md5"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;checksum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"fake.img"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"512"&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;Any future checksum verification code should use the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_hash_algo&lt;/span&gt;&lt;/code&gt; &amp;amp; &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_hash_value&lt;/span&gt;&lt;/code&gt; fields.
Fallback to the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;checksum&lt;/span&gt;&lt;/code&gt; field if not properly populated.&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: Scott McClymont&lt;/p&gt;
&lt;p&gt;Other contributors:&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 tests&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update the db to add &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_hash_algo&lt;/span&gt;&lt;/code&gt; &amp;amp; &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_hash_value&lt;/span&gt;&lt;/code&gt; columns to the images table (including
expand, migrate, contract, and monolith code)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update the sections of code that calculate the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;checksum&lt;/span&gt;&lt;/code&gt; to also
calculate &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_hash_algo&lt;/span&gt;&lt;/code&gt; &amp;amp; &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_hash_value&lt;/span&gt;&lt;/code&gt; (includes calculation on upload)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Discuss updating on download &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_hash_algo&lt;/span&gt;&lt;/code&gt; &amp;amp; &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_hash_value&lt;/span&gt;&lt;/code&gt; when value is null&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update internal checksum verification code to use the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os_hash_value&lt;/span&gt;&lt;/code&gt;
field and fallback to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;checksum&lt;/span&gt;&lt;/code&gt; field when not present&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update glance client&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update docs&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add the os_hash_algo value to the discovery API if the API is 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;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Update the tests to verify proper population of image properties&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="#id2"&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="http://multiformats.io/multihash/"&gt;http://multiformats.io/multihash/&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="#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/latest/user/signature.html"&gt;https://docs.openstack.org/glance/latest/user/signature.html&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;/aside&gt;
&lt;/section&gt;
</description><pubDate>Tue, 07 Aug 2018 00:00:00 </pubDate></item><item><title>Spec Lite: Remove the Images API v1</title><link>http://specs.openstack.org/openstack/glance-specs/specs/rocky/implemented/glance/remove-v1.html</link><description>

&lt;dl class="field-list simple"&gt;
&lt;dt class="field-odd"&gt;problem&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;The Images API verison 1 was DEPRECATED in the Newton release:
&lt;a class="reference external" href="https://docs.openstack.org/releasenotes/glance/newton.html"&gt;https://docs.openstack.org/releasenotes/glance/newton.html&lt;/a&gt;
It needs to be removed from the codebase.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;dependencies&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;copy_from&lt;/span&gt;&lt;/code&gt; import-method must be implemented and the
Images API version 2.6 must be CURRENT.  (That’s because the
key requested feature missing from Images v2 is a copy-from
functionality.)&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;solution&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;This will require some preliminary work before the code is removed,
for example, removing any Tempest tests that use the v1 API.  These
will be noted as “Work Items” on the Blueprint.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;how&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;Remove all v1 tests, remove v1 endpoints from Images API, remove
&lt;cite&gt;glance-cache-manage&lt;/cite&gt; command that is still relying fully on v1 API.
Gradually clean out the v1 code base that’s left behind.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;impacts&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;DocImpact (All v1 docs will have to be removed)&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;timeline&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;target for the Q-3 milestone (week of 22 January 2017)&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;link&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/glance/+spec/remove-v1"&gt;https://blueprints.launchpad.net/glance/+spec/remove-v1&lt;/a&gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;reviewers&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;all core reviewers&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;assignee&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;jokke&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
</description><pubDate>Tue, 07 Aug 2018 00:00:00 </pubDate></item><item><title>Spec Lite: Deprecate store_capabilities_update_min_interval</title><link>http://specs.openstack.org/openstack/glance-specs/specs/rocky/implemented/glance_store/deprecate-store_capabilities_update_min_interval.html</link><description>

&lt;dl class="field-list"&gt;
&lt;dt class="field-odd"&gt;project&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;glance_store&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;problem&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;The configuration option &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;store_capabilities_update_min_interval&lt;/span&gt;&lt;/code&gt;
is confusing because no existing stores implement the
StoreCapability.update_capabilities() method.  This has come up in
the context of nfs being used for the filesystem backend.  If nfs
is not ready for writing when the glance api starts, glance will
mark the filesystem as not writeable.  Operators have tried to get
around this problem by setting a non-zero positive value for this
option only to find that it doesn’t work.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;solution&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;Use oslo.config to mark the option as ‘deprecated’ with an
appropriate note.  Option will be deprecated in Rocky for removal
in ‘S’.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;alternatives&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;An alternative would be to rewrite the option help text to make
it clear that there is no current store for which the option is
actionable, but that a framework is in place through which
dynamic capability determination could be implemented.
Currently a debug level message to this effect is logged on
store startup although it is not obvious that the message is
related to the ineffectiveness of setting the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;store_capabilities_update_min_interval&lt;/span&gt;&lt;/code&gt; option.  The message
is: “Store %s doesn’t support updating dynamic storage
capabilities. Please overwrite ‘update_capabilities’ method of
the store to implement updating logics if needed.”  (This
message is logged independently of setting the option.)&lt;/p&gt;
&lt;p&gt;The advantage to this approach is that the framework would be
available to someone who wanted to implement dynamic updates
for a store, and the option would not have to be re-introduced.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;impacts&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;None&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;timeline&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;Rocky milestone 2&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;assignee&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;rosmaita&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
</description><pubDate>Tue, 07 Aug 2018 00:00:00 </pubDate></item><item><title>Support revert pending delete image</title><link>http://specs.openstack.org/openstack/glance-specs/specs/rocky/implemented/glance/Support-revert-pending-delete.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/glance/+spec/pending-delete-rollback"&gt;https://blueprints.launchpad.net/glance/+spec/pending-delete-rollback&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Glance support soft delete images. If this feature is enabled, when users
delete an image, the image and its locations will first be in a special
&lt;cite&gt;pending_delete&lt;/cite&gt; status that is not displayed in the API response. Then the
image will be deleted by &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance-scrubber&lt;/span&gt;&lt;/code&gt; process in period. But now, there
is no way to revert/rollback the &lt;cite&gt;pending_delete&lt;/cite&gt; images to &lt;cite&gt;active&lt;/cite&gt;.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Delayed_delete feature is usually used when the image is too large to delete at
once. With this feature, then the image data will not be deleted at once and
will be cleaned by &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance-scrubber&lt;/span&gt;&lt;/code&gt; process. The problem is that there is no
way to revert the delete action if the image is deleted by mistake. The only
way admin operator can do is to wait until the image data is deleted and then
reupload image data again.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;This proposal aims to recover an image which is in &lt;cite&gt;pending_delete&lt;/cite&gt; state so
as to provide the revert capability for the purposes of allowing emergency
operational action to recover an accidental delete. It is important to keep in
mind, however, that whether the recovery of a particular image will be possible
or not depends upon Glance configuration option settings and quick operator
action.&lt;/p&gt;
&lt;p&gt;Since the &lt;cite&gt;pending_delete&lt;/cite&gt; image will be only deleted by &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance-scrubber&lt;/span&gt;&lt;/code&gt;
and it’s an admin action, there is no need to expose a new API. A better way is
to enhance &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance-scrubber&lt;/span&gt;&lt;/code&gt; to support restoring the image from
&lt;cite&gt;pending_delete&lt;/cite&gt; status to &lt;cite&gt;active&lt;/cite&gt;.&lt;/p&gt;
&lt;p&gt;A new parameter called &lt;cite&gt;–restore&lt;/cite&gt; will be added to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance-scrubber&lt;/span&gt;&lt;/code&gt;
command. The usage is like: &lt;cite&gt;glance-scrubber –restore &amp;lt;image_id&amp;gt;&lt;/cite&gt;.
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance-scrubber&lt;/span&gt;&lt;/code&gt; first checks to see if the scrubber process is running, if
so, an error message that there is a scrubber currently running and you must
kill it first &amp;amp; scrubber terminates will be raised to admin. If not, scrubber
will switch image status from &lt;cite&gt;pending_delete&lt;/cite&gt; to &lt;cite&gt;active&lt;/cite&gt;.&lt;/p&gt;
&lt;p&gt;Please be sure that the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance-scrubber&lt;/span&gt;&lt;/code&gt; daemon is killed before restore
the &lt;cite&gt;pending_delete&lt;/cite&gt; image to avoid image data inconsistency. After restoring
the image, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance-scrubber&lt;/span&gt;&lt;/code&gt; daemon can be restarted.&lt;/p&gt;
&lt;section id="limitations"&gt;
&lt;h3&gt;Limitations&lt;/h3&gt;
&lt;p&gt;This is intended as an emergency operation for the use case where an operator
inadvertently deletes an important image and immediately realizes the mistake
and takes action within the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;scrub_time&lt;/span&gt;&lt;/code&gt; seconds set in the glance-api.conf
file.  The &lt;cite&gt;pending-delete&lt;/cite&gt; status is a purely internal Glance status and the
image still shows as being in &lt;cite&gt;deleted&lt;/cite&gt; status in API responses.  Thus there is
no way to tell via the API whether an image may be restorable or not.&lt;/p&gt;
&lt;p&gt;Further, when the image is restored, some of its metadata is irrecoverable. Any
additional properties, tags, or members will not be restored.  In other words,
this is purely a possible data recovery operation, not a full image restore.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;The alternative way which is not recommend is to create a new API to revert the
&lt;cite&gt;pending_delete&lt;/cite&gt; 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;POST&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;v2&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;images&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;images_id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;actions&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;revert&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The response body could 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="n"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt; &lt;span class="n"&gt;OK&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="s2"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"cirros-0.3.1-x86_64-uec"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"tags"&lt;/span&gt;&lt;span class="p"&gt;:[&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="s2"&gt;"kernel_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"be50418b-a03c-4947-9122-b80a57f47ac4"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"container_format"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"ami"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"created_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"2017-09-11T08:42:14Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"ramdisk_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"e1256074-9f7b-4067-8356-4a5759c1db11"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"disk_format"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"ami"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"updated_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"2017-09-11T08:42:16Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"visibility"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"public"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"self"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"/v2/images/26c16e07-24ca-4abc-a523-bec068012363"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"protected"&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;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"26c16e07-24ca-4abc-a523-bec068012363"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"file"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"/v2/images/26c16e07-24ca-4abc-a523-bec068012363/file"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"checksum"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"f8a2eeee2dc65b3d9b6e63678955bd83"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"min_disk"&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;"size"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;25165824&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"min_ram"&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;"schema"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"/v2/schemas/image"&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="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;Allow image status changing from &lt;cite&gt;pending_delete&lt;/cite&gt; to &lt;cite&gt;active&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;This is an administrator action. No security impact at all.&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;There is no impact for non-admin users. For administrators, they’ll have the
ability to rollback the image’s status from &lt;cite&gt;pending_delete&lt;/cite&gt; to &lt;cite&gt;active&lt;/cite&gt; by
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance-scrubber&lt;/span&gt;&lt;/code&gt; tool.&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;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;p&gt;wangxiyuan(&lt;a class="reference external" href="mailto:wangxiyuan%40huawei.com"&gt;wangxiyuan&lt;span&gt;@&lt;/span&gt;huawei&lt;span&gt;.&lt;/span&gt;com&lt;/a&gt;)&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;change &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance-scrubber&lt;/span&gt;&lt;/code&gt; to include the &lt;cite&gt;–restore &amp;lt;image_id&amp;gt;&lt;/cite&gt; option.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;change the image status transition to allow:  &lt;cite&gt;pending_delete&lt;/cite&gt; -&amp;gt;  &lt;cite&gt;active&lt;/cite&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update the related documentation and test.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Release note should 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;p&gt;Related unit test should be added.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Related doc should 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;
</description><pubDate>Wed, 20 Jun 2018 00:00:00 </pubDate></item><item><title>Spec Lite: Deprecate owner_is_tenant</title><link>http://specs.openstack.org/openstack/glance-specs/specs/rocky/implemented/glance/spec-lite-deprecate-owner_is_tenant.html</link><description>

&lt;dl class="field-list"&gt;
&lt;dt class="field-odd"&gt;project&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;glance&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;problem&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;owner_is_tenant&lt;/span&gt;&lt;/code&gt; option, which is True by default, allows an
operator to run Glance in a nonstandard configuration where the
image owner is the &lt;em&gt;user&lt;/em&gt; who created the image.  In all other
OpenStack services, resources are owned by the &lt;em&gt;project&lt;/em&gt; (as
they are in Glance when the default setting is used).&lt;/p&gt;
&lt;p&gt;A survey of operators conducted in March 2017 indicated that
no operators who responded (14) are using this option.  As it
is little used, results in a nonstandard OpenStack experience,
and complicates the Glance code, the option should be deprecated
in Rocky.  Following the standard &lt;a class="reference external" href="https://governance.openstack.org/tc/reference/tags/assert_follows-standard-deprecation.html"&gt;OpenStack deprecation policy&lt;/a&gt;,
it should be removed early in the ‘S’ cycle.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;solution&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;Use the oslo.config facilities to mark the option as deprecated.
As it appears that this option is used only in its default setting
of True, no migration path is proposed.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;impacts&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;None&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;timeline&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;R-1&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;assignee&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;rosmaita&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
</description><pubDate>Wed, 20 Jun 2018 00:00:00 </pubDate></item><item><title>Spec Lite: Glance cluster awareness</title><link>http://specs.openstack.org/openstack/glance-specs/specs/rocky/approved/glance/spec-lite-cluster-awareness.html</link><description>

&lt;dl class="field-list simple"&gt;
&lt;dt class="field-odd"&gt;project&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;glance&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;problem&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;Individual glance nodes are fully un-aware that there might be
other nodes operating in the same space. This lack of communication
between the nodes causes issues separating workers and operating in
different locations.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;solution&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;We have message queues already utilized in notifications and other
projects. Lets expand that for communications between different
glance-api nodes to gain better operational efficiency.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;impacts&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;DocImpact&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;dl class="field-list simple"&gt;
&lt;dt class="field-odd"&gt;alternatives&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;We could use something else than the message queues but
effectively that would end up recreating something like registry
but just as a message broker.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;timeline&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;Possible initial functionality in Rocky, more use cases covered S
and beyond. This can be expanded fairly easily so we can proceed as
time permits.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;assignee&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;jokke&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
</description><pubDate>Wed, 06 Jun 2018 00:00:00 </pubDate></item><item><title>Semver Utility for DB storage</title><link>http://specs.openstack.org/openstack/glance-specs/specs/kilo/semver-support.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/glance/+spec/semver-support"&gt;https://blueprints.launchpad.net/glance/+spec/semver-support&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Working with versions of various objects is a common problem, which already has
a number of market-adopted solutions. One of these solutions is Semantic
Versioning - a system of rules and requirements for assigning version numbers
to software components and other objects. One can find the specification for
SemVer freely at &lt;cite&gt;semver.org &amp;lt;http://semver.org&amp;gt;&lt;/cite&gt;&lt;/p&gt;
&lt;p&gt;It is proposed to add support of the semantic versioning concept into Glance,
according to the version 2.0.0 of the specification [1], so Glance objects
(starting from Artifacts, but probably including Images in future) may be
properly versioned.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Semantic versioning provides the ability to compare two or more objects based
on the version with which they are associated. According to the specification
[1] objects are compared first by their major versions, then minor versions,
then patch versions, also there is a concept of “pre-release” versions (alphas,
betas, release candidates (RC) etc) which should always be considered “lower”
then the “released” version with the same values of numeric versions.&lt;/p&gt;
&lt;p&gt;For example, 1.2.2 &amp;lt; 1.2.3-beta &amp;lt; 1.2.3&lt;/p&gt;
&lt;p&gt;If we want to store versioned objects in the catalog (this may be applied to
images, artifacts and other entities), then we need to be able to execute this
kind of semantic comparison for large amounts of entities.&lt;/p&gt;
&lt;p&gt;So, the comparison should be made not only in memory, but at the database as
well, and there is no generic datatype in modern RDBMs to store this kind of
versioning information. So, a method for storing easily-sortable version
identifiers should be introduced.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;First of all, Glance has to adopt some utility to parse strings which contain
version information, verify their compliance with the specification and
properly process the version objects in memory. There is a number of mature
libraries which have this functionality and there is no need to re-implement
them.
After some research it has been suggested to use “semantic_version” library
which is available at pypi [2]. This library is not present in OpenStack global
requirements, so a patchset [3] has been submitted to add it there.&lt;/p&gt;
&lt;p&gt;To be able to sort these version objects in the database it is required to
convert them into some generic comparable data type. Due to the nature of
version information (fixed numeric components for major-minor-patch part) and
arbitrary sequences of alphanumeric strings for pre-release and metadata labels
it is suggested to store them separately as three database fields: one for the
numeric part, another for the pre-release label and the last one for build
metadata.&lt;/p&gt;
&lt;p&gt;Three numeric components (major, minor and patch) may be converted into a
single unsigned 64-bit integer number: first 16 bits of this number
will be allocated to store major revision, next 16 bits - for minor revision,
next 16 bits - for patch revision. Remaining 16 bits will be used to store the
release type flag (to make sure that the final release had higher precedence
then pre-releases) and may be reserved for future improvement and storing
additional information which is irrelevant for semantic versioning but may have
some other meanings (see Alternatives section below for more details).&lt;/p&gt;
&lt;p&gt;The labels of pre-release version should be stored independently from the
numeric part as a regular string, because - according to the semver spec - they
are to be compared according to regular alphanumeric comparison only if the
numeric parts of the versions are identical.&lt;/p&gt;
&lt;p&gt;So, these two values - long number and a string - may be combined into a single
composite index in the database, which will provide efficient capabilities to
sort and filter objects with the versions assigned.&lt;/p&gt;
&lt;p&gt;However, there is one important difference between the semver requirement and
simple comparison of alphanumeric strings: semver requires that the labels are
compared “per component” (where “component” is a dot-separated part of the
label), and the components which consists only of digits are to be treated as
integers rather then ASCII strings. For example, version “1.0.0-alpha.4.foo”
should have lower precedence then “1.0.0-alpha.10.bar”, because their numeric
components are equal, and the labels have identical first component (‘alpha’)
but differs in the second (“4” vs “10”), and 4 is less then 10.
But the labels are compared as string database fields, the precedence will be
wrong as “alpha.4.foo” is lexically greater then “alpha.10.bar” (due to “4”
being greater then “1”).&lt;/p&gt;
&lt;p&gt;To solve this problem it is suggested to add one constraint to this semver
implementation: to limit the maximum length of numeric components in the pre-
release label to a reasonably low value (say, 6 characters) and add extra
leading zeros to these components when saving them to database.&lt;/p&gt;
&lt;p&gt;In this case the “alpha.4.foo” label from the example above will become
“alpha.000004.foo”, and “alpha.10.foo” - “alpha.000010.foo”. ASCII-based
comparison of these strings will give the results which are consistent with the
requirements of semver. Later, when these values are read from the database the
leading zeros may be removed so the labels look fine again.&lt;/p&gt;
&lt;p&gt;This applies only to the pre-release label part. Build metadata (the part which
is separated by the ‘+’ character) does not take part in the precedence
resolution, so it neither has to be part of the database index nor has to be
pre-processed in anyway.&lt;/p&gt;
&lt;p&gt;It is suggested to create custom composite field for SQLAlchemy which will
encapsulate the above described logic (converting from semantic version into 3
database-friendly values and back) and will be usable for building
version-aware model classes.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Semantic Versioning is not the only specification which defines the format for
version string.
There is another standard - PEP440 - which describes a scheme for identifying
versions of Python software distributions [4]. It shares some common features
with Semantic Versioning but has different and a bit more complicated notation.&lt;/p&gt;
&lt;p&gt;Besides slightly different syntax (it just concatenates pre-release segments to
the right of release number, while semver separates them with a dash), it puts
extra constraints on what the pre-release label may contain. In semver,
pre-release label may contain arbitrary alphanumeric characters, while in
PEP440 they may be only be ‘a’, ‘b’ or ‘rc’ followed by a number. This could
theoretically allow to store the pre-release component as part of the same
64-bit long database field which is used to store the release number (e.g.
the release type flag takes 2 bits, and remaining 14 bits are left for the
number of the pre-release build) - however this significantly decreases the
flexibility of the pre-release version field.&lt;/p&gt;
&lt;p&gt;Also, PEP440 adds more additional entities: it has a concept of development
builds (being one additional special segment which goes after the pre-release
segments), Epochs (which precedes the build number), local version (which is
actually similar to build metadata of semantic versioning but has different
purpose and also takes part in precedence resolution by following about the
same rules as arbitrary pre-release label of semantic versioning) etc. Also,
unlike semantic versioning PEP440 does not have any limits on the amount of
numeric components in the build number: so, it may be anything from simple “1”
to “1.2.3.4.5.6.7.8.9.10” and beyond. This, of course, gives more flexibility
and power, but may not be easily mapped to efficient database storage.&lt;/p&gt;
&lt;p&gt;Which is more important, PEP440 is a standard which is native to Python world,
but is not known outside, while the purpose of Glance Artifacts is to be as
generic as possible in terms of the nature of its objects. This means that the
users of the artifacts are not restricted to be Python developers only: they
may not be the developers at all. So, following easier and more generic
standard seems preferable.&lt;/p&gt;
&lt;p&gt;There is one more standard which stands between semver and pep440. It is
called “Linux Compatible Semantic Versioning 3.0.0”, is a fork of regular
semver (its 2.0 version) and is developed within OpenStack community [5]. It
tries to blend regular semver with versions of Linux Distribution packages and
uses some concepts of pep440 for it.&lt;/p&gt;
&lt;p&gt;This notation is easier to map to the database type, however it is still local
to relatively small community of developers (OpenStack developers in this
case), so more generic and widely adopted standard as semver seems more
preferable.&lt;/p&gt;
&lt;p&gt;However we are not limited to having only a single versioning notation. In
future we may add support for extra schemas, including some subset of pep440 or
Linux Compatible Semantic Versioning. This may be implemented as part of
further Artifact Repository roadmap or other activities. This particular spec
leaves this out of scope and focuses only on semver implementation.&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: this spec does not cover any actual database changes, it just describes
the utility which will allow to operate with semver objects and convert them to
data which may be usable for DB storage - and back.&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 proposed change does not affect existing code in any sense.&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 spec assumes that [3] is merged, i.e. the semantic_version library is
added to the global requirements.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;The usage of the lib should be documented for developers, so they may
efficiently use it in their code.&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;ativelkov&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="reviewers"&gt;
&lt;h3&gt;Reviewers&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Core reviewer(s):&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;jokke&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other reviewer(s):&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;ivasilevskaya
mfedosin
travis-tripp
icordasc&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;Initial implementation of the feature may be done in a single changeset.
However it seems preferable to add this support to semantic_version library [2]
and remove it from glance codebase aftwerwards.
If the maintainer of the library does not accept this functionality (or if we
decide to add support for more versioning notations later) then this code may
be transferred to some common OpenStack library, such as Oslo.&lt;/p&gt;
&lt;p&gt;After this feature is implemented we should continue the work to add support
for other versioning schemas, such as pep440, Linux Compatible Semantic
Versioning and others. These should be added as independent features covered by
separate specs.&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 unit test should be added demonstrating the data structure usage, comparison,
string parsing and conversion operation to DB type (long)&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Developers’ guide has to be updated to hint the developers on how to properly
use the library in their code.&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="http://semver.org"&gt;http://semver.org&lt;/a&gt;
[2] &lt;a class="reference external" href="https://pypi.org/project/semantic_version/"&gt;https://pypi.org/project/semantic_version/&lt;/a&gt;
[3] &lt;a class="reference external" href="https://review.openstack.org/#/c/151466/"&gt;https://review.openstack.org/#/c/151466/&lt;/a&gt;
[4] &lt;a class="reference external" href="https://www.python.org/dev/peps/pep-0440/"&gt;https://www.python.org/dev/peps/pep-0440/&lt;/a&gt;&lt;/p&gt;
&lt;/section&gt;
</description><pubDate>Sun, 13 May 2018 00:00:00 </pubDate></item><item><title>Taskflow Integration</title><link>http://specs.openstack.org/openstack/glance-specs/specs/kilo/taskflow-integration.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/glance/+spec/taskflow-integration"&gt;https://blueprints.launchpad.net/glance/+spec/taskflow-integration&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Add a new task executor using the taskflow library.&lt;/p&gt;
&lt;p&gt;“TaskFlow is a Python library for OpenStack (and other projects) that helps make
task execution easy, consistent, scalable and reliable. It allows the creation
of lightweight task objects and/or functions that are combined together into
flows (aka: workflows) in a declarative manner.”: &lt;a class="reference external" href="https://wiki.openstack.org/wiki/TaskFlow"&gt;Taskflow Wiki&lt;/a&gt;&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Glance currently comes with an eventlet executor which is not easily extensible
by nature and doesn’t support many features that taskflow support out of the
box such as execution on remote workers.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;We propose here a new executor (self-contained) implementing the interfaces of the
executor API. This executor will route the tasks to the eventlet executor of taskflow.
We will be using the &lt;a class="reference external" href="http://docs.openstack.org/developer/taskflow/types.html#taskflow.types.futures.GreenThreadPoolExecutor"&gt;Taskflow Green Thread Pool Executor&lt;/a&gt; which ensures that eventlet green threads are used when
using the taskflow engine.
The initial implementation should provide the same result as the eventlet executor
already contained in Glance. However, subsequent blueprints will come to leverage
more advanced functionalities.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Use the existing eventlet executor. This approach is likely to become rewriting
taskflow.&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 with this spec. However, in the future, it will be possible to plug-in to
the taskflow notification engine and potentially drop its messages onto a
notification bus.&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 should be able to transparently execute tasks with all the
executors.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;For serial execution of tasks, the performance of the evenlet executor and
the taskflow executor should be close to similar.
However, for more complex workflows, we should be able to achieve performance
improvements by parallelizing the work, and also distributing it with taskflow.&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 have to update glance-api.conf and specify ‘taskflow’ as the
executor.
Also, it will be possible to choose the engine mode ‘serial’ or ‘parallel’ and
the maximum number of workers.
Remote workers (not supported with this spec) will require more infrastructure.&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;arnaud&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;harlowja&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="reviewers"&gt;
&lt;h3&gt;Reviewers&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Core reviewer(s):&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;nikhil, zhiyan&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other reviewer(s):&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;harlowja&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;Implementation of the taskflow executor with unit tests.&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;It will be possible to add a specifc configuration in DevStack leverage this
new executor. Ultimately, this is the executor that should be used at 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;Initially, the documentation should explain how to configure glance-api.conf and
what is taskflow. Later on, it should be explained how to achieve more complex
scenario.&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://wiki.openstack.org/wiki/TaskFlow"&gt;https://wiki.openstack.org/wiki/TaskFlow&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/taskflow"&gt;https://github.com/openstack/taskflow&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://pypi.org/project/taskflow/"&gt;https://pypi.org/project/taskflow/&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/85211/14"&gt;https://review.openstack.org/#/c/85211/14&lt;/a&gt; (needs to be rebased once the spec
is approved)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Discussions at the OpenStack Summit in Paris&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
</description><pubDate>Sun, 13 May 2018 00:00:00 </pubDate></item><item><title>Rocky Review Priorities</title><link>http://specs.openstack.org/openstack/glance-specs/priorities/rocky-priorities.html</link><description>
&lt;span id="rocky-priorities"/&gt;
&lt;p&gt;The Rocky review priorities were discussed at the Dublin PTG and refined
during the spec review process early in the Rocky cycle.  The preliminary
list was maintained on the &lt;a class="reference external" href="https://etherpad.openstack.org/p/glance-rocky-priorities"&gt;Rocky PTG priorities etherpad&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This list is an estimate of what the Glance project team can accomplish
during the Rocky cycle based on our developers’ estimates of how much
time they can commit to Glance.  If additional resources become available,
it’s possible that some of the &lt;a class="reference internal" href="../specs/untargeted/index.html"&gt;&lt;span class="doc"&gt;Untargeted Approved Specifications&lt;/span&gt;&lt;/a&gt; could be
added to Rocky.&lt;/p&gt;
&lt;p&gt;The following list is roughly in priority order (highest to lowest).&lt;/p&gt;
&lt;p&gt;TODO: add priorities&lt;/p&gt;
&lt;section id="important-dates"&gt;
&lt;h2&gt;Important dates&lt;/h2&gt;
&lt;p&gt;This is an abbreviated list focused on dates relevant to Glance.  See
&lt;a class="reference external" href="https://releases.openstack.org/rocky/schedule.html"&gt;Rocky Release Schedule&lt;/a&gt; for the complete list for OpenStack.&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;Countdown&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Week of&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;What&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;R-19&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Apr 16&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Rocky-1 milestone&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Friday, April 20: Bug scrub&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;R-14&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;May 21&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;OpenStack Summit&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;R-12&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Jun 04&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Rocky-2 milestone&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Spec Freeze&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Friday, June 8: Bug scrub&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;R-6&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Jul 16&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;glance_store Rocky release&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;R-5&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Jul 23&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Rocky-3 milestone&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;glanceclient Rocky release&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Feature Freeze&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Rocky community goals completed&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Friday, July 27: Bug scrub&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;R-3&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Aug 06&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Glance Release Candidate 1&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;String freeze&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;R-1&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Aug 20&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Final Glance Release Candidates&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;R-0&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Aug 27&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Glance Rocky Release&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Mon, 26 Mar 2018 00:00:00 </pubDate></item><item><title>Artifact Repository</title><link>http://specs.openstack.org/openstack/glance-specs/specs/kilo/artifact-repository.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/glance/+spec/artifact-repository"&gt;https://blueprints.launchpad.net/glance/+spec/artifact-repository&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Extend Glance’s functionality to store not only the VM images but any other
artifacts, i.e binary objects accompanied with composite metadata.&lt;/p&gt;
&lt;p&gt;Glance should become a catalog of such artifacts, providing capabilities to
store, search and retrieve their artifacts, their metadata and associated
binary objects.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Various OpenStack services often need to catalog different objects they use to
operate. Such objects may contain various data as well as metadata needed for
identification and description.&lt;/p&gt;
&lt;p&gt;Images used by Nova to run the VMs are just the best known examples of such
objects. Other examples include Heat templates, Solum Plan Files, Mistral
Workbooks, Murano Application Packages etc.&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;“To catalog” means to have the following functionality:&lt;/dt&gt;&lt;dd&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;To store the object reliably&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;To guarantee its immutabity once it is stored&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;To provide search capabilities to find the objects in catalog&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;To return the detailed info about the requested object&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;To allow fetching the object for usage by a Service&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;To control the access to the object: enforce usage and modification
policies, publication scenarios etc&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;To manage the object lifecyle&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;Obviously, this set of functionality is common for different kinds of objects,
and is usually unrelated to the primary mission of respective projects using
these objects.
That is why it is suggested to have a dedicated service which will provide the
catalog functionality for other OpenStack services. As Glance already serves
as a catalog of Images for Nova, it is suggested to extend its mission so it
may serve as a catalog for other services as well.&lt;/p&gt;
&lt;p&gt;The objects stored in the catalog are called &lt;em&gt;Artifacts&lt;/em&gt;, and the catalog
itself – &lt;em&gt;Artifact Repository&lt;/em&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;It is proposed to add Artifact Repository functionality to Glance, i.e. create
a set of APIs, data models and services which will allow to store artifacts of
different types in Glance.&lt;/p&gt;
&lt;p&gt;It is required to introduce the following concepts and behaviors:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Artifact&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Artifact&lt;/em&gt; is a block of binary data stored with a description – &lt;em&gt;metadata&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;All artifacts should have the following properties:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Artifacts shall be consumable by OpenStack services. Like Nova uses Images
to run the VMs, so will other existing or upcoming OpenStack services use
different kinds of Artifacts. Ability to be consumed by the services is
important: data chunks which are not consumable by other services (e.g. user
data) are NOT artifacts. If one is looking to store such unrelated data then
Swift (or any other generic object storage) should be a proper choice.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Artifacts description (metadata) should have a well-defined, discoverable
structure. Artifacts’ metadata should contain only the fixed set of fields.
Different types of artifacts may have different sets of allowed fields, but
attaching unexpected values should be prohibited.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Artifacts are immutable. I.e. once the artifact is made available, there
should be no way to change its binary content and at least some meaningful
parts of its metadata. So once the consumer has discovered an artifact, its
content is guaranteed to remain the same during the whole life of the object,
and no other object may get the same ID. The artifact may be deleted, but any
modifications introduced will result in creating a new object with a new ID.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;Note: To properly handle modification scenarios it is advised not to delete
the existing artifact, but to create the new version of it. See the “Artifact
Versions” section below&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Artifact types&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Type of the Artifact defines its purpose and contents. It is defined by the
OpenStack service which is supposed to use the artifact, however the mapping
between an Artifact type and a Service is not one-to-one: a single service may
utilise a number of different artifact types, and in some cases the same
types of artifact may be consumed by different services.&lt;/p&gt;
&lt;p&gt;Examples of Artifact types include Images (consumed by Nova), Templates
(consumed by Heat and other services working on top of the Heat, such as
Solum or Murano), Solum plan files (consumed by Solum), Application Packages
(consumed by Murano Application Catalog) etc.
The type of artifact defines the structure of both its binary data and
metadata. Some of the repository operations may also be defined per artifact
type and may have different behaviour for different types.&lt;/p&gt;
&lt;p&gt;The new types of artifacts may be added. This will be implemented using a
plugin system. Each plugin defines one or more of the artifact types and
completely describes their data structure, metadata-scheme and actions.&lt;/p&gt;
&lt;p&gt;Artifact types supported by the particular Glance repository, as well as the
structure and available actions of a particular type should be discoverable
via a set of special API calls.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Artifact plugin&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;A plugin is a python module which defines one or more Artifact Types, with
their custom metadata fields, BLOB kinds, custom validation logic etc (see
respective sections below).&lt;/p&gt;
&lt;p&gt;Glance uses stevedore library to discover the artifact types defined in the
plugins. Each endpoint defined in the plugin identifies the Artifact Type being
exported. The name of the each endpoint should be equal to the name of the
artifact type.
All the endpoints should belong to &lt;cite&gt;glance.artifacts.types&lt;/cite&gt; namespace.&lt;/p&gt;
&lt;p&gt;Each Artifact Type has a version assigned to it. From code point of view each
version of the same Artifact Type is a different python class with different
value of version-identifying attribute. A single plugin may contain definitions
of several versions of the same Artifact Type. Also, different versions of the
same Artifact Type may be defined in different plugins: it is up to the plugin
developers to decide which composition suits their needs better.&lt;/p&gt;
&lt;p&gt;If the plugin contains a single version of some artifact type then the
corresponding endpoint should export the class definition of this particular
type with type name matching the endpoint name.&lt;/p&gt;
&lt;p&gt;If the plugin contains multiple versions of the artifact type then the
corresponding endpoint should export a list of class definitions, and each of
these classes should have distinct type version values and identical type name,
all equal to the name of endpoint.&lt;/p&gt;
&lt;p&gt;A given version of specific artifact type may be defined only in a single
plugin, i.e. if there may be no second plugin defining the same artifact type
with the same version.&lt;/p&gt;
&lt;p&gt;At startup Glance will inspect all the enabled plugins and ensure that no
artifact-type conflict occurs. If several active plugins define the same
artifact type and version, the critical exception occures and artifact’s
server does not start. It is up to the operator to resolve the conflict and
uninstall the unnecessary plugin(s).&lt;/p&gt;
&lt;p&gt;To enable a plugin the cloud operator has to install the python module into
the python environment of the node which runs Glance and make appropriate
changes into the configuration files.&lt;/p&gt;
&lt;p&gt;Only the types from explicitly enabled plugins are available for usage.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Metadata Structure&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The metadata describing the artifacts has to have a predefined and discoverable
structure. Some of the metadata fields are common for all the types of
Artifacts, while the others are defined for particular types only.&lt;/p&gt;
&lt;p&gt;Some of the fields are immutable: i.e. their value can be changed only while
the artifact is being interactively created (see below) and is fixed since the
moment once the artifact is published in the repository. Other fields may be
modified at any time.  Also there are system fields which cannot be modified
at any time - their value is set automatically by the repository.&lt;/p&gt;
&lt;table class="docutils align-default" id="id2"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;&lt;strong&gt;Common metadata fields&lt;/strong&gt;&lt;/span&gt;&lt;/caption&gt;
&lt;colgroup&gt;
&lt;col style="width: 12.5%"/&gt;
&lt;col style="width: 12.5%"/&gt;
&lt;col style="width: 7.5%"/&gt;
&lt;col style="width: 17.5%"/&gt;
&lt;col style="width: 50.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;Access&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Required&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Data 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;ID&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;System&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;N/A&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;UUID String&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Identifies the artifact in the repository.
Is assigned automatically once the artifact’s draft is registered.
Is not supposed to be explicitly set by the user, however administrators
may override this value if needed.&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Type&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Immutable&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Yes&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Alphanumeric string, valid artifact type name&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Identifies the type of artifact, and so its data and metadata structure
should be one of the types supported by the repository (handled by the
active plugins)&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;TypeVersion&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;System&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;N/A&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;String following SemVer notation&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;A system field defining the version of artifact type, i.e. the version
of the plugin which contains the artifact type definition.
The value is set automatically when the artifact record is created.&lt;/p&gt;
&lt;p&gt;In future, this may be used to do automatic or manual migrations of
artifacts data and metadata.&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Name&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Immutable&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Yes&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Alphanumeric string, 255 characters max&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Defines the name of the artifact.
In the future certain uniquiness of (name, version) will be guaranteed,
so that it will be capable of identifying the artifact within a catalog.&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Version&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Immutable&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Yes&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;String following the SemVer notation&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Defines the version of the artifact. See “Artifact versioning” section
below for the details.&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Mutable&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;String&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Arbitrary text describing the artifact, 255 characters max&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Tags&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Mutable&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;Set of alphanumeric strings, each 255 characters max&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;A set of arbitrary string labels associated with the artifact for
search and filter capabilities&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Visibility&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Mutable&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Yes&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Enum, any of PRIVATE, PUBLIC&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;A  field indicating if the artifact is accessible for all the
tenants in the cloud (PUBLIC), or for its owner only (PRIVATE).&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;State&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;System&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;N/A&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Enum, any of: CREATING, ACTIVE, DEACTIVATED, DELETED&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;A system field set by the repository, indicating the current phase of
the artifact’s lifecycle. See “Artifact Lifecyle” below for details&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Owner&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;System&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;N/A&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;String, OpenStack tenant (project) identifier&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;An identifier of the tenant (project) to which the artifact has been
uploaded&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;CreatedAt&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;System&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;N/A&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Timestamp&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Time when the artifact record was created in the repository.
Never changes once set&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;UpdatedAt&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;System&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;N/A&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Timestamp&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Time when the artifact was last modified. Is updated automatically by
repository on every operation which updates the artifact record or its
relatives.&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;PublishedAt&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;System&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;N/A&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Timestamp&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Time when the artifact was published, i.e. moved from CREATING to ACTIVE
state. Empty for artifacts in CREATING state&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;DeletedAt&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;System&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;N/A&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Timestamp&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Time when the artifact was deleted, i.e. moved from CREATING, ACTIVE or
DEACTIVATED state to DELETED. Is empty for artifacts not in DELETED
state&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;Type-specific metadata fields&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;For each type of artifact, additional metadata fields may be defined.
This set of fields and their properties are specified by the artifact types.
The plugin which defines the artifact defines all its type-specific fields.
Each type-specific metadata field is represented by a data structure having
the following properties:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Field name&lt;/strong&gt; - alphanumeric value identifying the field. Should be unique
per artifact type&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Field type&lt;/strong&gt; - a type of the data stored in the field. Identifies the
types of queries which may be made to search and filter the artifacts in
catalog.
The following types are supported:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;String&lt;/em&gt; - simple string value (255 characters max). In listing queries
may use this field to filter artifacts by value equality (e.g. “filter all
the artifacts of type ‘Image’ having the field ‘OS_TYPE’ equal to
‘Linux’”)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;Integer&lt;/em&gt;. - integer field. In listing queries may use this field to
filter artifacts by both value equality and value range (e.g. “filter all
the artifacts of type ‘Image’ having the field ‘REQUIRED_RAM’ less or equal
to 16”)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;Numeric&lt;/em&gt; - same as Integer, but stored as Numeric&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;Boolean*&lt;/em&gt; - boolean values, having either ‘True’ or ‘False’ as the value.
In listing queries may use this field to filter artifacts by value equality.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;Text&lt;/em&gt; - Long text field. May not be used for filtering, just stores
arbitrary large text descriptions, JSONs etc. The loading of these fields
from the Database should be deferred when the artifacts are listed, taken
for modification etc - they should be loaded only when the client request
the contents of the artifact. This reduces the load on Database.
Additionally the plugin developers may put custom constraints to limit the
length of the text.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;Array&lt;/em&gt; - a list of values of some specific type (String, Text, Integer,
Numeric, Boolean) or their combination.
Such field may be used for tag-like filtering semantics (i.e. the artifacts
of some type may have a set field called ‘Category’, each such artifact may
have a number of categories assigned, and the filtering query may be made
to list only the artifacts having the specific category)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;Dict&lt;/em&gt; - a set of key-value pairs, where key are string values (255 chars
max) while values may be any of String, Text, Integer, Numeric or Boolean.
May be used for filtering the artifacts by having specific value of some
key or by just having some specific key with any value.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Required&lt;/strong&gt; - boolean value indicating if the field value should be
specified for the artifact to be valid.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Mutable&lt;/strong&gt; - boolean value indicating if the field value may be changed
after the artifact is published.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Internal&lt;/strong&gt; - a boolean value indicating that the value of this field is not
shown to the end-user (cannot be fetched using API or used in queries), but
may be accessed internally by the plugin logic.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Default&lt;/strong&gt; - a default value for the field may be specified by the Artifact
Type.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Allowed values&lt;/strong&gt; - a list of possible values for the field to store&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Constraints&lt;/strong&gt; - a number of constraints may be defined for each metadata
field. Available constraints depend on the field type:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;String&lt;/em&gt; -  minLength, maxLength, pattern&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;Integer&lt;/em&gt; and &lt;em&gt;Numeric&lt;/em&gt; -  minimum, maximum values&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;Array&lt;/em&gt; - types of the elements (either a single type for all the elements
or specific type for each element), minimum and maximum numbers of elements
in the array, type-specific constrains for elements.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;Dict&lt;/em&gt; - types of the values (either a single type for all the values of
specific type for each value), minimum and maximum numbers of values in the
dict, type-specific constrains for values.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Also, custom, code-driven constrains may be defined for each field by the
plugin developer.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Artifact Versions&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The Artifact repository is able to store different versions of the same
artifact. From repository’s point of view these are different objects
(having different IDs, stored independently and having independent
lifecycle), but having the same type and name, but different version fields.&lt;/p&gt;
&lt;p&gt;The version field is one of common immutable metadata fields (see above).
It follows the &lt;a class="reference external" href="http://semver.org"&gt;SemVer notation&lt;/a&gt;, i.e. its value is
composed out of 3 numeric parts (major version, minor version and patch, with
optional alphanumeric prerelease suffix), e.g. 5.1.3 or 1.1.4-alpha.
An order is defined between version values according to the SemVer spec, e.g.
1.2.3 &amp;gt; 1.2.2, 1.0.1 &amp;lt; 1.1.0, 1.0.0 &amp;gt; 1.0.0-some-suffix etc, according to
spec.
When the version is specified, some of its parts may be omitted: e.g. 10 will
stand for 10.0.0, 5.1 will stand for 5.1.0. The repository will accept such an
input and will convert it to the fill semver notation.
The major version part is mandatory.
Either major or minor parts should be non-zero: e.g. 0.1 is possible while 0.0
is not.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Binary Data&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The data is the heart and soul of artifacts and the primary reason of their
existence. Sometimes it is just a simple text (or XML, YAML or JSON object
represented as text) which may be stored in the artifact’s additional metadata
fields, however in many cases it is a large binary object, such as VM image or
other large block of bytes. And even textual data is often completely unrelated
to artifact’s metadata - and thus has to be treated separately.&lt;/p&gt;
&lt;p&gt;Be the data really binary or textual it should be stored independently from the
artifact record in some dedicated storage system - in a same manner as VM
images are stored independently from their definitions in the current version
of Glance.&lt;/p&gt;
&lt;p&gt;When the artifact is initially created in the repository (the record is
inserted into the database), it is in the CREATING state (see the “Artifact
Lifecycle” section below) and has no binary data associated. Then - before
publishing the artifact - its owner may upload the data by using the
appropriate API calls or specify the location/uri of the existing binary blob
pre-uploaded to some back-end storage.
If the new blobs are uploaded, they will be placed into the storage system (the
one which is being used for the particular instance of Glance) and associated
with the artifact record by using its id.
If the existing location/uri is passed, only the association will be made.&lt;/p&gt;
&lt;p&gt;When the artifact repository is browsed, only the artifact metadata is
returned: the data objects for each specific artifact have to be downloaded
separately, by sending an appropriate API calls either to Glance or directly to
the appropriate underlying storage system.&lt;/p&gt;
&lt;p&gt;Unlike the current Glance Images, a single artifact may have more than one
binary object associated.&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;&lt;em&gt;For example, a Heat template, being stored as an artifact, may require a
Heat template itself, a number of provider templates, plus, probably, an Icon
to be  displayed in the catalog UI. All of these are considered to be
“artifact’s data” (although the templates are not actually binary), and there
is no sense in merging them into a single block of data: different templates
may be required at different moments of time, while the icon is needed in UI
only - so they are stored as different “binary objects” and are retrieved
one-by-one when really needed&lt;/em&gt;&lt;/p&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;This means that each artifact may have a number of different BLOBs associated.&lt;/p&gt;
&lt;p&gt;The amount of blobs and their types (“Heat template”, “Provider Templates” and
“Icon” in the example above) are defined per each artifact type. When the
artifact is in CREATING state its owner will have to upload all the required
parts one-by-one, specifying their types every time. If some required blob is
not uploaded, the “publishing check” will not pass and the artifact will not be
accepted into the repository. So, in general, this is similar to specifying the
values of additional type-specific metadata fields.&lt;/p&gt;
&lt;p&gt;For each artifact type its plugin can define several BLOB properties that
correspond to the BLOBs supported by this particular type.
BLOB properties can be defined in 2 forms - either as a single
BinaryObject, or as BinaryObjectList. The latter can be constrained with
maximum and minimum length.
Each BLOB property is represented by a data structure having the following
properties:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Name&lt;/strong&gt; (alphanumeric string) - name of the blob property. Should be unique
per artifact type.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Required&lt;/strong&gt; (boolean) - a flag indicating if the blob(s) of this property
is required for the artifact to be valid.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Minimum Length (for BinaryObjectList only)&lt;/strong&gt; (a positive integer
value or None) - specifies the minimal required amount of blobs
per artifact. If set to None, then the number of blobs in BLOBs list per
artifact has no lower bound.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Maximum Length (for BinaryObjectList only)&lt;/strong&gt; (a positive integer
value or None) - specifies the maximum amount of blobs per artifact.
If set to None, then the number of blobs in BLOBs list per
artifact has no upper bound.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;For example, the above-mentioned artifact type “Heat template” may define
an optional BinaryObjectList property with the Name set to “ProviderTemplate”,
and a required BinaryObjectList property with the name “Icon” and minimum
and maximum length constraints equal to 1.
This means that the artifacts of this type have to contain exactly one icon
blob and zero or more provider template blobs.&lt;/em&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The repository provides an API call to inspect the blob contents of each
artifact.&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;&lt;em&gt;In the example above the API returns a dictionary containing two
keys: “ProviderTemplates” and “Icon”. The first key defined a list of
records, each one corresponding to a different blob with a provider template,
the second one defines a single record corresponding to the blob with the
icon. Each of the blob records contains an id of the particular blob, which
may be used to download the blob.&lt;/em&gt;&lt;/p&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;Binary data is immutable, and no new blobs may be added as well as no existing
blobs may be deleted once the artifact is moved to the ACTIVE state.
When the artifact is deleted, all its blobs are deleted as well.
The blob data is accessible to a user only if they have permission to access
the artifact containing that blob.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Artifact Dependency Relations&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;In OpenStack ecosystems the entities rarely go alone: usually they interact
with each other. Artifacts aren’t different: quite often an artifact may need
to work with other artifacts in one way or another.
In this case it may be reasonable to introduce a concept of &lt;em&gt;Artifact
Dependency&lt;/em&gt;: an artifact may depend on any number of other artifacts of any
type.&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;&lt;em&gt;For example there may be an artifact containing a reusable pack of Puppet
manifests which configure some common software components on the VMs
(artifact A). Another artifact containing some Heat Software Config template
(artifact B) may utilise the puppet manifests from the artifact A for some
post-deploy configuration actions on the VMs created by the template. In
this case artifact B may specify artifact A as its dependency, so the
service which is going to use B may detect, that it may need A as well and
download it in advance.&lt;/em&gt;&lt;/p&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;This eventually creates chains of transitively-dependent artifacts.
An API method provided by Artifact Repository should allow to retrieve all the
dependencies of a given artifact. Subsequent calls to the same API will allow
to retrieve all the transitive dependencies.&lt;/p&gt;
&lt;p&gt;These dependency relations are actually a special kind of artifact metadata:
they are stored in repository database together with artifact records. They
are immutable, i.e. can be defined only while the artifact is in the CREATING
state and cannot be modified after it is published.&lt;/p&gt;
&lt;p&gt;The operations to create, view or modify a dependency for a particular
artifact should be implemented as a set of APIs similar to other metadata
editing.&lt;/p&gt;
&lt;p&gt;The dependencies cannot be circular (e.g if A depends on B, B depends on C and
C depends on D, then D cannot depend on A), and the published artifact may not
depend on an artifact being in a “CREATING” state. For example, if A depends
on B and both are in “CREATING” state, then B should be published before A,
otherwise the publishing check of A will fail.&lt;/p&gt;
&lt;p&gt;The dependencies may be created only on the artifacts which belong to the same
tenant as the dependent artifact.
Once the dependency is established, a target artifact cannot be deleted before
its dependent artifact is deleted. If both are deleted and should be restored,
they restoreation should happen in the same order as creation: the target
artifact first, the dependent - second.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Artifacts Lifecycle&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;An Artifact may be in one of the three states, indicating different phases of
its lifecycle:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;CREATING&lt;/strong&gt; state indicates that the artifact record has been created in
repository (ID was assigned), but the artifact is still being constructed
(some fields have to be set, the data uploaded etc). Mutable metadata fields
may be modified while the artifact is in this state. The binary data may be
uploaded or location uri for pre-uploaded blobs may be specified, the
dependencies may be set or modified.&lt;/p&gt;
&lt;p&gt;Artifacts in the CREATING state are not visible to tenants other than the
owner’s even if the ‘Visibility’ field is set to ‘PUBLIC’.
When artifact is in the CREATING state its owner may call a ‘Publish’ API
method to publish the artifact. This will validate the artifact and change its
state to ACTIVE.
When the artifact is in CREATING state its owner may initiate its deletion.
This will change the state of the artifact to ‘DELETED’.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;ACTIVE&lt;/strong&gt; state indicates that the artifact is available for use.
When the artifact is in this state the immutable metadata fields may not be
updated, no new binary data may be uploaded, existing data may not be deleted.&lt;/p&gt;
&lt;p&gt;Artifacts in ACTIVE state are visible to other tenants if the ‘Visibility’
field is set to PUBLIC.
When the artifact is in this state it is assumed that it may be used by
the third-party services.
When the artifact is in ACTIVE state its owner may initiate its deletion.
This will change the state of the artifact to ‘DELETED’.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;DEACTIVATED&lt;/strong&gt; state indicates that the artifact which had been previously
published has been temporary deactivated (i.e. prevented from being used) by
the cloud administrator. Artifact is visible to all the users which may
access it regularly (i.e. to its owner and to other tenants if it is
made public) and its metadata can be fetched as well, but the binary data
is not accessible and the artifact should not be used by third-party services
until the deactivation is removed.
Usually this is used for investigations of reported problems with artifacts.
When the investigation is completed the artifact may be reactivated again (by
changing the state back to ACTIVE) or deleted.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;DELETED&lt;/strong&gt; state indicates that the artifact has been deleted and its data
and metadata objects are not accessible anymore.&lt;/p&gt;
&lt;p&gt;This state is available only if a “delayed_delete” option is enabled in the
configuration file, which makes the deletion to be non-immediate: the
artifacts are just marked as deleted, however the actual deletion is delayed
for the configurable amount of time.&lt;/p&gt;
&lt;p&gt;If delayed_delete is disabled, then artifacts do not enter the DELETED state,
their records are permanently removed from the repository when the deletion
operation is executed.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A state transition diagram can be found &lt;a class="reference external" href="https://wiki.openstack.org/w/images/0/05/Artifact_states.png"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Composing an Artifact&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Artifacts may be created using an iterative process, which starts with
creating an artifact record in the database. Then a number of APIs may be
called to set the values of various metadata properties, upload the binary
data, specify the dependency links etc.&lt;/p&gt;
&lt;p&gt;While the aftifact is being composed it remains in CREATING state.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Publishing an Artifact&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Publishing is an operation which makes an artifact available for usage: when
all the metadata fields are set and the binary data parts are uploaded
(which may be a lengthly multi-step process), it may be made available by
calling a special API method to change its state to ACTIVE.&lt;/p&gt;
&lt;p&gt;During the execution of this call Glance will verify that all the dependency
relations are set to the existing and already published artifacts. If at least
one of the dependencies either does not exist (i.e. the artifact has been
deleted after the dependency was created) or is not in the ACTIVE state, then
the publishing action will fail.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Deleting an Artifact&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;An artifact may be deleted only by its owner or a cloud administrator. When
the delete action is called, the following actions are executed:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;All the artifacts of the current tenant are inspected. If any of them have a
Dependency Relation to the artifact being deleted, the deletion operation is
aborted&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If the delayed delete is enabled, artifact’s state is set to DELETED and the
deletion operation is scheduled to in the configurable time interval&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If the soft delete is not enabled, then a background deletion operation is
scheduled to run immediately&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The deletion operation (be it delayed or immediate) does the following:&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Delete all the binary data objects of the artifact from the underlying
storage system.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Delete the artifact’s record from the database, including all the custom
metadata property values, associated tags and outgoing dependency relations&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;The need of a catalog service seems obvious, however sometimes questions are
asked if Glance is appropriate project for this. Some people were suggesting
to use a completely separate service for this, some suggested to use Swift
instead of Glance.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Why not a separate service?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Because Glance’s Images are perfect examples of Artifacts: they are binary
objects stored with arbitrary metadata describing them. Glance already
provides search and filter capabilities, they just have to be extended to
support artifact types other then images.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Why not to use Swift?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;For a number of reasons.&lt;/p&gt;
&lt;p&gt;First, Swift is not a catalog, it is just an object storeage. There are no
search or filter capabilities, object immutability is not guranteed.&lt;/p&gt;
&lt;p&gt;Then, Swift has a different level of abstraction: it does not care about the
data which is being stored within it, while Glance should be aware of the
artifact types specifics.&lt;/p&gt;
&lt;p&gt;Last but not least, many production-grade OpenStack deployments do not have
Swift deployed, as they do not need it. Meanwhile, Glance is present on each
and every OpenStack cloud.&lt;/p&gt;
&lt;p&gt;Meanwhile, Swift still may be used as an underlying storage for artifacts - in
the same way as Glance uses it to store Images.&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;This will use a relational database and exist in the same database as the
existing Glance relational data, but there is not anticipated impact
to existing Glance data models. This is all new functionality.&lt;/p&gt;
&lt;p&gt;Support will be added to:
* glance/db/sqlalchemy/api.py
* registry/api.py
* simple/api.py&lt;/p&gt;
&lt;p&gt;A new script glance/db/sqlalchemy/artifacts.py will be added&lt;/p&gt;
&lt;p&gt;The table classes will be in glance/db/sqlalchemy/models_artifacts.py&lt;/p&gt;
&lt;p&gt;The following DB schema is the initial suggested schema. Constraints are not
shown for readability.&lt;/p&gt;
&lt;table class="docutils align-default" id="id3"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;&lt;strong&gt;Artifacts Table&lt;/strong&gt;&lt;/span&gt;&lt;/caption&gt;
&lt;colgroup&gt;
&lt;col style="width: 25.0%"/&gt;
&lt;col style="width: 25.0%"/&gt;
&lt;col style="width: 25.0%"/&gt;
&lt;col style="width: 25.0%"/&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Field&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;Null&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Key&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;id&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;varchar(36)&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;PRI&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;name&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;varchar(255)&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;MUL&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;type_name&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;varchar(255)&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;MUL&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;type_version_prefix&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;bigint(20)&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;NO&lt;/p&gt;&lt;/td&gt;
&lt;td/&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;type_version_suffix&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;varchar(255)&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;YES&lt;/p&gt;&lt;/td&gt;
&lt;td/&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;type_version_meta&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;varchar(255)&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;YES&lt;/p&gt;&lt;/td&gt;
&lt;td/&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;version_prefix&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;bigint(20)&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;NO&lt;/p&gt;&lt;/td&gt;
&lt;td/&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;version_suffix&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;varchar(255)&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;YES&lt;/p&gt;&lt;/td&gt;
&lt;td/&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;version_meta&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;varchar(255)&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;YES&lt;/p&gt;&lt;/td&gt;
&lt;td/&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;description&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;text&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;YES&lt;/p&gt;&lt;/td&gt;
&lt;td/&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;visibility&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;varchar(32)&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;MUL&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;state&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;varchar(32)&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;MUL&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;owner&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;varchar(255)&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;MUL&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;created_at&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;datetime&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;NO&lt;/p&gt;&lt;/td&gt;
&lt;td/&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;updated_at&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;datetime&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;NO&lt;/p&gt;&lt;/td&gt;
&lt;td/&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;published_at&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;datetime&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;YES&lt;/p&gt;&lt;/td&gt;
&lt;td/&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;deleted_at&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;datetime&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;YES&lt;/p&gt;&lt;/td&gt;
&lt;td/&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;div class="line-block"&gt;
&lt;div class="line"&gt;&lt;br/&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;table class="docutils align-default" id="id4"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;&lt;strong&gt;Artifact Blobs Table&lt;/strong&gt;&lt;/span&gt;&lt;/caption&gt;
&lt;colgroup&gt;
&lt;col style="width: 25.0%"/&gt;
&lt;col style="width: 25.0%"/&gt;
&lt;col style="width: 25.0%"/&gt;
&lt;col style="width: 25.0%"/&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Field&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;Null&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Key&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;id&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;varchar(36)&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;PRI&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;name&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;varchar(36)&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;MUL&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;artifact_id&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;varchar(36)&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;MUL&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;size&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;bigint(20)&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;NO&lt;/p&gt;&lt;/td&gt;
&lt;td/&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;position&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;int(11)&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;YES&lt;/p&gt;&lt;/td&gt;
&lt;td/&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;item_key&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;varchar(329)&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;YES&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;MUL&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;checksum&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;varchar(329)&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;YES&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;MUL&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;created_at&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;datetime&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;NO&lt;/p&gt;&lt;/td&gt;
&lt;td/&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;updated_at&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;datetime&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;NO&lt;/p&gt;&lt;/td&gt;
&lt;td/&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;div class="line-block"&gt;
&lt;div class="line"&gt;&lt;br/&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;table class="docutils align-default" id="id5"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;&lt;strong&gt;Artifact Blob Locations Table&lt;/strong&gt;&lt;/span&gt;&lt;/caption&gt;
&lt;colgroup&gt;
&lt;col style="width: 31.2%"/&gt;
&lt;col style="width: 31.2%"/&gt;
&lt;col style="width: 18.8%"/&gt;
&lt;col style="width: 18.8%"/&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Field&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;Null&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Key&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;id&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;varchar(36)&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;PRI&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;value&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;text&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;NO&lt;/p&gt;&lt;/td&gt;
&lt;td/&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;blob_id&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;varchar(36)&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;MUL&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;status&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;varchar(36)&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;YES&lt;/p&gt;&lt;/td&gt;
&lt;td/&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;position&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;int(11)&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;YES&lt;/p&gt;&lt;/td&gt;
&lt;td/&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;created_at&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;datetime&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;NO&lt;/p&gt;&lt;/td&gt;
&lt;td/&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;updated_at&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;datetime&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;NO&lt;/p&gt;&lt;/td&gt;
&lt;td/&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;div class="line-block"&gt;
&lt;div class="line"&gt;&lt;br/&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;table class="docutils align-default" id="id6"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;&lt;strong&gt;Artifact Dependencies Table&lt;/strong&gt;&lt;/span&gt;&lt;/caption&gt;
&lt;colgroup&gt;
&lt;col style="width: 31.2%"/&gt;
&lt;col style="width: 31.2%"/&gt;
&lt;col style="width: 18.8%"/&gt;
&lt;col style="width: 18.8%"/&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Field&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;Null&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Key&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;id&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;varchar(36)&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;PRI&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;artifact_source&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;varchar(36)&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;MUL&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;artifact_dest&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;varchar(36)&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;MUL&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;artifact_origin&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;varchar(36)&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;MUL&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;is_direct&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;tinyint(1)&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;NO&lt;/p&gt;&lt;/td&gt;
&lt;td/&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;position&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;int(11)&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;YES&lt;/p&gt;&lt;/td&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;varchar(36)&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;YES&lt;/p&gt;&lt;/td&gt;
&lt;td/&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;created_at&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;datetime&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;NO&lt;/p&gt;&lt;/td&gt;
&lt;td/&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;updated_at&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;datetime&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;NO&lt;/p&gt;&lt;/td&gt;
&lt;td/&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;div class="line-block"&gt;
&lt;div class="line"&gt;&lt;br/&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;table class="docutils align-default" id="id7"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;&lt;strong&gt;Artifact Properties Table&lt;/strong&gt;&lt;/span&gt;&lt;/caption&gt;
&lt;colgroup&gt;
&lt;col style="width: 31.2%"/&gt;
&lt;col style="width: 31.2%"/&gt;
&lt;col style="width: 18.8%"/&gt;
&lt;col style="width: 18.8%"/&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Field&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;Null&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Key&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;id&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;varchar(36)&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;PRI&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;artifact_id&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;varchar(36)&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;MUL&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;string_value&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;varchar(255)&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;YES&lt;/p&gt;&lt;/td&gt;
&lt;td/&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;int_value&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;int(11)&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;YES&lt;/p&gt;&lt;/td&gt;
&lt;td/&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;numeric_value&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;decimal(10,0)&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;YES&lt;/p&gt;&lt;/td&gt;
&lt;td/&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;bool_value&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;tinyint(1)&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;YES&lt;/p&gt;&lt;/td&gt;
&lt;td/&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;text_value&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;text&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;YES&lt;/p&gt;&lt;/td&gt;
&lt;td/&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;position&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;int(11)&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;YES&lt;/p&gt;&lt;/td&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;varchar(36)&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;MUL&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;created_at&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;datetime&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;NO&lt;/p&gt;&lt;/td&gt;
&lt;td/&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;updated_at&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;datetime&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;NO&lt;/p&gt;&lt;/td&gt;
&lt;td/&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;div class="line-block"&gt;
&lt;div class="line"&gt;&lt;br/&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;table class="docutils align-default" id="id8"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;&lt;strong&gt;Artifact Tags Table&lt;/strong&gt;&lt;/span&gt;&lt;/caption&gt;
&lt;colgroup&gt;
&lt;col style="width: 31.2%"/&gt;
&lt;col style="width: 31.2%"/&gt;
&lt;col style="width: 18.8%"/&gt;
&lt;col style="width: 18.8%"/&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Field&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;Null&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Key&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;id&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;varchar(36)&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;PRI&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;artifact_id&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;varchar(36)&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;MUL&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;value&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;varchar(255)&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;YES&lt;/p&gt;&lt;/td&gt;
&lt;td/&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;created_at&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;datetime&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;NO&lt;/p&gt;&lt;/td&gt;
&lt;td/&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;updated_at&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;datetime&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;NO&lt;/p&gt;&lt;/td&gt;
&lt;td/&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&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 new APIs to be placed under the &lt;em&gt;/v2/artifacts&lt;/em&gt; API branch&lt;/p&gt;
&lt;p&gt;All the APIs which are specific to the particular artifact type should be
placed to &lt;cite&gt;/v2/artifacts/{artifact_type}&lt;/cite&gt;, where &lt;cite&gt;artifact_type&lt;/cite&gt; is a constant
defined by the artifact type definition (i.e. by the plugin), which usually
should be plural of the artifact type name.
For example, for artifacts of type “template” this constant may be called
‘templates’, so the API endpoints will start with &lt;cite&gt;/v2/artifacts/templates&lt;/cite&gt;.&lt;/p&gt;
&lt;p&gt;The &lt;cite&gt;artifact_type&lt;/cite&gt; constant should unambiguously identify the
artifact type, so the values of this constants should be unique among all the
artifact types defined by the active plugins.&lt;/p&gt;
&lt;p&gt;The &lt;cite&gt;artifact_type&lt;/cite&gt; constant should be followed by &lt;cite&gt;type_version&lt;/cite&gt; identifier
containing a SemVer-compliant string prefixed with &lt;cite&gt;v&lt;/cite&gt;, e.g. &lt;cite&gt;v1.1.5&lt;/cite&gt;. This
will identify the particular version of the artifact type if there are many of
them available. In the “List Artifacts” and “Get an Artifact” API calls the
&lt;cite&gt;type_version&lt;/cite&gt; is optional and may be omitted.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;dl&gt;
&lt;dt&gt;&lt;strong&gt;List artifacts&lt;/strong&gt;&lt;/dt&gt;&lt;dd&gt;&lt;ul&gt;
&lt;li&gt;&lt;dl&gt;
&lt;dt&gt;&lt;strong&gt;GET /v2/artifacts/{artifact_type}/[{type_version}/]creating&lt;/strong&gt; - list&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;artifact drafts&lt;/p&gt;
&lt;p&gt;Returns the list of artifacts in CREATING state having the specified
type and owned by the current tenant. If the user is administrator
returns the artifacts in CREATING state owned by all the tenants.&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/li&gt;
&lt;li&gt;&lt;dl&gt;
&lt;dt&gt;&lt;strong&gt;GET /v2/artifacts/{artifact_type}/[{type_version}/]&lt;/strong&gt; - list artifacts&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;which are ready for usage&lt;/p&gt;
&lt;p&gt;Returns the list of artifacts in ACTIVE state, which are either owned
by the current tenant or are made available to everyone with setting
Visibility metadata field to PUBLIC.&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/li&gt;
&lt;li&gt;&lt;dl&gt;
&lt;dt&gt;&lt;strong&gt;GET /v2/artifacts/{artifact_type}/[{type_version}/]deactivated&lt;/strong&gt; - list&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;artifacts in DEACTIVATED state.&lt;/p&gt;
&lt;p&gt;Returns the list of artifacts in DEACTIVATE state which are temporary
suspended from usage.&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/li&gt;
&lt;li&gt;&lt;dl class="simple"&gt;
&lt;dt&gt;URL parameters:&lt;/dt&gt;&lt;dd&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;dl class="simple"&gt;
&lt;dt&gt;&lt;cite&gt;artifact_type&lt;/cite&gt; identifier of the artifact type, should be equal to a&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;valid constant defined in one of the active artifact plugins.&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;cite&gt;type_version&lt;/cite&gt; optional identifier defining the version of artifact
type. If omitted all versions of an artifact type are assumed, but
sorting and filtering capabilities are limited to generic properties
only.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/li&gt;
&lt;li&gt;&lt;dl&gt;
&lt;dt&gt;Query parameters:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Query may contain parameters intended for filtering and soring by most
of common and type-specific metadata fields.
Type-specific fields may be used only if &lt;cite&gt;type_version&lt;/cite&gt; parameter is
set to specific version of the artifact type.
The set of parameters and their values should be compliant to the
schema defined by the artifact type and its version.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Filtering&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Filter keys may be any generic and type-specific metadata fields of
primitive type, like ‘string’, ‘numeric’, ‘int’ and ‘bool’. But
filtering by type-specific properties is allowed only when artifact
version is provided.&lt;/p&gt;
&lt;p&gt;Direct comparison requires a property name to be specified as query
parameter and the filtering value as its value, e.g. &lt;cite&gt;?name=some_name&lt;/cite&gt;&lt;/p&gt;
&lt;p&gt;Parameter names and values are case sensitive.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Artifact API supports filtering operations in format
&lt;cite&gt;?name=&amp;lt;op&amp;gt;:some_name&lt;/cite&gt;, where &lt;cite&gt;op&lt;/cite&gt; is one of the following:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;eq&lt;/strong&gt;: equal;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;ne&lt;/strong&gt;: not equal;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;gt&lt;/strong&gt;: greater than;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;ge&lt;/strong&gt;: greater or equal than;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;lt&lt;/strong&gt;: lesser than;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;le&lt;/strong&gt;: lesser or equal than.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Set comparison filtering is available for all the set-valued
type-specific metadata fields as well as common field “tags”.&lt;/p&gt;
&lt;p&gt;Set comparison requires a property name to be specified as query
parameter. The property may be repeated several times, e.g. the query
&lt;cite&gt;?tags=abc&amp;amp;tags=cde&amp;amp;tags=qwerty&lt;/cite&gt; will filter artifacts having either
‘abc, ‘cde’ or ‘qwerty’ tags associated.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Checking for entry into the array property is performed by &lt;strong&gt;in&lt;/strong&gt;
operation. It’s done the same way as other filters, e.g.
&lt;cite&gt;?items_array=in:array_element&lt;/cite&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Sorting&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;In order to retrieve data in any sort order and direction, artifacts
REST API accepts multiple sort keys and directions.&lt;/p&gt;
&lt;p&gt;Artifacts API will align with the &lt;a class="reference external" href="https://github.com/openstack/api-wg/blob/master/guidelines/pagination_filter_sort.rst"&gt;API Working group sorting guidelines&lt;/a&gt; and support the following parameter on
the request:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;sort: Comma-separated list of sort keys, each key is optionally
appended with &amp;lt;:dir&amp;gt;, where ‘dir’ is the direction for the
corresponding sort key (supported values are ‘asc’ for ascending
and ‘desc’ for descending)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Sort keys may be any generic and type-specific metadata fields of
primitive type, like ‘string’, ‘numeric’, ‘int’ and ‘bool’. But sorting
by type-specific properties is allowed only when artifact version
is provided.&lt;/p&gt;
&lt;p&gt;Default value for sort direction is ‘desc’, default value for sort key
is ‘created_at’.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Pagination&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;cite&gt;limit&lt;/cite&gt; and &lt;cite&gt;marker&lt;/cite&gt; query parameters may be used to paginate through
the artifacts collection in the same way as it is done in the current
version of Glance “List Images” API.&lt;/p&gt;
&lt;p&gt;Maximum &lt;cite&gt;limit&lt;/cite&gt; number is 1000. It’s done for security reasons to protect
the system from intruders to prevent them from sending requests that can
pull the entire database at a time.&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/li&gt;
&lt;li&gt;&lt;dl class="simple"&gt;
&lt;dt&gt;HTTP Responses:&lt;/dt&gt;&lt;dd&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;200 if &lt;cite&gt;artifact_type&lt;/cite&gt; is valid&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;404 if no Artifact Type is defined to handle specified value of
&lt;cite&gt;artifact_type&lt;/cite&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Response schema: [JSON list with artifacts’ metadata]&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;&lt;strong&gt;Create a new Artifact draft&lt;/strong&gt;&lt;/dt&gt;&lt;dd&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;POST /v2/artifacts/{artifact_type}/{type_version}/creating&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Creates a new artifact record in database, the status of artifact is set
to CREATING. Request body may contain initial metadata of the artifact.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;dl class="simple"&gt;
&lt;dt&gt;URL parameters:&lt;/dt&gt;&lt;dd&gt;&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;cite&gt;artifact_type&lt;/cite&gt; identifier of the artifact type, should be equal to a
valid constant defined in one of the active artifact plugins.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;cite&gt;type_version&lt;/cite&gt; identifier defining the version of artifact type.&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;HTTP Responses:&lt;/dt&gt;&lt;dd&gt;&lt;ul&gt;
&lt;li&gt;&lt;p&gt;201 if everything went fine. Location header is set to the artifact
location&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;404 if no Artifact Type is defined to handle specified value of
&lt;cite&gt;artifact_type&lt;/cite&gt; and/or &lt;cite&gt;type_version&lt;/cite&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;400 if an artifact of this type with the same name and version already
exists.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Response schema: [JSON with created artifact]&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;dl class="simple"&gt;
&lt;dt&gt;&lt;strong&gt;Publish an Artifact&lt;/strong&gt;&lt;/dt&gt;&lt;dd&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;POST /v2/artifacts/{artifact_type}/{type_version}/{id}/publish&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Publishes an artifact, i.e. moves it to ACTIVE state.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;dl class="simple"&gt;
&lt;dt&gt;URL parameters:&lt;/dt&gt;&lt;dd&gt;&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;cite&gt;artifact_type&lt;/cite&gt; identifier of the artifact type, should be equal to a
valid constant defined in one of the active artifact plugins.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;cite&gt;id&lt;/cite&gt; identifier of the artifact&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;cite&gt;type_version&lt;/cite&gt; identifier defining the version of artifact type.&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;HTTP Responses:&lt;/dt&gt;&lt;dd&gt;&lt;ul&gt;
&lt;li&gt;&lt;p&gt;200 if everything went fine&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;404 if no artifact with the given ID was found or if the type of the
found artifact differs from type specified by &lt;cite&gt;artifact_type&lt;/cite&gt;
parameter (if it is not equal to generic value ‘artifacts’) or if the
found artifact is not owned by the current tenant.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;400 if the artifact draft has dependencies on missing or non-published
artifacts.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;403 if the artifact is not in the CREATING state&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Request body: None&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Response schema: [JSON with published artifact]&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;&lt;strong&gt;Get an artifact&lt;/strong&gt;&lt;/dt&gt;&lt;dd&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;GET /v2/artifacts/{artifact_type}/[{type_version}]/{id}&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Returns an artifact record with all the common and type-specific metadata&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;dl class="simple"&gt;
&lt;dt&gt;URL parameters:&lt;/dt&gt;&lt;dd&gt;&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;cite&gt;artifact_type&lt;/cite&gt; identifier of the artifact type, should be equal to a
valid constant defined in one of the active artifact plugins.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;cite&gt;id&lt;/cite&gt; identifier of the artifact&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;cite&gt;type_version&lt;/cite&gt; optional identifier defining the version of artifact
type. Unlike in other (modifying) calls in this one it can be omitted
to provide possibility to get the artifact by its type and id
regardless of type version.&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;HTTP Responses:&lt;/dt&gt;&lt;dd&gt;&lt;ul&gt;
&lt;li&gt;&lt;p&gt;200 if everything went fine&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;404 if no artifact with the given ID was found or if the type of the
found artifact differs from type specified by &lt;cite&gt;artifact_type&lt;/cite&gt;
parameter (if it is not equal to generic value ‘artifacts’) or if the
found artifact is not accessible by the current tenant.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Response schema: [JSON artifact definition, TBD]&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;&lt;strong&gt;Update an Artifact&lt;/strong&gt;&lt;/dt&gt;&lt;dd&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;PATCH /v2/artifacts/{artifact_type}/{type_version}/{id}&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Updates artifact’s metadata fields. If the artifact is in state other
than CREATING then only mutable fields may be updated.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;dl class="simple"&gt;
&lt;dt&gt;URL parameters:&lt;/dt&gt;&lt;dd&gt;&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;cite&gt;artifact_type&lt;/cite&gt; identifier of the artifact type, should be equal to a
valid constant defined in one of the active artifact plugins.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;cite&gt;id&lt;/cite&gt; identifier of the artifact&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;HTTP Responses:&lt;/dt&gt;&lt;dd&gt;&lt;ul&gt;
&lt;li&gt;&lt;p&gt;200 if everything went fine&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;404 if no artifact with the given ID was found or if the type of the
found artifact differs from type specified by &lt;cite&gt;artifact_type&lt;/cite&gt;
parameter (if it is not equal to generic value ‘artifacts’) or if the
found artifact is not owned by the current tenant.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;403 if the PATCH attempts to modify the immutable property while the
artifact’s state is other than CREATING&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Request schema:  [JSON patch, TBD]&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Response schema: [JSON artifact definition, TBD]&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/li&gt;
&lt;li&gt;&lt;dl&gt;
&lt;dt&gt;&lt;strong&gt;Delete an Artifact&lt;/strong&gt;&lt;/dt&gt;&lt;dd&gt;&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;DELETE /v2/artifacts/{artifact_type}/{type_version}/{id}&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Deletes an artifact. See &lt;em&gt;Deleting an Artifact&lt;/em&gt; for details&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;dl class="simple"&gt;
&lt;dt&gt;URL parameters:&lt;/dt&gt;&lt;dd&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;cite&gt;artifact_type&lt;/cite&gt; identifier of the artifact type, should be equal to a
valid constant defined in one of the active artifact plugins.
May also contain value equal to “artifacts”&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;cite&gt;id&lt;/cite&gt; identifier of the artifact&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;cite&gt;type_version&lt;/cite&gt; identifier defining the version of artifact type.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;HTTP Responses:&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;200 if everything went fine&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;dl class="simple"&gt;
&lt;dt&gt;404 if no artifact with the given ID was found or if the type of the&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;found artifact differs from type specified by &lt;cite&gt;artifact_type&lt;/cite&gt;
parameter (if it is not equal to generic value ‘artifacts’) or if the
found artifact is not owned by the current tenant.&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;400 if there are other artifacts which depend on the given one.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A detailed example:&lt;/p&gt;
&lt;p&gt;Let’s assume that the artifact type has several type-specific properties,
defined as follows:&lt;/p&gt;
&lt;p&gt;tags = Array(item_type=String())
dependencies = ArtifactReferenceList()
blob = BinaryObject()&lt;/p&gt;
&lt;p&gt;Sample HTTP-requests for the given artifact will be given below.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;GET /v2/artifacts/{artifact_type}/{id}&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Retrieves an artifact with type &lt;cite&gt;artifact_type&lt;/cite&gt; and id &lt;cite&gt;id&lt;/cite&gt;.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;PATCH /v2/artifacts/{artifact_type}/{type_version}/{id}
body = [{‘op’: ‘add’, ‘path’: ‘/tags/-’, ‘value’: ‘new’}]&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This request appends string ‘new’ to a &lt;cite&gt;tags&lt;/cite&gt; property.
Here &lt;cite&gt;tags&lt;/cite&gt; is not a reserved name, like in images, it is just the name chosen
for an artifact property representing an array of strings.
As this is a data-modifying request, it should include the &lt;cite&gt;type_version&lt;/cite&gt; part
of the URI to ensure that caller knows exactly which version of the artifact
schema is being targeted.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;PATCH /v2/artifacts/{artifact_type}/{type_version}/{id}
body = [{‘op’: ‘remove’, ‘path’: ‘/dependencies/0’}]&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This request removes first element from the artifact’s &lt;cite&gt;dependencies&lt;/cite&gt; property.
Mind that &lt;cite&gt;dependencies&lt;/cite&gt; is not a reserved word, but a custom
property name for a list of ArtifactReferences.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;PUT /v2/artifacts/{artifact_type}/{type_version}/{id}/blob
or
POST /v2/artifacts/{artifact_type}/{type_version}/{id}/blob&lt;/p&gt;
&lt;p&gt;content-type ‘application/octet-stream’
body = SOMEDATA&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This request uploads data specified in request’s body to BinaryObject
property &lt;cite&gt;blob&lt;/cite&gt;.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;GET /v2/artifacts/{artifact_type}/{id}/blob/download&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This request retrieves the value of BinaryObject property &lt;cite&gt;blob&lt;/cite&gt;.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;DELETE /v2/artifacts/{artifact_type}/{type_version}/{id}/files/{file_id}&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;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;The artifact types (their type-specific metadata fields and BLOB kinds) are
defined in independent python modules (plugins). This code may be provided by
third-party developers, and thus has to be inspected for potential security
problems. However, an explicit cloud operators action is required to enable
this modules (i.e. they are not user-supplied), so while the operator enables
only the trusted plugins there are no security threats.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The artifact types may define custom logic to validate the values of some of
their type-specific metadata fields. This Custom logic is part of the plugin
(i.e. cloud operator’s action is required to enable it). Thus there is no
security issue here unless the operator
enables untrusted plugin.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As this change adds a set of new APIs, a set of new policies should be added
as well to provide a role-based access to these APIs. Plugin-specific
policies may be added later. However, this spec does not include any actions
for these policies, so they have to be specified by later specs.&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;To be added later with different specifications / blueprints&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 new APIs are being added, appropriate changes to python-glanceclient and
glance CLI should be made to support this interactions.&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 APIs and data models should follow the same architecture as the
existing ones. Thus there should be now impact on performance when calling
the APIs.&lt;/p&gt;
&lt;p&gt;Long running tasks (such as artifact deletion) should be made asynchronous and
should be executed by dedicated background workers, so they will not interfere
with the API performance.
The implementation of the asynchronous task should reuse the existing delayed
delete functionality.&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 database schema changes should be made with migrations. This migrations
have to be executed prior the usage of the new functionality.&lt;/p&gt;
&lt;p&gt;Glance deployment should include adding and activating the plugins which define
artifact types.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;Existing APIs are not modified.&lt;/p&gt;
&lt;p&gt;All the artifact-related actions will be available as new API endpoints
under the /v2/ branch&lt;/p&gt;
&lt;p&gt;The existing images API will not be migrated to artifacts in v2 branch.
After artifacts are implemented and stabilized there will be an alternative
implementation of Images which will use artifacts’ semantic instead of the
current one, however this implementation will not substitute the existing one&lt;/p&gt;
&lt;p&gt;Deprecation of the current images API is beyond the scope of the current spec
and should not happen unless a separate blueprint is filed and a proper
deprecation period is announced.&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;ativelkov&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;gokrokve
mfedosin
ivasilevskaya&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="reviewers"&gt;
&lt;h3&gt;Reviewers&lt;/h3&gt;
&lt;p&gt;mfedosin
jokke
hemanth-makkapati
nikhil-komawar&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;The database layer and data migrations for Artifacts and their common
metadata properties&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The database layer and data migrations to store and manage the values of
type-specific metadata fields and blob references&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The plugin interfaces which will allow to specify artifact types and
their metadata structures.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The REST API for artifact composition, publishing, deletion and search of
artifacts, as well as retrival of their data and metadata&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Modifications to plugin interface to allow custom logic definition for
importing and exporting artifacts as a single operation&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The REST API to support import/export operations for artifacts&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The database layer and data migrations to add artifact dependency relations&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The REST API to support defining dependency relations during artifact
composition&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;delayed_delete feature: modifying the current delayed delete to support
artifact deletion.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Modifications to python-glancecleint to make use of all the new APIs.&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;No new dependencies required.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;All the new APIs should be covered by functional and integration tests with
Tempest&lt;/p&gt;
&lt;p&gt;Data migrations and database API should be covered by 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;All the new APIs, configuration options and policies should be documented.&lt;/p&gt;
&lt;p&gt;A new document - “Plugin developers guide” has to be added.&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.google.com/a/mirantis.com/document/d/1tOTsIytVWtXGUaT2Ia4V5PWq4CiTfZPDn6rpRm5In7U/edit"&gt;Initial specification draft with comments&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="http://etherpad.openstack.org/p/juno-hot-artifacts-repository-finalize-design"&gt;Summit Etherpad from Artifacts’ discussion session&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://db.tt/jsIOasiT"&gt;Artifact DB Schema&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/api-wg/blob/master/guidelines/pagination_filter_sort.rst"&gt;API Working group sorting guidelines&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
</description><pubDate>Thu, 08 Mar 2018 00:00:00 </pubDate></item><item><title>Glare API</title><link>http://specs.openstack.org/openstack/glance-specs/specs/newton/approved/glance/glare-api.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/glance/+spec/glare-api"&gt;https://blueprints.launchpad.net/glance/+spec/glare-api&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This specification describes stable API of Glance Artifact Repository
service (aka Glare) and covers all most popular use cases.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Glare needs a stable API that satisfy requirements of API-WG and DefCore.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;This specification aims to solve the described problem by complete refactoring
of Glance Artifact Repository API and changing calls to Glare service.&lt;/p&gt;
&lt;p&gt;The behavior of the servers and API calls for Glare will be changed.
To describe service behavior after refactoring in details we prepared some
glossary and list of Use Cases.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;User list&lt;/strong&gt;&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;Developer&lt;/em&gt; - person who is contributing to Glare.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;Glare&lt;/em&gt; - represents Glare service deployed within OpenStack.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;User&lt;/em&gt; - Glare user who wants to consume Glare artifacts. User should be
created in Keystone under some project and domain.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;Cloud Admin&lt;/em&gt; - person who is responsible for Glare administration and
support within OpenStack.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Glossary&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;Glare&lt;/em&gt; (from GLance Artifact REpository) - a service that provides access
to a unified catalog of immutable objects with structured meta-information as
well as related binary data (these structures are also called &lt;em&gt;‘artifacts’&lt;/em&gt;).
Glare controls artifact consistency and guaranties that binary data and
properties won’t change during artifact lifetime.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;Artifact type developer can declare properties which values may be
changed, but he has to do it explicitly, because by default all properties
are considered immutable.&lt;/p&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;Artifact&lt;/em&gt; - in terms of Glare, an Artifact is a structured immutable object
with some properties, related binary data and metadata.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;Artifact Version&lt;/em&gt; - property of artifact that defines its version in SemVer
format.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;Artifact type&lt;/em&gt; - defines artifact structure of both its binary data and
properties. Examples of OpenStack artifact types that will be supported
in Glare are: Heat templates, Murano Packages, Nova Images, Tacker VNFs and
so on.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;Artifact status&lt;/em&gt; - specifies the state of the artifact and the possible
actions that can be done with it. List of possible artifact statuses:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;queued&lt;/em&gt; - Artifact created but not activated, so it can be changed by
Artifact owner.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;active&lt;/em&gt; - Artifact activated, immutable properties cannot be changed.
Artifact available for download to other Users.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;deactivated&lt;/em&gt; - Artifact is not available to other users except
administrators, used when Cloud Admin need to check the artifact.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;deleted&lt;/em&gt; - Artifact deleted.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;&lt;strong&gt;Artifact status transition table&lt;/strong&gt;&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Artifacts Status&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;queued&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;active&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;deactivated&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;deleted&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;strong&gt;queued&lt;/strong&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;X&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;activate Artifact&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;N/A&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;delete Artifact&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;&lt;strong&gt;active&lt;/strong&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;N/A&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;X&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;de-activate Artifact&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;delete Artifact&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;&lt;strong&gt;deactivated&lt;/strong&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;N/A&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;reactivate Artifact&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;X&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;delete Artifact&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;&lt;strong&gt;deleted&lt;/strong&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;N/A&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;N/A&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;N/A&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;X&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;Artifact Property&lt;/em&gt; - property of artifact that defines some information
about Artifact. Artifact Properties always have name, type, value and
optional additional parameters, described bellow.&lt;/p&gt;
&lt;p&gt;Types are based on types from oslo.versionedobjects library. All types
are inherited from &lt;a class="reference external" href="https://github.com/openstack/oslo.versionedobjects/blob/master/oslo_versionedobjects/fields.py#L111-L128"&gt;FieldType class&lt;/a&gt;
and define custom behavior.&lt;/p&gt;
&lt;p&gt;Glare uses several primitive types from oslo.versionedobjects directly:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;String&lt;/em&gt;;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;Integer&lt;/em&gt;;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;Float&lt;/em&gt;;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;Boolean&lt;/em&gt;;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And also Glare expands this list with custom types:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;Blob&lt;/em&gt;;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;Dependency&lt;/em&gt;;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Structured generic types &lt;em&gt;Dict&lt;/em&gt; or &lt;em&gt;List&lt;/em&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Each property has additional parameters:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;required_on_activate&lt;/strong&gt; - boolean value indicating if the property value
should be specified for the artifact before activation. (Default: True)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;mutable&lt;/strong&gt; - boolean value indicating if the property value may be changed
after the artifact is activated. (Default: False)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;system&lt;/strong&gt; - boolean value indicating if the property value cannot be edited
by User. (Default: False)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;sortable&lt;/strong&gt; - boolean value indicating if there is a possibility to sort by
this property’s values. (Default: False)&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;Only properties of 4 primitive types may be sortable: integer, string, float
and boolean.&lt;/p&gt;
&lt;/div&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;default&lt;/strong&gt; - a default value for the property may be specified by the Artifact
Type. (Default: None)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;validators&lt;/strong&gt; - a list of functions or lambdas like f(self, v) -&amp;gt; Bool. When
user sets a value to the property with additional validators Glare checks them
before setting the value and raises &lt;em&gt;ValueError&lt;/em&gt; if at least one of the
requirements is not satisfied.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;filter_ops&lt;/strong&gt; - a list of available filter operators for the property. There
are seven available operators: ‘eq’, ‘neq’, ‘lt’, ‘lte’, ‘gt’, ‘gte’, ‘in’.
All of them cam be applied to primitive properties only.
Dict values can be sorted using the following syntax
“?&amp;lt;dict_name&amp;gt;.&amp;lt;key_name&amp;gt;=&amp;lt;op_name&amp;gt;:&amp;lt;value&amp;gt;.”&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;Artifact Dependency&lt;/em&gt; - property type that defines soft dependency of the
Artifact from another Artifact. It is an url that allows user to obtain
some Artifact data. For external dependency the format is the following:
&lt;em&gt;http(s)://&amp;lt;netloc&amp;gt;/&amp;lt;path&amp;gt;&lt;/em&gt;
For internal dependencies dependency contains only &amp;lt;path&amp;gt;.
Example of &amp;lt;path&amp;gt;:
/artifacts/&amp;lt;artifact_type&amp;gt;/&amp;lt;artifact identifier&amp;gt;.
User can use filters and page_limits in path to define dynamic dependencies.
All that Glare will do is request GET with dependency to receive Artifact
info.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;Artifact Blob&lt;/em&gt; - property type that defines binary data for Artifact.
User can download Artifact blob from Glare. Each blob property has a flag
&lt;em&gt;external&lt;/em&gt;, that indicates if the property was created during file upload
(False) or by direct user request (True). In other words, “external” means
that blob property url is just a reference to some external file and Glare
does not manage the blob operations in that case.
Json schema that defines blob format:&lt;/p&gt;
&lt;div class="highlight-javascript 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;"type"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"object"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s2"&gt;"properties"&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;"size"&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;"type"&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="s2"&gt;"number"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"null"&lt;/span&gt;&lt;span class="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;"checksum"&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;"type"&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="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="s2"&gt;"null"&lt;/span&gt;&lt;span class="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;"external"&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;"type"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"boolean"&lt;/span&gt;
&lt;span class="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;"status"&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;"type"&lt;/span&gt;&lt;span class="o"&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="s2"&gt;"enum"&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="s2"&gt;"saving"&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="s2"&gt;"pending_delete"&lt;/span&gt;&lt;span class="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="s2"&gt;"required"&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="s2"&gt;"size"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"checksum"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"external"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"status"&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;Artifact blob properties may have the following statuses:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;saving&lt;/em&gt; - Artifact blob record created in table, blob upload started.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;active&lt;/em&gt; - blob upload successfully finished.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;pending_delete&lt;/em&gt; - indicates that blob will be deleted soon by Scrubber
(if delayed delete is enabled) or by Glare itself.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;table class="docutils align-default" id="id2"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;&lt;strong&gt;Blob status transition table&lt;/strong&gt;&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Blob Status&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;saving&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;active&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;pending delete&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;strong&gt;saving&lt;/strong&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;X&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;finish blob upload&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;request for artifact delete&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;&lt;strong&gt;active&lt;/strong&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;N/A&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;X&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;request for artifact delete&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;&lt;strong&gt;pending_delete&lt;/strong&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;N/A&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;N/A&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;X&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;Artifact Dict and List&lt;/em&gt; - compound generic property types that
implement Dict or List interfaces respectively, and contain values of some
primitive type, defined by &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;element_type&lt;/span&gt;&lt;/code&gt; attribute.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;Artifact visibility&lt;/em&gt; - defines who may have an access to active artifact.
Initially there are 2 options: ‘private’ artifact is accessible by its owner and
admin only and ‘public’, when all users have an access to the artifact by default.
When artifact is ‘queued’ its visibility is ‘private’. It’s allowed to change
visibility only when artifact has ‘active’ status.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;Artifact locking&lt;/em&gt; - when artifact is &lt;em&gt;queued&lt;/em&gt; all its properties
are editable, but when it becomes &lt;em&gt;active&lt;/em&gt; it is “locked” and cannot be modified
(except for those properties explicitly declared as mutable).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Use Case list&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Use Case 1.&lt;/strong&gt; Add Artifact type.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Pre-condition:&lt;/em&gt; None.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Success condition:&lt;/em&gt; New Artifact type has been added to Glare and it can be
used by other OS users.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Steps:&lt;/em&gt;&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Operator adds Artifact type class to ‘glare/objects’ folder.&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;Artifact types are pre-published in Glance repository. All of
them will be reviewed and committed by Glance developers and reviewers.&lt;/p&gt;
&lt;/div&gt;
&lt;ol class="arabic simple" start="2"&gt;
&lt;li&gt;&lt;p&gt;Operator implements all abstract methods and defines data API.&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;We are using image data API for image artifact type and common
unified data API for other artifacts.&lt;/p&gt;
&lt;/div&gt;
&lt;ol class="arabic simple" start="3"&gt;
&lt;li&gt;&lt;p&gt;Operator regenerates (with oslo config generator) or updates Glare
configuration file to enable new Artifact type.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Operator restarts Glare service, Glare validates new Artifact type.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;em&gt;Alternative scenarios:&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;4A. Artifact type validation failed - Glare won’t start.&lt;/p&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Use Case 2.&lt;/strong&gt; Update Artifact type.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Pre-condition:&lt;/em&gt; Artifact type supported by Glare
(Artifact type class has been implemented).&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;&lt;em&gt;Success condition:&lt;/em&gt; Artifact type definition has been updated in Glare&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;and it can be used by other OpenStack users. Old artifacts (that existed
before update) are available to OpenStack users.&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;&lt;em&gt;Steps:&lt;/em&gt;&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Operator adds new field or update field in Artifact type class.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Operator updates artifact type class (bump version) to cover support
compatibility between database and new changes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Operator re-generates or updates Glare configuration file (if needed).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Operator restarts Glare service, Glare validates updated Artifact type.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;em&gt;Alternative scenarios:&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;4A. Artifact type validation failed - Glare won’t start.&lt;/p&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Use Case 3.&lt;/strong&gt; Disable artifact type.&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;&lt;em&gt;Pre-condition&lt;/em&gt;: Artifact type supported by Glare (Artifact type class has&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;been implemented).&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;em&gt;Success condition&lt;/em&gt;: Artifact type definition has been updated in Glare and&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;it can be used by other .&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;&lt;em&gt;Steps:&lt;/em&gt;&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Operator deletes artifact type name from Glare configuration file.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Operator restarts Glare.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;em&gt;Alternative scenarios:&lt;/em&gt;&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;None.&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;Artifacts of disabled artifact type will be presented in database
and all data will be in storage, but users won’t be able to access
those artifacts with Glare API.&lt;/p&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Use Case 4.&lt;/strong&gt; List artifact types.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Pre-condition:&lt;/em&gt; Running Glare API.&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;&lt;em&gt;Success condition:&lt;/em&gt; List of Artifact type definitions provided in that&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;deployment to User.&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;&lt;em&gt;Steps:&lt;/em&gt;&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;User requests list of supported Artifact types (GET /schemas).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Glare checks Glare configuration, artifact type classes and generates
JSON representation of artifact type.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Glare returns the representation to the user (200 OK).&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;em&gt;Alternative scenarios:&lt;/em&gt;&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;None.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Use Case 5.&lt;/strong&gt; Get artifact type info.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Pre-condition:&lt;/em&gt; Running Glare API.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Success condition:&lt;/em&gt; Artifact type definition provided to User&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Steps:&lt;/em&gt;&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;User requests Artifact type info
(GET /schemas/{artifact_type}).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Glare checks glare configuration, artifact type class and generates
JSON schema&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Glare returns JSON schema to the user (200 OK).&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;em&gt;Alternative scenarios:&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;2A. No Artifact type found with requested name (404 Not Found)&lt;/p&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Use Case 6.&lt;/strong&gt; Create artifact.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;No blob upload here. Only creating an Artifact entity in DB.&lt;/p&gt;
&lt;/div&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;&lt;em&gt;Pre-conditions:&lt;/em&gt;&lt;/dt&gt;&lt;dd&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Artifact type definition has been added to Glare.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Artifact type is active in Glare.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;User has a permission to create artifact.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;&lt;em&gt;Success condition:&lt;/em&gt; Artifact entity has been created in Glare DB.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Steps:&lt;/em&gt;&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;User defines Artifact allowed properties and requests for Artifact
creation (POST /artifacts/{artifact_type}).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Glare checks Artifact the possibility of artifact creation.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Glare creates Artifact entity in DB (only record in DB).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Glare returns metadata of created artifact (201 Created).&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;em&gt;Alternative scenarios:&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;2A. Property value is incorrect (400 Bad Request)&lt;/p&gt;
&lt;p&gt;2B. Property with name doesn’t exist (400 Bad Request)&lt;/p&gt;
&lt;p&gt;2C. Dependency format is incorrect (400 Bad Request)&lt;/p&gt;
&lt;p&gt;2D. Property is system (403 Forbidden)&lt;/p&gt;
&lt;p&gt;2E. Artifact type is not found (404 Not Found)&lt;/p&gt;
&lt;p&gt;2F. Artifact with required name and version already exists for
this user (409 Conflict)&lt;/p&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Use Case 7.&lt;/strong&gt; Upload Artifact binary data.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Pre-conditions:&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Artifact type definition has been added to Glare.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Artifact type is active in Glare.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Artifact instance has been successfully created.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;User has enough quota space.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Artifact has ‘queued’ status.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;&lt;em&gt;Success condition:&lt;/em&gt; Data is uploaded in storage, Artifact blob has been&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;successfully crated and has status ‘active’.&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;&lt;em&gt;Steps:&lt;/em&gt;&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;User specifies Artifact identifier, blob property name, blob binary data,
content-type as &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;application/octet-stream&lt;/span&gt;&lt;/code&gt; and request upload
(PUT /artifacts/{artifact_type}/{artifacts_id}/{blob_name}).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Glare checks if Artifact identifier and blob property is valid.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Glare creates a blob record in db, changes its status to ‘saving’ and
associates the record with related Artifact blob property.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Glare uploads blob binary to store back end.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Glare sets all required metadata (‘size’, ‘checksum’ and so on) to the
blob and changes its status to ‘active’.&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;Glare doesn’t use registry service, so do not need trusts here.&lt;/p&gt;
&lt;/div&gt;
&lt;ol class="arabic simple" start="6"&gt;
&lt;li&gt;&lt;p&gt;Glare responds with 200 OK.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;em&gt;Alternative scenarios:&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;2A. No artifact found (404 Not Found).&lt;/p&gt;
&lt;p&gt;2B. No blob property found (400 Bad Request).&lt;/p&gt;
&lt;p&gt;2C. Metadata is not valid (400 Bad Request).&lt;/p&gt;
&lt;p&gt;3C. Blob is already uploaded and has status ‘active’ (409 Conflict)&lt;/p&gt;
&lt;p&gt;3D. Blob is saving (409 Conflict).&lt;/p&gt;
&lt;p&gt;4A. Artifact quota per tenant exceed (413 HTTPRequestEntityTooLarge).&lt;/p&gt;
&lt;p&gt;4B. Blob upload failed. Glare initiates Blob killing and responds with
appropriate error (depends on backend error).&lt;/p&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Use Case 8.&lt;/strong&gt; Add a custom location for artifact.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Pre-conditions:&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Artifact type definition has been added to Glare.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Artifact type is active in Glare.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Artifact instance has been successfully created.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Artifact has ‘queued’ status.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;&lt;em&gt;Success condition:&lt;/em&gt; blob location has been successfully added to Artifact.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Steps:&lt;/em&gt;&lt;/p&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;&lt;p&gt;User specifies Artifact identifier, blob property name, location,
content-type as &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;application/json&lt;/span&gt;&lt;/code&gt; and sends the request
(PUT /artifacts/{artifact_type}/{artifacts_id}/{blob_name}).&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Body:&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;div class="highlight-javascript 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;"url"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;some_url&amp;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;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Glare checks if Artifact identifier and blob property name is valid.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Glare checks given location, creates blob record in db, associate it
with Artifact and adds location to blob.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Glare changes blob property status to active.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Glare responds with 200 OK.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;em&gt;Alternative scenarios:&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;2A. No artifact found (404 Not Found).&lt;/p&gt;
&lt;p&gt;2B. No property found (400 Bad Request).&lt;/p&gt;
&lt;p&gt;3A. Location url is not valid (400 Bad Request).&lt;/p&gt;
&lt;p&gt;3B. Location url is not downloadable (400 Bad Request).&lt;/p&gt;
&lt;p&gt;3C. Blob record is already exists (409 Conflict).&lt;/p&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Use Case 9.&lt;/strong&gt; Activate Artifact.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Pre-conditions:&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Artifact type definition has been added to Glare.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Artifact type is active in Glare.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Artifact instance has been successfully created.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Success condition:* Artifact is activated in Glare (status is ‘active’).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;Steps:&lt;/em&gt;&lt;/p&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;&lt;p&gt;User defines Artifact id and requests Artifact activation
(PATCH /artifacts/{artifact_type}/{artifacts_id}).&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Body:&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;div class="highlight-javascript 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;"op"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"replace"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s2"&gt;"path"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&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;"value"&lt;/span&gt;&lt;span class="o"&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;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Glare checks if all required Artifact properties specified according
to Artifact definition.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Glare checks if all required blob properties are active according
to Artifact definition.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Glare checks if all Artifact dependencies are correct.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Glare activates Artifact so it becomes visible to other Users and
returns response (200 OK).&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;em&gt;Alternative scenarios:&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;2-4A. some obligatory properties or blobs were not specified, dependencies
are not correct (no dependency found by url or there are multiple
artifacts per dependency) (400 Bad Request).&lt;/p&gt;
&lt;p&gt;2B. Artifact doesn’t exist or deleted (404 Not Found).&lt;/p&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Use Case 10A.&lt;/strong&gt; Update Artifact non-blob property, Artifact is queued.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Pre-conditions:&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Artifact type definition has been added to Glare.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Artifact type is active in Glare.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Artifact instance has been successfully created.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;&lt;em&gt;Success condition:&lt;/em&gt; Artifact property has been updated in Glare.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Steps:&lt;/em&gt;&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;User requests for Artifact property, blob property or dependency update
(PATCH /artifacts/{artifact_type}/{artifacts_id}).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Glare updates required properties and returns updated artifact (200 OK).&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;em&gt;Alternative scenarios:&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;2A. Dependency url is not correct or downloadable (400 Bad Request).&lt;/p&gt;
&lt;p&gt;2B. Artifact doesn’t exist or deleted (404 Not Found).&lt;/p&gt;
&lt;p&gt;2C. Parameter is incorrect (400 Bad Request).&lt;/p&gt;
&lt;p&gt;2D. Property is system (403 Forbidden).&lt;/p&gt;
&lt;p&gt;2E. Artifact with updated name and version already exists for
this user (409 Conflict).&lt;/p&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Use Case 10B.&lt;/strong&gt; Update Artifact non-blob property, Artifact is active.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Pre-conditions:&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Artifact type definition has been added to Glare.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Artifact type is active in Glare.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Artifact instance has been successfully created.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;&lt;em&gt;Success condition:&lt;/em&gt; Artifact has been updated in Glare.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Steps:&lt;/em&gt;&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;User requests for Artifact property or dependency update
(PATCH /artifacts/{artifact_type}/{artifacts_id}).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Glare checks if dependency is mutable and can be updated.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Glare checks if property is mutable and can be updated.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Glare updates required properties (200 OK).&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;em&gt;Alternative scenarios:&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;2A. Dependency property is immutable (403 Forbidden).&lt;/p&gt;
&lt;p&gt;2B. Dependency url is not correct or downloadable (400 Bad Request).&lt;/p&gt;
&lt;p&gt;3A. Property is immutable (403 Forbidden).&lt;/p&gt;
&lt;p&gt;3B. Parameter is incorrect (400 Bad Request).&lt;/p&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Use Case 11.&lt;/strong&gt; Download blob.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Pre-conditions:&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Artifact type definition has been added to Glare.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Artifact type is active in Glare.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Artifact instance has been successfully created.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;&lt;em&gt;Success condition:&lt;/em&gt; Blob is downloaded.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Steps:&lt;/em&gt;&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;User provides blob property name and Artifact identifier
(GET /artifacts/{artifact_type}/{artifacts_id}/{blob_name}).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Glare provides Artifact binary stream to the User (200 OK).&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;em&gt;Alternative scenarios:&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;2A. Artifact blob contains no data (204 No Content).&lt;/p&gt;
&lt;p&gt;2B. Artifact blob has status ‘saving’ (204 No content).&lt;/p&gt;
&lt;p&gt;2C. Download is not successful (depends on backend error).&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;2D. Artifact is deactivated and user doesn’t have a permission&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;to download (403 Forbidden)&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Use Case 12.&lt;/strong&gt; Get Artifact info&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Pre-conditions:&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Artifact type definition has been added to Glare.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Artifact type is active in Glare.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Artifact instance has been successfully created.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;&lt;em&gt;Success condition:&lt;/em&gt; Artifact definition returned to User.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Steps:&lt;/em&gt;&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;User requests for Artifact info with artifact identifier and artifact type
(GET /artifacts/{artifact_type}/{artifacts_id}).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Glare returns Artifact properties, blobs information and dependency
information (200 OK).&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;em&gt;Alternative scenarios:&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;2A. No grants to view artifacts (403 Forbidden).&lt;/p&gt;
&lt;p&gt;2B. No artifact or artifact type found (404 Not Found).&lt;/p&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Use Case 13.&lt;/strong&gt; Deactivate Artifact.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Pre-conditions:&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Artifact type definition has been added to Glare.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Artifact type is active in Glare.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Artifact instance has been successfully created.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;&lt;em&gt;Success condition:&lt;/em&gt; Artifact status is deactivated.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Steps:&lt;/em&gt;&lt;/p&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;&lt;p&gt;User sends a request to deactivate artifact
(PATCH /artifacts/{artifact_type}/{artifacts_id}).&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Body:&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;div class="highlight-javascript 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;"op"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"replace"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s2"&gt;"path"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&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;"value"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"deactivated"&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;/li&gt;
&lt;/ul&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;access to the deactivation is managed by oslo policy.&lt;/p&gt;
&lt;/div&gt;
&lt;ol class="arabic simple" start="2"&gt;
&lt;li&gt;&lt;p&gt;Glare changes status of artifact from active to deactivated (200 OK).&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;current dependencies are soft dependencies. So no integrity check
between artifacts here.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;&lt;em&gt;Alternative scenarios:&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;2A. Artifact status is not active (400 Bad Request).&lt;/p&gt;
&lt;p&gt;2B. User doesn’t have permission to deactivate artifact (403 Forbidden).&lt;/p&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Use Case 14.&lt;/strong&gt; Reactivate Artifact.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Pre-conditions:&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Artifact type definition has been added to Glare.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Artifact type is active in Glare.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Artifact instance has been successfully created.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;&lt;em&gt;Success condition:&lt;/em&gt; Artifact is active.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Steps:&lt;/em&gt;&lt;/p&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;&lt;p&gt;User sends a request to re-activate Artifact
(PATCH /artifacts/{artifact_type}/{artifacts_id}).&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Body:&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;div class="highlight-javascript 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;"op"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"replace"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s2"&gt;"path"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&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;"value"&lt;/span&gt;&lt;span class="o"&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;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;/li&gt;
&lt;/ul&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;access to the deactivation is managed by oslo policy.&lt;/p&gt;
&lt;/div&gt;
&lt;ol class="arabic simple" start="2"&gt;
&lt;li&gt;&lt;p&gt;Glare changes status of Artifact from deactivated to active
(200 OK).&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;em&gt;Alternative scenarios:&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;2A. Artifact status is not deactivated (400 Bad Request).&lt;/p&gt;
&lt;p&gt;2B. User doesn’t have permission to reactivate artifact (403 Forbidden).&lt;/p&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Use Case 15.&lt;/strong&gt; Publish Artifact.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Pre-conditions:&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Artifact type definition has been added to Glare.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Artifact type is active in Glare.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Artifact instance has been successfully created.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Artifact status is ‘active’.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;&lt;em&gt;Success condition:&lt;/em&gt; Artifact is published (i.e. artifact visibility is
&lt;em&gt;public&lt;/em&gt;).&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Steps:&lt;/em&gt;&lt;/p&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;&lt;p&gt;User sends a request to publish Artifact
(PATCH /artifacts/{artifact_type}/{artifacts_id})&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Body:&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;div class="highlight-javascript 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;"op"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"replace"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s2"&gt;"path"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/visibility"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s2"&gt;"value"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"public"&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;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Glare changes visibility of Artifact from ‘private’ to ‘public’
(200 OK).&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;em&gt;Alternative scenarios:&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;2A. Artifact status is not ‘active’ (400 Bad Request).&lt;/p&gt;
&lt;p&gt;2B. User doesn’t have permission to publish artifact (403 Forbidden).&lt;/p&gt;
&lt;p&gt;2C. Public artifact with required name and version already exists
(409 Conflict).&lt;/p&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Use Case 16.&lt;/strong&gt; List Artifacts.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Pre-conditions:&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Artifact type definition has been added to Glare.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Artifact type is active in Glare.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;&lt;em&gt;Success condition:&lt;/em&gt; List of artifacts returned to User.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Steps:&lt;/em&gt;&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;User request for Artifact list with specified artifact type, limit,
marker, filters (GET /artifacts/{artifact_type}).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Glare returns all Artifacts to the User (200 OK).&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;em&gt;Alternative scenarios:&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;2A. Number of Artifacts is too large (400 Bad Request)
(use limit to restrict number of Artifacts in response).&lt;/p&gt;
&lt;p&gt;2B. Query params is invalid (sorting or filtering by non-existing key)
(400 Bad Request).&lt;/p&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Use Case 17.&lt;/strong&gt; Delete artifact.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Pre-conditions:&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Artifact type definition has been added to Glare.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Artifact type is active in Glare.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Artifact instance has been successfully created.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;&lt;em&gt;Success condition:&lt;/em&gt; Artifact has been successfully deleted from Glare.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Steps:&lt;/em&gt;&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;User requests Artifact delete with Artifact type and Artifact identifier
(DELETE /artifacts/{artifact_type}/{artifacts_id}).&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;2. Glare updates artifact status to ‘deleted’ and set all artifact’s blobs
statuses to ‘pending_delete’.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;no dependency consistency check here.&lt;/p&gt;
&lt;/div&gt;
&lt;ol class="arabic simple" start="3"&gt;
&lt;li&gt;&lt;p&gt;Glare deletes all artifact’s custom properties and tags.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;4. Glare sequentially deletes blob data from store and removes blob instances
from db.&lt;/p&gt;
&lt;ol class="arabic simple" start="5"&gt;
&lt;li&gt;&lt;p&gt;Glare responds 204 No Content.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;em&gt;Alternative scenarios:&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;2A. Some blob is uploading. Glare finishes uploading of the blob and
deletes it immediately.&lt;/p&gt;
&lt;p&gt;2B. Some blob is downloading. It depends on the store backend, in common
case downloading will be canceled.&lt;/p&gt;
&lt;p&gt;4A. There was a storage error during blob deleting. Glare stops blob deleting,
user have to remove them from Store with Scrubber.&lt;/p&gt;
&lt;p&gt;4B. ‘delayed_delete’ config option is enabled. Glare does nothing and returns
204 No Content. Blob data should be removed later with Scrubber.&lt;/p&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Use Case 18.&lt;/strong&gt; Add Artifact tag.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Pre-conditions:&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Artifact type definition has been added to Glare.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Artifact type is active in Glare.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Artifact has been successfully created.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;&lt;em&gt;Success condition:&lt;/em&gt; Artifact tag has been successfully added to Artifact.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Steps:&lt;/em&gt;&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;User specifies tag name and Artifact identifier and sends request.
(PUT /artifacts/{artifact_type}/{artifacts_id}/tags/{tag_value})&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Glare adds tag to the Artifact (200 OK).&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;em&gt;Alternative scenarios:&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;2A. Tag is already exist (200 OK).&lt;/p&gt;
&lt;p&gt;2B. Artifact does not exist (404 Not Found).&lt;/p&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Use Case 19.&lt;/strong&gt; Delete Artifact tag.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Pre-conditions:&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Artifact type definition has been added to Glare.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Artifact type is active in Glare.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Artifact has been successfully created.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;&lt;em&gt;Success condition:&lt;/em&gt; Artifact tag has been successfully removed
from Artifact.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Steps:&lt;/em&gt;&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;User specifies tag name and Artifact identifier and sends request.
(DELETE /artifacts/{artifact_type}/{artifacts_id}/tags/{tag_value}).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Glare removes tag from Artifact (204 No Content).&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;em&gt;Alternative scenario:&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;2A. Tag or Artifact does not exist (404 Not Found).&lt;/p&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;We need to address API-WG and DefCore comments anyway, so there are no
alternatives 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;No data model impact.&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 API calls are placed under the &lt;em&gt;/artifacts/{artifact_type}&lt;/em&gt; branch,
where artifact_type is a constant defined by the Artifact Type, which
usually should be plural of the artifact type name. For example, for
artifacts of type “template” this constant should be called ‘templates’,
so the API endpoints will start with &lt;em&gt;/artifacts/templates&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Glare API complies with OpenStack API-WG guidelines:&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://github.com/openstack/api-wg/blob/master/guidelines/pagination_filter_sort.rst"&gt;Filtering, sorting and pagination&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://specs.openstack.org/openstack/api-wg/guidelines/tags.html"&gt;Tags&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/api-wg/guidelines/errors.html"&gt;Errors&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;For updating artifact properties Glare API uses &lt;a class="reference external" href="http://jsonpatch.com/"&gt;json-patch&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Glare supports microversions to define what API version it should use:
&lt;a class="reference external" href="http://specs.openstack.org/openstack/api-wg/guidelines/microversion_specification.html"&gt;API-WG microversion guidelines&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Info&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;list of available API versions&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;GET /&lt;/p&gt;
&lt;p&gt;Returns json representation of the minimum and maximum API versions.
Code 200 OK&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;list of available artifact types schemas&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;GET /schemas&lt;/p&gt;
&lt;p&gt;Returns json representation of all active artifact types. Code 200 OK&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;description of artifact type&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;GET /schemas/{artifact_type}&lt;/p&gt;
&lt;p&gt;Returns json schema of given artifact type. Code 200 OK&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;Artifacts&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;list of artifacts with given type name&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;GET /artifacts/{artifact_type}&lt;/p&gt;
&lt;p&gt;Returns json representation of list of artifacts. Code 200 OK.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;These requests support query parameters that comply with
&lt;a class="reference external" href="https://github.com/openstack/api-wg/blob/master/guidelines/pagination_filter_sort.rst"&gt;API-WG filtering, sorting and pagination guidelines&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;create an artifact of the given type name&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;POST /artifacts/{artifact_type}&lt;/p&gt;
&lt;p&gt;Returns info about created instance in json format. Code 201 Created.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;show artifact&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;GET /artifacts/{artifact_type}/{artifacts_id}&lt;/p&gt;
&lt;p&gt;Returns info about artifact with given ID in json format. Code 200 OK.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;update artifact&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;PATCH /artifacts/{artifact_type}/{artifacts_id}&lt;/p&gt;
&lt;p&gt;Returns updated artifact info in json format. Code 200 OK.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;delete artifact&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;DELETE /artifacts/{artifact_type}/{artifacts_id}&lt;/p&gt;
&lt;p&gt;Code 204 No Content.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;Blobs&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;upload file to artifact&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;PUT /artifacts/{artifact_type}/{artifacts_id}/{blob_name}&lt;/p&gt;
&lt;p&gt;Code 200 OK.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;download file from artifact&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;GET /artifacts/{artifact_type}/{artifacts_id}/{blob_name}&lt;/p&gt;
&lt;p&gt;Returns binary stream of requested blob. Code 200 OK&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;Tags&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;These requests comply with &lt;a class="reference external" href="https://specs.openstack.org/openstack/api-wg/guidelines/tags.html"&gt;API-WG tags guidelines&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;add a tag to artifact&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;PUT /artifacts/{artifact_type}/{artifacts_id}/tags/{tag_name}&lt;/p&gt;
&lt;p&gt;Code 200 OK.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;remove a tag from artifact&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;DELETE /artifacts/{artifact_type}/{artifacts_id}/tags/{tag_name}&lt;/p&gt;
&lt;p&gt;Code 200 OK.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;delete all tags from artifact&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;DELETE /artifacts/{artifact_type}/{artifacts_id}/tags&lt;/p&gt;
&lt;p&gt;Code 204 No Content.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;replace list of tags for artifact&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;PUT /artifacts/{artifact_type}/{artifacts_id}/tags&lt;/p&gt;
&lt;p&gt;Code 200 OK.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;get list of tags for artifact&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;GET /artifacts/{artifact_type}/{artifacts_id}/tags&lt;/p&gt;
&lt;p&gt;Code 200 OK.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;Examples of API requests&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;For example, we have an artifact type ‘example_type’ with properties:&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;id: StringField&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;name: StringField&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;visibility: StringField&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;status: StringField&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;blob_file: BlobField&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;metadata: DictOfStringsField&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;version:  VersionField&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Create artifact&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;Request:&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Method: POST&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;URL: &lt;a class="reference external" href="http://host:port/artifacts/example_type"&gt;http://host:port/artifacts/example_type&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Body:&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;div class="highlight-javascript 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;"name"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"new_art"&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;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;Response:&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;201 Created&lt;/p&gt;
&lt;div class="highlight-javascript 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;"status"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"queued"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="s2"&gt;"name"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"new_art"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="s2"&gt;"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;"art_id1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="s2"&gt;"version"&lt;/span&gt;&lt;span class="o"&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="s2"&gt;"blob_file"&lt;/span&gt;&lt;span class="o"&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="s2"&gt;"metadata"&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;"visibility"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"private"&lt;/span&gt;
&lt;span class="w"&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;/div&gt;&lt;/blockquote&gt;
&lt;ol class="arabic simple" start="2"&gt;
&lt;li&gt;&lt;p&gt;Get artifact&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;Request:&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Method: GET&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;URL: &lt;a class="reference external" href="http://host:port/artifacts/example_type/art_id1"&gt;http://host:port/artifacts/example_type/art_id1&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;Response:&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;200 OK&lt;/p&gt;
&lt;div class="highlight-javascript 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;"status"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"queued"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s2"&gt;"name"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"new_art"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s2"&gt;"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;"art_id1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s2"&gt;"version"&lt;/span&gt;&lt;span class="o"&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="s2"&gt;"blob_file"&lt;/span&gt;&lt;span class="o"&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="s2"&gt;"metadata"&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;"visibility"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"private"&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;/div&gt;&lt;/blockquote&gt;
&lt;ol class="arabic simple" start="3"&gt;
&lt;li&gt;&lt;p&gt;List artifacts&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;Request:&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Method: GET&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;URL: &lt;a class="reference external" href="http://host:port/artifacts/example_type"&gt;http://host:port/artifacts/example_type&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;Response:&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;200 OK&lt;/p&gt;
&lt;div class="highlight-javascript 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;"example_type"&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;"status"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"queued"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="s2"&gt;"name"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"new_art"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="s2"&gt;"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;"art_id1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="s2"&gt;"version"&lt;/span&gt;&lt;span class="o"&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="s2"&gt;"blob_file"&lt;/span&gt;&lt;span class="o"&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="s2"&gt;"metadata"&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;"visibility"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"private"&lt;/span&gt;
&lt;span class="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="s2"&gt;"status"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"queued"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="s2"&gt;"name"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"old_art"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="s2"&gt;"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;"art_id2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="s2"&gt;"version"&lt;/span&gt;&lt;span class="o"&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="s2"&gt;"blob_file"&lt;/span&gt;&lt;span class="o"&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="s2"&gt;"metadata"&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;"visibility"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"private"&lt;/span&gt;
&lt;span class="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="s2"&gt;"status"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"queued"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="s2"&gt;"name"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"old_art"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="s2"&gt;"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;"art_id3"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="s2"&gt;"version"&lt;/span&gt;&lt;span class="o"&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="s2"&gt;"blob_file"&lt;/span&gt;&lt;span class="o"&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="s2"&gt;"metadata"&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;"visibility"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"private"&lt;/span&gt;
&lt;span class="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;"first"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/artifacts/example_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;"schema"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/schemas/example_type"&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;Request:&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Method: GET&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;URL: &lt;a class="reference external" href="http://host:port/artifacts/example_type?name=eq:old_art"&gt;http://host:port/artifacts/example_type?name=eq:old_art&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;Response:&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;200 OK&lt;/p&gt;
&lt;div class="highlight-javascript 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;"example_type"&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;"status"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"queued"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="s2"&gt;"name"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"old_art"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="s2"&gt;"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;"art_id2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="s2"&gt;"version"&lt;/span&gt;&lt;span class="o"&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="s2"&gt;"blob_file"&lt;/span&gt;&lt;span class="o"&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="s2"&gt;"metadata"&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;"visibility"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"private"&lt;/span&gt;
&lt;span class="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="s2"&gt;"status"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"queued"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="s2"&gt;"name"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"old_art"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="s2"&gt;"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;"art_id3"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="s2"&gt;"version"&lt;/span&gt;&lt;span class="o"&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="s2"&gt;"blob_file"&lt;/span&gt;&lt;span class="o"&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="s2"&gt;"metadata"&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;"visibility"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"private"&lt;/span&gt;
&lt;span class="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;"first"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/artifacts/example_type?name=ne%3Anew_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;"schema"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/schemas/example_type"&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;/div&gt;&lt;/blockquote&gt;
&lt;ol class="arabic simple" start="4"&gt;
&lt;li&gt;&lt;p&gt;Update artifact&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;Request:&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Method: PATCH&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;URL: &lt;a class="reference external" href="http://host:port/artifacts/example_type/art_id1"&gt;http://host:port/artifacts/example_type/art_id1&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Body:&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;div class="highlight-javascript 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;"op"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"replace"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s2"&gt;"path"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/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;"value"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"stark"&lt;/span&gt;
&lt;span class="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;"op"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"add"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s2"&gt;"path"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/metadata/slogan"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s2"&gt;"value"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"winter is coming"&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;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;Response:&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;200 OK&lt;/p&gt;
&lt;div class="highlight-javascript 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;"status"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"queued"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s2"&gt;"name"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"stark"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s2"&gt;"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;"art_id1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s2"&gt;"version"&lt;/span&gt;&lt;span class="o"&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="s2"&gt;"blob_file"&lt;/span&gt;&lt;span class="o"&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="s2"&gt;"metadata"&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;"slogan"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"winter is coming"&lt;/span&gt;
&lt;span class="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;"visibility"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"private"&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;/div&gt;&lt;/blockquote&gt;
&lt;ol class="arabic simple" start="5"&gt;
&lt;li&gt;&lt;p&gt;Upload blob&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;Request:&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Method: PUT&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;URL: &lt;a class="reference external" href="http://host:port/artifacts/example_type/art_id1/blob_file"&gt;http://host:port/artifacts/example_type/art_id1/blob_file&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Body:&lt;/p&gt;
&lt;p&gt;What Is Dead May Never Die&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;Response:&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;200 OK&lt;/p&gt;
&lt;div class="highlight-javascript 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;"status"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"queued"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s2"&gt;"name"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"stark"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s2"&gt;"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;"art_id1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s2"&gt;"version"&lt;/span&gt;&lt;span class="o"&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="s2"&gt;"metadata"&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;"slogan"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"winter is coming"&lt;/span&gt;
&lt;span class="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;"blob_file"&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;"status"&lt;/span&gt;&lt;span class="o"&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="s2"&gt;"checksum"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"8452e47f27b9618152a2b172357a547d"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="s2"&gt;"external"&lt;/span&gt;&lt;span class="o"&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="s2"&gt;"size"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;16&lt;/span&gt;
&lt;span class="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;"visibility"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"private"&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;/div&gt;&lt;/blockquote&gt;
&lt;ol class="arabic simple" start="6"&gt;
&lt;li&gt;&lt;p&gt;Download blob&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;Request:&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Method: GET&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;URL: &lt;a class="reference external" href="http://host:port/artifacts/example_type/art_id1/blob_file"&gt;http://host:port/artifacts/example_type/art_id1/blob_file&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;Response:&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;200 OK&lt;/p&gt;
&lt;p&gt;What Is Dead May Never Die&lt;/p&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;ol class="arabic simple" start="7"&gt;
&lt;li&gt;&lt;p&gt;Activate artifact&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;Request:&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Method: PATCH&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;URL: &lt;a class="reference external" href="http://host:port/artifacts/example_type/art_id1"&gt;http://host:port/artifacts/example_type/art_id1&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Body:&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;div class="highlight-javascript 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;"op"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"replace"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s2"&gt;"path"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&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;"value"&lt;/span&gt;&lt;span class="o"&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;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;Response:&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;200 OK&lt;/p&gt;
&lt;div class="highlight-javascript 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;"status"&lt;/span&gt;&lt;span class="o"&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="s2"&gt;"name"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"stark"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s2"&gt;"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;"art_id1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s2"&gt;"version"&lt;/span&gt;&lt;span class="o"&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="s2"&gt;"metadata"&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;"slogan"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"winter is coming"&lt;/span&gt;
&lt;span class="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;"blob_file"&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;"status"&lt;/span&gt;&lt;span class="o"&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="s2"&gt;"checksum"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"8452e47f27b9618152a2b172357a547d"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="s2"&gt;"external"&lt;/span&gt;&lt;span class="o"&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="s2"&gt;"size"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;16&lt;/span&gt;
&lt;span class="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;"visibility"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"private"&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;/div&gt;&lt;/blockquote&gt;
&lt;ol class="arabic simple" start="8"&gt;
&lt;li&gt;&lt;p&gt;Deactivate artifact&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;Request:&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Method: PATCH&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;URL: &lt;a class="reference external" href="http://host:port/artifacts/example_type/art_id1"&gt;http://host:port/artifacts/example_type/art_id1&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Body:&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;div class="highlight-javascript 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;"op"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"replace"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s2"&gt;"path"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&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;"value"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"deactivated"&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;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;Response:&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;200 OK&lt;/p&gt;
&lt;div class="highlight-javascript 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;"status"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"deactivated"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s2"&gt;"name"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"stark"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s2"&gt;"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;"art_id1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s2"&gt;"version"&lt;/span&gt;&lt;span class="o"&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="s2"&gt;"metadata"&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;"slogan"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"winter is coming"&lt;/span&gt;
&lt;span class="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;"blob_file"&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;"status"&lt;/span&gt;&lt;span class="o"&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="s2"&gt;"checksum"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"8452e47f27b9618152a2b172357a547d"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="s2"&gt;"external"&lt;/span&gt;&lt;span class="o"&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="s2"&gt;"size"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;16&lt;/span&gt;
&lt;span class="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;"visibility"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"private"&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;/div&gt;&lt;/blockquote&gt;
&lt;ol class="arabic simple" start="9"&gt;
&lt;li&gt;&lt;p&gt;Reactivate artifact&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;Request:&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Method: PATCH&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;URL: &lt;a class="reference external" href="http://host:port/artifacts/example_type/art_id1"&gt;http://host:port/artifacts/example_type/art_id1&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Body:&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;div class="highlight-javascript 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;"op"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"replace"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s2"&gt;"path"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&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;"value"&lt;/span&gt;&lt;span class="o"&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;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;Response:&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;200 OK&lt;/p&gt;
&lt;div class="highlight-javascript 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;"status"&lt;/span&gt;&lt;span class="o"&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="s2"&gt;"name"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"stark"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s2"&gt;"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;"art_id1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s2"&gt;"version"&lt;/span&gt;&lt;span class="o"&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="s2"&gt;"metadata"&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;"slogan"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"winter is coming"&lt;/span&gt;
&lt;span class="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;"blob_file"&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;"status"&lt;/span&gt;&lt;span class="o"&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="s2"&gt;"checksum"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"8452e47f27b9618152a2b172357a547d"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="s2"&gt;"external"&lt;/span&gt;&lt;span class="o"&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="s2"&gt;"size"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;16&lt;/span&gt;
&lt;span class="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;"visibility"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"private"&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;/div&gt;&lt;/blockquote&gt;
&lt;ol class="arabic simple" start="10"&gt;
&lt;li&gt;&lt;p&gt;Publish artifact&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;Request:&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Method: PATCH&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;URL: &lt;a class="reference external" href="http://host:port/artifacts/example_type/art_id1"&gt;http://host:port/artifacts/example_type/art_id1&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Body:&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;div class="highlight-javascript 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;"op"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"replace"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s2"&gt;"path"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/visibility"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s2"&gt;"value"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"public"&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;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;Response:&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;200 OK&lt;/p&gt;
&lt;div class="highlight-javascript 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;"status"&lt;/span&gt;&lt;span class="o"&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="s2"&gt;"name"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"stark"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s2"&gt;"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;"art_id1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s2"&gt;"version"&lt;/span&gt;&lt;span class="o"&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="s2"&gt;"metadata"&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;"slogan"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"winter is coming"&lt;/span&gt;
&lt;span class="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;"blob_file"&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;"status"&lt;/span&gt;&lt;span class="o"&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="s2"&gt;"checksum"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"8452e47f27b9618152a2b172357a547d"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="s2"&gt;"external"&lt;/span&gt;&lt;span class="o"&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="s2"&gt;"size"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;16&lt;/span&gt;
&lt;span class="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;"visibility"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"public"&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;/div&gt;&lt;/blockquote&gt;
&lt;ol class="arabic simple" start="11"&gt;
&lt;li&gt;&lt;p&gt;Delete artifact&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;Request:&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Method: DELETE&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;URL: &lt;a class="reference external" href="http://host:port/artifacts/example_type/art_id1"&gt;http://host:port/artifacts/example_type/art_id1&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;Response:&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;204 No Content&lt;/p&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;/div&gt;&lt;/blockquote&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;No security 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 notification 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;The new API will need the client support. The support of the
Glare API v0.1 may be removed at the same moment when v1 support is added or
at any moment afterwards.&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&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 Glare service will follow the Glance release cycle. It’s expected that
artifact type updating, however, will proceed more quickly than a 6 month
cycle. Thus we want to make it possible to update artifact types more
frequently, but in a controlled manner that will be easy for deployers.&lt;/p&gt;
&lt;p&gt;We propose to address this situation by creating a single new repository
where all new glare-objects (Artifact types) will go. It will either be a
oslo-inc style library, but preferably a non-client OpenStack library which
can be released to pip and the Glare objects can be then pulled into Glance
repository using the right upper constraints per branch and at the same time
adhere to the OpenStack packaging fundamentals.&lt;/p&gt;
&lt;p&gt;The motivation, intent and purpose behind creating this new separate repo for
library is to form a organized way for OpenStack wide cross-project developers
to contribute to custom artifact object types and provide a consistent feedback.
At the same time, common code can be shared by the glare-objects and best
practices can be documented in the same place.&lt;/p&gt;
&lt;p&gt;Release of all the glare objects will be precise with that of glance
requirements and testing can be done comprehensively for all custom objects
in the same release of the library (irrespective if subset of objects have had
changes or not). This should ease the packaging pain and avoid operator/upgrade
mess.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;As the library would be a OpenStack non-client library, it would require
privileged access to the source code from non-regular glance developers
who are primarily working on projects like Murano or Heat, and so on.&lt;/p&gt;
&lt;p&gt;We would need to establish some common code and best practices for developers
in this repository.&lt;/p&gt;
&lt;p&gt;Since the Glare v 0.1 API is EXPERIMENTAL, developers should be prepared for
its deprecation.&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: mfedosin&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;kkushaev
dshakhray
nikhil-komawar&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="reviewers"&gt;
&lt;h3&gt;Reviewers&lt;/h3&gt;
&lt;p&gt;Glance core team because we need to spread the knowledge about Glare
to whole team.&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 API router and controllers. Mark v1 as &lt;strong&gt;EXPERIMENTAL&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Write helper methods to implement query parameter parsing (e.g. for
filtering, sorting, tags etc, according to API-WG guidelines)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Cover stable API with unit and functional tests.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Set v0.1 API as &lt;strong&gt;DEPRECATED&lt;/strong&gt; and v1 as &lt;strong&gt;STABLE&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Implement Glare v1 client&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 work on separating Glare API from Glance API (i.e. the transition from
Glance v3 to Glare v0.1), defined in spec [6] should be completed first.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Glare api should be covered by functional and unit tests. Integration tests
with Tempest should be implemented 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;Glare API, configuration options and policies should be documented.&lt;/p&gt;
&lt;p&gt;A new document - “Artifact type developers guide” has to be added.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="http://developer.openstack.org/api-ref-image-v2.html"&gt;OpenStack Image API v2 reference&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://specs.openstack.org/openstack/glance-specs/specs/kilo/artifact-repository.html"&gt;Initial spec&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/glance-artifacts-api-issues"&gt;Summary of API issues identified by API-WG&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/api-wg/guidelines/pagination_filter_sort.html"&gt;Filtering and sorting API-WG guideline&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/api-wg/blob/master/guidelines/tags.rst"&gt;Tags API-WG guideline&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/api-wg/guidelines/errors.html"&gt;Errors API-WG guideline&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/glance-v3-open-issues"&gt;Description of type-version issue&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/254163/"&gt;Glare v0.1 transition spec&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="http://jsonpatch.com/"&gt;json-patch description&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://docs.google.com/document/d/1KyY8VB00XvehtpBcLDo_Andx0BDgG-C7E_TdhfvcGv4/edit?usp=sharing"&gt;how to install Glare on devstack&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</description><pubDate>Thu, 08 Mar 2018 00:00:00 </pubDate></item><item><title>Glance Client Spec Lite</title><link>http://specs.openstack.org/openstack/glance-specs/specs/newton/approved/python-glanceclient/lite-specs.html</link><description>

&lt;p&gt;Please keep this template section in place and add your own copy of it between the markers.
Please fill only one Spec Lite per commit.&lt;/p&gt;
&lt;section id="title-of-your-spec-lite"&gt;
&lt;h2&gt;&amp;lt;Title of your Spec Lite&amp;gt;&lt;/h2&gt;
&lt;dl class="field-list simple"&gt;
&lt;dt class="field-odd"&gt;problem&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;&amp;lt;What is the driver to make the change.&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;solution&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;&amp;lt;High level description what needs to get done. For example: “We need to
add client function X.Y.Z to interact with new server functionality Z”.&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;impacts&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;&amp;lt;All possible *Impact flags (same as in commit messages) or ‘None’.&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;section id="optionals-please-remove-this-line-and-fill-or-remove-the-rest-until-end-of-template"&gt;
&lt;h3&gt;Optionals (please remove this line and fill or remove the rest until End of Template):&lt;/h3&gt;
&lt;dl class="field-list simple"&gt;
&lt;dt class="field-odd"&gt;how&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;&amp;lt;More technical details than the high level overview of &lt;cite&gt;solution&lt;/cite&gt; if needed.&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;alternatives&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;&amp;lt;Any alternative approaches that might be worth of bringing to discussion.&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;timeline&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;&amp;lt;Estimation of the time needed to complete the work.&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;link&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;&amp;lt;Link to the change in gerrit that already would provide the &lt;cite&gt;solution&lt;/cite&gt;.
After committing the Spec Lite depend the change to the Spec Lite commit.&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;reviewers&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;&amp;lt;If reviewers has been agreed for the functionality, list them here.&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;assignee&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;&amp;lt;If known, list who is going to work on the feature implementation here&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="end-of-template"&gt;
&lt;h3&gt;End of Template&lt;/h3&gt;
&lt;section id="add-your-spec-lite-before-this-line"&gt;
&lt;h4&gt;Add your Spec Lite before this line&lt;/h4&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;/section&gt;
</description><pubDate>Thu, 08 Mar 2018 00:00:00 </pubDate></item><item><title>Rolling upgrades</title><link>http://specs.openstack.org/openstack/glance-specs/specs/ocata/approved/glance/rolling-upgrades.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/glance/+spec/rolling-upgrades"&gt;https://blueprints.launchpad.net/glance/+spec/rolling-upgrades&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This spec provides a gap analysis of what is required for the Glance project to
assert the various rolling upgrade tags and specifies the actions necessary to
close the gaps.&lt;/p&gt;
&lt;p&gt;The goal for Ocata is to assert the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;assert:supports-zero-downtime-upgrade&lt;/span&gt;&lt;/code&gt;
tag, with a stretch goal of asserting the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;assert:supports-zero-impact-upgrade&lt;/span&gt;&lt;/code&gt; tag.  Given that asserting these tags
depends on completion of another feature (see spec proposal &lt;a class="reference internal" href="#gsp1" id="id1"&gt;&lt;span&gt;[GSP1]&lt;/span&gt;&lt;/a&gt;), the
backup goal is to assert the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;assert:supports-rolling-upgrade&lt;/span&gt;&lt;/code&gt; tag.  In any
case, Glance will make progress on the upgrade front in this cycle.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;There are currently four upgrade tags:&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;assert:supports-upgrade&lt;/span&gt;&lt;/code&gt; &lt;a class="reference internal" href="#gov3" id="id2"&gt;&lt;span&gt;[GOV3]&lt;/span&gt;&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;assert:supports-rolling-upgrade&lt;/span&gt;&lt;/code&gt; &lt;a class="reference internal" href="#gov1" id="id3"&gt;&lt;span&gt;[GOV1]&lt;/span&gt;&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;assert:supports-zero-downtime-upgrade&lt;/span&gt;&lt;/code&gt; &lt;a class="reference internal" href="#gov4" id="id4"&gt;&lt;span&gt;[GOV4]&lt;/span&gt;&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;assert:supports-zero-impact-upgrade&lt;/span&gt;&lt;/code&gt; &lt;a class="reference internal" href="#gov5" id="id5"&gt;&lt;span&gt;[GOV5]&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;section id="supports-upgrade"&gt;
&lt;h3&gt;supports-upgrade&lt;/h3&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;assert:supports-upgrade&lt;/span&gt;&lt;/code&gt; tag &lt;a class="reference internal" href="#gov3" id="id6"&gt;&lt;span&gt;[GOV3]&lt;/span&gt;&lt;/a&gt; has been asserted for Glance
&lt;a class="reference internal" href="#gov0" id="id7"&gt;&lt;span&gt;[GOV0]&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="supports-rolling-upgrade"&gt;
&lt;h3&gt;supports-rolling-upgrade&lt;/h3&gt;
&lt;p&gt;The requirements for asserting the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;assert:supports-rolling-upgrade&lt;/span&gt;&lt;/code&gt; tag are
listed in &lt;a class="reference internal" href="#gov1" id="id8"&gt;&lt;span&gt;[GOV1]&lt;/span&gt;&lt;/a&gt;.  They are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The project is already tagged as &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;type:service&lt;/span&gt;&lt;/code&gt; &lt;a class="reference internal" href="#gov2" id="id9"&gt;&lt;span&gt;[GOV2]&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Glance status: done&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The project has already successfully asserted the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;assert:supports-upgrade&lt;/span&gt;&lt;/code&gt;
tag &lt;a class="reference internal" href="#gov3" id="id10"&gt;&lt;span&gt;[GOV3]&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Glance staus: done&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The project has a defined plan that allows operators to roll out new code to
subsets of services, eliminating the need to restart all services on new code
simultaneously.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Glance status: need to define a plan.&lt;/p&gt;
&lt;p&gt;More detail about the required plan, as described in &lt;a class="reference internal" href="#gov1" id="id11"&gt;&lt;span&gt;[GOV1]&lt;/span&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;This plan should clearly call out the supported configuration(s) that
are expected to work, unless there are no such caveats. This does not
require complete elimination of downtime during upgrades, but rather
reducing the scope from “all services” to “some services at a time.” In
other words, “restarting all API services together” is a reasonable
restriction.&lt;/p&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;The Glance services consist of the Glance API server and the optional
Glance Registry API server.  The Glance Registry API server is not
intended to be exposed to end users or other OpenStack services; it is
expressly designed for internal Glance use only.&lt;/p&gt;
&lt;p&gt;(Note that it’s OK for there to be specific configurations under which a
rolling upgrade is expected to work.  In particular, it’s likely that we
will require deployments using the optional Glance registry to run it on
dedicated nodes.)&lt;/p&gt;
&lt;p&gt;Glance has had healthcheck middleware that can be used to signal to a load
balancer that an API node is out of service since the Liberty release
&lt;a class="reference internal" href="#gla2" id="id12"&gt;&lt;span&gt;[GLA2]&lt;/span&gt;&lt;/a&gt;.  This can be leveraged to take Glance nodes running “old” code out
of rotation while nodes running “new” code are brought in.&lt;/p&gt;
&lt;p&gt;Note that while this proposal will allow a mixed deployment of API versions
to run simultaneously, it does not envision that this will include multiple
versions of the API running &lt;em&gt;on the same node&lt;/em&gt; simultaneously.  In other
words, we do not intend to support a scenario in which “new” API code is
deployed to a node while “old” Glance processes are running on that node.
Instead, we expect operators to allow the “old” nodes to drain completely
and all processes running the “old” code to be stopped before the “new”
code is deployed to that node.  (If the Glance nodes are VMs, a completely
drained node could simply be deleted and be replaced by a fresh VM
containing the “new” code.)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Full stack integration testing with services arranged in a mid-upgrade manner
is performed on every proposed commit to validate that mixed-version services
work together properly.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Glance status: needs to be implemented (but note that the tests required
for the next tag would more than satisfy this requirement).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="supports-zero-downtime-upgrade"&gt;
&lt;h3&gt;supports-zero-downtime-upgrade&lt;/h3&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;assert:supports-zero-downtime-upgrade&lt;/span&gt;&lt;/code&gt; tag indicates that a project
supports minimal rolling upgrade capabilities in such a way that no disruptions
to API availability occur during the upgrade.&lt;/p&gt;
&lt;p&gt;The requirements for asserting this tag are listed in &lt;a class="reference internal" href="#gov4" id="id13"&gt;&lt;span&gt;[GOV4]&lt;/span&gt;&lt;/a&gt;.  They are:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;The project is already tagged as &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;type:service&lt;/span&gt;&lt;/code&gt; &lt;a class="reference internal" href="#gov2" id="id14"&gt;&lt;span&gt;[GOV2]&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Glance status: done&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The project has already successfully asserted both the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;assert:supports-upgrade&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;assert:supports-rolling-upgrade&lt;/span&gt;&lt;/code&gt; tags.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Glance status: the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;assert:supports-rolling-upgrade&lt;/span&gt;&lt;/code&gt; tag has not yet
been asserted.  See the previous section for what’s required.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Services must completely eliminate API downtime of the control plane during
the upgrade.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Glance status: The key issue is how to handle database changes required for
release N while release N-1 code is still running.  This is addressed by
another spec, “Database strategy for rolling upgrades” &lt;a class="reference internal" href="#gsp1" id="id15"&gt;&lt;span&gt;[GSP1]&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Services must be capable of receiving and handling requests throughout the
upgrade process with a normal success rate.  Services must prevent regression
by implementing a zero-downtime gate job wherein both a new version of the
service and an old version of the service are run concurrently.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Glance status: needs to be implemented.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="supports-zero-impact-upgrade"&gt;
&lt;h3&gt;supports-zero-impact-upgrade&lt;/h3&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;assert:supports-zero-impact-upgrade&lt;/span&gt;&lt;/code&gt; tag indicates that a project
supports both rolling upgrade capabilities and a zero-downtime upgrade (as
described above) in such a way that no perceivable API performance penalty
occurs during the upgrade.&lt;/p&gt;
&lt;p&gt;The requirements for asserting this tag are listed in &lt;a class="reference internal" href="#gov5" id="id16"&gt;&lt;span&gt;[GOV5]&lt;/span&gt;&lt;/a&gt;.  They are:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;The project is already tagged as &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;type:service&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Glance status: done&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The project has already successfully asserted the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;assert:supports-upgrade&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;assert:supports-rolling-upgrade&lt;/span&gt;&lt;/code&gt;, and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;assert:supports-zero-downtime-upgrade&lt;/span&gt;&lt;/code&gt; tags.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Glance status: see the previous sections.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Services must completely eliminate any perceivable performance
penalty during the upgrade process. Operators should not
expect any portion of the upgrade or migration process to place abnormally
high load on any part of the cloud, or to cause delays in the handling of API
requests, even intermittently.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Glance status: Given that we’re talking about Glance services only (not the
DBMS and not the storage backend), this should be achieved when the
zero-downtime upgrade is implemented.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Services must prevent regression by implementing a zero-impact gate job
wherein both a new version of the service and an old version of the service
are run concurrently under load. A measurement of API response times must
show that there are no statistically significant outliers during the upgrade
process when compared to normal operations.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Glance status: needs to be implemented.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&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 two major changes:&lt;/p&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;&lt;p&gt;Process Documentation&lt;/p&gt;
&lt;p&gt;What we need to establish is that the Glance project has “a defined plan
that allows operators to roll out new code to subsets of services,
eliminating the need to restart all services on new code simultaneously.”&lt;/p&gt;
&lt;p&gt;The “Gaps” section of the Product Working Group’s “Rolling Updates and
Upgrades” user story &lt;a class="reference internal" href="#pwg1" id="id17"&gt;&lt;span&gt;[PWG1]&lt;/span&gt;&lt;/a&gt; provides a useful list of the phases an
operator would go through in performing a rolling upgrade of an OpenStack
cloud.  We propose to document the relevant phases clearly for Glance so
that operators can understand the Glance rolling upgrade story.&lt;/p&gt;
&lt;p&gt;The phases identified by the Product Working Group are:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Maintenance Mode&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;Upgrade Orchestration - Deploy&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Multi-version Interoperability&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Online Schema Migration&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Graceful Shutdown&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Upgrade Orchestration - Remove&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Upgrade Orchestration - Tooling&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Upgrade Gating&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Project Tagging&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;For Glance, upgrading from release N-1 to release N, we can compress these
into:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Upgrade Orchestration - Deploy&lt;/strong&gt;&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;stage the code for release N to new Glance nodes&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Online Schema Migration&lt;/strong&gt; - Part 1&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;initial database schema migration (the “expand” phase as described
in &lt;a class="reference internal" href="#gsp1" id="id18"&gt;&lt;span&gt;[GSP1]&lt;/span&gt;&lt;/a&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;background data migration (as described in &lt;a class="reference internal" href="#gsp1" id="id19"&gt;&lt;span&gt;[GSP1]&lt;/span&gt;&lt;/a&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Multi-version interoperabilty&lt;/strong&gt;&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;start the release N nodes&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;take the release N-1 nodes out of rotation, allowing them to drain&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Upgrade Orchestration - Remove&lt;/strong&gt;&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;take each release N-1 node offline once it has completed processing its
current requests&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Online Schema Migration&lt;/strong&gt; - Part 2&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;final database schema migration (the “contract” phase as described
in &lt;a class="reference internal" href="#gsp1" id="id20"&gt;&lt;span&gt;[GSP1]&lt;/span&gt;&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;Testing&lt;/p&gt;
&lt;p&gt;Full stack integration testing with services arranged in a mid-upgrade
manner is performed on every proposed commit to validate that mixed-version
services work together properly.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;This testing must be performed on configurations that the project
considers to be its reference implementations.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The arrangement(s) tested will depend on the project (i.e. should be
representative of a meaningful-to-operators rolling upgrade scenario) and
available testing resources.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;At least one representative arrangement must be tested full-stack in the
gate.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;We propose using Grenade &lt;a class="reference internal" href="#grn1" id="id21"&gt;&lt;span&gt;[GRN1]&lt;/span&gt;&lt;/a&gt; for the full stack integration tests.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;&lt;p&gt;One alternative would be to choose not to support rolling upgrades in
Glance.  Such a choice, however, would impact other services that depend
upon Glance (for example, Nova).  Such services would experience disruptions
during the Glance upgrade.  So this doesn’t seem to be a serious
alternative.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The proposal in this spec is to use the “disable by file” feature of the
oslo healthcheck middleware to take the Glance nodes running “old” code out
of rotation and allow them to drain.  Stuart McLaren has suggested an
alternative, namely to piggyback on the zero downtime configuration reload
feature of Glance (available since the Kilo release &lt;a class="reference internal" href="#gla1" id="id22"&gt;&lt;span&gt;[GLA1]&lt;/span&gt;&lt;/a&gt;) and create a
“graceful stop” function that would accept a signal to shut down child
processes as they complete.  (See &lt;a class="reference internal" href="#gsp2" id="id23"&gt;&lt;span&gt;[GSP2]&lt;/span&gt;&lt;/a&gt; for details.)&lt;/p&gt;
&lt;p&gt;Since we’ve got the “disable by file” functionality available, this
alternative isn’t necessary to achieve the upgrade tags.  It would, however,
be an operator-friendly enhancement that we could pick up at some point.&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&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;It is anticipated that a rolling upgrade will require operator intervention.&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 be aware of Glance features that enable rolling
upgrades and make sure they aren’t removed.  (Developers will also need to work
within the constraints of the database strategy for rolling upgrades, but that
developer impact is covered by another 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;rosmaita
hemanthm&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;nikhil&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;Verify the accuracy of current Glance upgrade documentation.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Write documentation for rolling upgrade (developer docs).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Write documentation for rolling upgrade (operator docs).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Grenade tests.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Assert the tag and notify the OpenStack Technical Committee.&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;To achieve the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;assert::supports-zero-downtime-upgrade&lt;/span&gt;&lt;/code&gt; tag, this spec
depends upon implementation of the spec “Database strategy for rolling
upgrades” &lt;a class="reference internal" href="#gsp1" id="id24"&gt;&lt;span&gt;[GSP1]&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;We’ll need to implement gate tests (see above).&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;Documentation of general information for Glance rolling upgrades, in
particular:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The supported configuration(s) for rolling upgrades&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The operator workflow for performing a rolling upgrade&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;div role="list" class="citation-list"&gt;
&lt;div class="citation" id="gla1" role="doc-biblioentry"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id22"&gt;GLA1&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/122181/"&gt;https://review.openstack.org/#/c/122181/&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class="citation" id="gla2" role="doc-biblioentry"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id12"&gt;GLA2&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/148595/"&gt;https://review.openstack.org/#/c/148595/&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class="citation" id="gov0" role="doc-biblioentry"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id7"&gt;GOV0&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/245897/"&gt;https://review.openstack.org/#/c/245897/&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class="citation" id="gov1" role="doc-biblioentry"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;GOV1&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="#id8"&gt;2&lt;/a&gt;,&lt;a role="doc-backlink" href="#id11"&gt;3&lt;/a&gt;)&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://governance.openstack.org/reference/tags/assert_supports-rolling-upgrade.html"&gt;https://governance.openstack.org/reference/tags/assert_supports-rolling-upgrade.html&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class="citation" id="gov2" role="doc-biblioentry"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;GOV2&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="#id14"&gt;2&lt;/a&gt;)&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://governance.openstack.org/reference/tags/type_service.html"&gt;https://governance.openstack.org/reference/tags/type_service.html&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class="citation" id="gov3" role="doc-biblioentry"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;GOV3&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;a role="doc-backlink" href="#id10"&gt;3&lt;/a&gt;)&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://governance.openstack.org/reference/tags/assert_supports-upgrade.html"&gt;https://governance.openstack.org/reference/tags/assert_supports-upgrade.html&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class="citation" id="gov4" role="doc-biblioentry"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;GOV4&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="#id13"&gt;2&lt;/a&gt;)&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://governance.openstack.org/reference/tags/assert_supports-zero-downtime-upgrade.html"&gt;https://governance.openstack.org/reference/tags/assert_supports-zero-downtime-upgrade.html&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class="citation" id="gov5" role="doc-biblioentry"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;GOV5&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class="backrefs"&gt;(&lt;a role="doc-backlink" href="#id5"&gt;1&lt;/a&gt;,&lt;a role="doc-backlink" href="#id16"&gt;2&lt;/a&gt;)&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://governance.openstack.org/reference/tags/assert_supports-zero-impact-upgrade.html"&gt;https://governance.openstack.org/reference/tags/assert_supports-zero-impact-upgrade.html&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class="citation" id="grn1" role="doc-biblioentry"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id21"&gt;GRN1&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-dev/grenade"&gt;https://github.com/openstack-dev/grenade&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class="citation" id="gsp1" role="doc-biblioentry"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;GSP1&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="#id15"&gt;2&lt;/a&gt;,&lt;a role="doc-backlink" href="#id18"&gt;3&lt;/a&gt;,&lt;a role="doc-backlink" href="#id19"&gt;4&lt;/a&gt;,&lt;a role="doc-backlink" href="#id20"&gt;5&lt;/a&gt;,&lt;a role="doc-backlink" href="#id24"&gt;6&lt;/a&gt;)&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://review.openstack.org/#/c/331740/"&gt;https://review.openstack.org/#/c/331740/&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class="citation" id="gsp2" role="doc-biblioentry"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id23"&gt;GSP2&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/331489/8/specs/ocata/approved/glance/rolling-upgrades.rst@75"&gt;https://review.openstack.org/#/c/331489/8/specs/ocata/approved/glance/rolling-upgrades.rst@75&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class="citation" id="pwg1" role="doc-biblioentry"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id17"&gt;PWG1&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://specs.openstack.org/openstack/openstack-user-stories/user-stories/proposed/rolling-upgrades.html"&gt;http://specs.openstack.org/openstack/openstack-user-stories/user-stories/proposed/rolling-upgrades.html&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
</description><pubDate>Thu, 08 Mar 2018 00:00:00 </pubDate></item><item><title>Glance Store Spec Lite</title><link>http://specs.openstack.org/openstack/glance-specs/specs/ocata/approved/glance_store/lite-specs.html</link><description>

&lt;p&gt;Please keep this template section in place and add your own copy of it between the markers.
Please fill only one Spec Lite per commit.&lt;/p&gt;
&lt;section id="title-of-your-spec-lite"&gt;
&lt;h2&gt;&amp;lt;Title of your Spec Lite&amp;gt;&lt;/h2&gt;
&lt;dl class="field-list simple"&gt;
&lt;dt class="field-odd"&gt;problem&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;&amp;lt;What is the driver to make the change.&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;solution&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;&amp;lt;High level description what needs to get done. For example: “We need to
add client function X.Y.Z to interact with new server functionality Z”.&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;impacts&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;&amp;lt;All possible *Impact flags (same as in commit messages) or ‘None’.&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;section id="optionals-please-remove-this-line-and-fill-or-remove-the-rest-until-end-of-template"&gt;
&lt;h3&gt;Optionals (please remove this line and fill or remove the rest until End of Template):&lt;/h3&gt;
&lt;dl class="field-list simple"&gt;
&lt;dt class="field-odd"&gt;how&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;&amp;lt;More technical details than the high level overview of &lt;cite&gt;solution&lt;/cite&gt; if needed.&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;alternatives&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;&amp;lt;Any alternative approaches that might be worth of bringing to discussion.&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;timeline&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;&amp;lt;Estimation of the time needed to complete the work.&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;link&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;&amp;lt;Link to the change in gerrit that already would provide the &lt;cite&gt;solution&lt;/cite&gt;.
After committing the Spec Lite depend the change to the Spec Lite commit.&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;reviewers&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;&amp;lt;If reviewers has been agreed for the functionality, list them here.&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;assignee&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;&amp;lt;If known, list who is going to work on the feature implementation here&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="end-of-template"&gt;
&lt;h3&gt;End of Template&lt;/h3&gt;
&lt;section id="add-your-spec-lite-before-this-line"&gt;
&lt;h4&gt;Add your Spec Lite before this line&lt;/h4&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;/section&gt;
</description><pubDate>Thu, 08 Mar 2018 00:00:00 </pubDate></item><item><title>Glance Client Spec Lite</title><link>http://specs.openstack.org/openstack/glance-specs/specs/ocata/approved/python-glanceclient/lite-specs.html</link><description>

&lt;p&gt;Please keep this template section in place and add your own copy of it between the markers.
Please fill only one Spec Lite per commit.&lt;/p&gt;
&lt;section id="title-of-your-spec-lite"&gt;
&lt;h2&gt;&amp;lt;Title of your Spec Lite&amp;gt;&lt;/h2&gt;
&lt;dl class="field-list simple"&gt;
&lt;dt class="field-odd"&gt;problem&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;&amp;lt;What is the driver to make the change.&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;solution&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;&amp;lt;High level description what needs to get done. For example: “We need to
add client function X.Y.Z to interact with new server functionality Z”.&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;impacts&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;&amp;lt;All possible *Impact flags (same as in commit messages) or ‘None’.&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;section id="optionals-please-remove-this-line-and-fill-or-remove-the-rest-until-end-of-template"&gt;
&lt;h3&gt;Optionals (please remove this line and fill or remove the rest until End of Template):&lt;/h3&gt;
&lt;dl class="field-list simple"&gt;
&lt;dt class="field-odd"&gt;how&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;&amp;lt;More technical details than the high level overview of &lt;cite&gt;solution&lt;/cite&gt; if needed.&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;alternatives&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;&amp;lt;Any alternative approaches that might be worth of bringing to discussion.&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;timeline&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;&amp;lt;Estimation of the time needed to complete the work.&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;link&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;&amp;lt;Link to the change in gerrit that already would provide the &lt;cite&gt;solution&lt;/cite&gt;.
After committing the Spec Lite depend the change to the Spec Lite commit.&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;reviewers&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;&amp;lt;If reviewers has been agreed for the functionality, list them here.&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;assignee&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;&amp;lt;If known, list who is going to work on the feature implementation here&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="end-of-template"&gt;
&lt;h3&gt;End of Template&lt;/h3&gt;
&lt;section id="add-your-spec-lite-before-this-line"&gt;
&lt;h4&gt;Add your Spec Lite before this line&lt;/h4&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;/section&gt;
</description><pubDate>Thu, 08 Mar 2018 00:00:00 </pubDate></item><item><title>Glance Spec Lite</title><link>http://specs.openstack.org/openstack/glance-specs/specs/pike/approved/glance/lite-specs.html</link><description>

&lt;p&gt;Please keep this template section in place and add your own copy of it between the markers.
Please fill only one Spec Lite per commit.&lt;/p&gt;
&lt;section id="title-of-your-spec-lite"&gt;
&lt;h2&gt;&amp;lt;Title of your Spec Lite&amp;gt;&lt;/h2&gt;
&lt;dl class="field-list simple"&gt;
&lt;dt class="field-odd"&gt;problem&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;&amp;lt;What is the driver to make the change.&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;solution&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;&amp;lt;High level description what needs to get done. For example: “We need to
add client function X.Y.Z to interact with new server functionality Z”.&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;impacts&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;&amp;lt;All possible *Impact flags (same as in commit messages) or ‘None’.&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;section id="optionals-please-remove-this-line-and-fill-or-remove-the-rest-until-end-of-template"&gt;
&lt;h3&gt;Optionals (please remove this line and fill or remove the rest until End of Template):&lt;/h3&gt;
&lt;dl class="field-list simple"&gt;
&lt;dt class="field-odd"&gt;how&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;&amp;lt;More technical details than the high level overview of &lt;cite&gt;solution&lt;/cite&gt; if needed.&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;alternatives&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;&amp;lt;Any alternative approaches that might be worth of bringing to discussion.&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;timeline&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;&amp;lt;Estimation of the time needed to complete the work.&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;link&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;&amp;lt;Link to the change in gerrit that already would provide the &lt;cite&gt;solution&lt;/cite&gt;.
After committing the Spec Lite depend the change to the Spec Lite commit.&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;reviewers&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;&amp;lt;If reviewers has been agreed for the functionality, list them here.&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;assignee&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;&amp;lt;If known, list who is going to work on the feature implementation here&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="end-of-template"&gt;
&lt;h3&gt;End of Template&lt;/h3&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="community-goal-support-python-3-5"&gt;
&lt;h2&gt;Community Goal: Support Python 3.5&lt;/h2&gt;
&lt;dl class="field-list simple"&gt;
&lt;dt class="field-odd"&gt;problem&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;Satisfy the Pike community goal &lt;a class="reference external" href="https://governance.openstack.org/tc/goals/pike/python35.html"&gt;Support Python 3.5&lt;/a&gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;solution&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;Ensure that Glance meets the criteria of the Goal.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;impacts&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;None.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;assignee&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;Open&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;section id="end-of-community-goal-support-python-3-5"&gt;
&lt;h3&gt;End of &lt;cite&gt;Community Goal: Support Python 3.5&lt;/cite&gt;&lt;/h3&gt;
&lt;section id="add-your-spec-lite-before-this-line"&gt;
&lt;h4&gt;Add your Spec Lite before this line&lt;/h4&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;/section&gt;
</description><pubDate>Thu, 08 Mar 2018 00:00:00 </pubDate></item><item><title>Glance Store Spec Lite</title><link>http://specs.openstack.org/openstack/glance-specs/specs/pike/approved/glance_store/lite-specs.html</link><description>

&lt;p&gt;Please keep this template section in place and add your own copy of it between the markers.
Please fill only one Spec Lite per commit.&lt;/p&gt;
&lt;section id="title-of-your-spec-lite"&gt;
&lt;h2&gt;&amp;lt;Title of your Spec Lite&amp;gt;&lt;/h2&gt;
&lt;dl class="field-list simple"&gt;
&lt;dt class="field-odd"&gt;problem&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;&amp;lt;What is the driver to make the change.&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;solution&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;&amp;lt;High level description what needs to get done. For example: “We need to
add client function X.Y.Z to interact with new server functionality Z”.&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;impacts&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;&amp;lt;All possible *Impact flags (same as in commit messages) or ‘None’.&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;section id="optionals-please-remove-this-line-and-fill-or-remove-the-rest-until-end-of-template"&gt;
&lt;h3&gt;Optionals (please remove this line and fill or remove the rest until End of Template):&lt;/h3&gt;
&lt;dl class="field-list simple"&gt;
&lt;dt class="field-odd"&gt;how&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;&amp;lt;More technical details than the high level overview of &lt;cite&gt;solution&lt;/cite&gt; if needed.&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;alternatives&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;&amp;lt;Any alternative approaches that might be worth of bringing to discussion.&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;timeline&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;&amp;lt;Estimation of the time needed to complete the work.&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;link&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;&amp;lt;Link to the change in gerrit that already would provide the &lt;cite&gt;solution&lt;/cite&gt;.
After committing the Spec Lite depend the change to the Spec Lite commit.&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;reviewers&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;&amp;lt;If reviewers has been agreed for the functionality, list them here.&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;assignee&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;&amp;lt;If known, list who is going to work on the feature implementation here&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="end-of-template"&gt;
&lt;h3&gt;End of Template&lt;/h3&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="community-goal-support-python-3-5"&gt;
&lt;h2&gt;Community Goal: Support Python 3.5&lt;/h2&gt;
&lt;dl class="field-list simple"&gt;
&lt;dt class="field-odd"&gt;problem&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;Satisfy the Pike community goal &lt;a class="reference external" href="https://governance.openstack.org/tc/goals/pike/python35.html"&gt;Support Python 3.5&lt;/a&gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;solution&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;Ensure that glance_store meets the criteria of the Goal.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;impacts&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;None.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;assignee&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;Alex Bashmakov&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;section id="end-of-community-goal-support-python-3-5"&gt;
&lt;h3&gt;End of &lt;cite&gt;Community Goal: Support Python 3.5&lt;/cite&gt;&lt;/h3&gt;
&lt;section id="add-your-spec-lite-before-this-line"&gt;
&lt;h4&gt;Add your Spec Lite before this line&lt;/h4&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;/section&gt;
</description><pubDate>Thu, 08 Mar 2018 00:00:00 </pubDate></item><item><title>Glance Client Spec Lite</title><link>http://specs.openstack.org/openstack/glance-specs/specs/pike/approved/python-glanceclient/lite-specs.html</link><description>

&lt;p&gt;Please keep this template section in place and add your own copy of it between the markers.
Please fill only one Spec Lite per commit.&lt;/p&gt;
&lt;section id="title-of-your-spec-lite"&gt;
&lt;h2&gt;&amp;lt;Title of your Spec Lite&amp;gt;&lt;/h2&gt;
&lt;dl class="field-list simple"&gt;
&lt;dt class="field-odd"&gt;problem&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;&amp;lt;What is the driver to make the change.&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;solution&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;&amp;lt;High level description what needs to get done. For example: “We need to
add client function X.Y.Z to interact with new server functionality Z”.&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;impacts&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;&amp;lt;All possible *Impact flags (same as in commit messages) or ‘None’.&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;section id="optionals-please-remove-this-line-and-fill-or-remove-the-rest-until-end-of-template"&gt;
&lt;h3&gt;Optionals (please remove this line and fill or remove the rest until End of Template):&lt;/h3&gt;
&lt;dl class="field-list simple"&gt;
&lt;dt class="field-odd"&gt;how&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;&amp;lt;More technical details than the high level overview of &lt;cite&gt;solution&lt;/cite&gt; if needed.&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;alternatives&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;&amp;lt;Any alternative approaches that might be worth of bringing to discussion.&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;timeline&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;&amp;lt;Estimation of the time needed to complete the work.&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;link&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;&amp;lt;Link to the change in gerrit that already would provide the &lt;cite&gt;solution&lt;/cite&gt;.
After committing the Spec Lite depend the change to the Spec Lite commit.&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;reviewers&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;&amp;lt;If reviewers has been agreed for the functionality, list them here.&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;assignee&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;&amp;lt;If known, list who is going to work on the feature implementation here&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="end-of-template"&gt;
&lt;h3&gt;End of Template&lt;/h3&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="community-goal-support-python-3-5"&gt;
&lt;h2&gt;Community Goal: Support Python 3.5&lt;/h2&gt;
&lt;dl class="field-list simple"&gt;
&lt;dt class="field-odd"&gt;problem&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;Satisfy the Pike community goal &lt;a class="reference external" href="https://governance.openstack.org/tc/goals/pike/python35.html"&gt;Support Python 3.5&lt;/a&gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;solution&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;Ensure that python-glanceclient meets the criteria of the Goal.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;impacts&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;None.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;assignee&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;Alex Bashmakov&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;section id="end-of-community-goal-support-python-3-5"&gt;
&lt;h3&gt;End of &lt;cite&gt;Community Goal: Support Python 3.5&lt;/cite&gt;&lt;/h3&gt;
&lt;section id="add-your-spec-lite-before-this-line"&gt;
&lt;h4&gt;Add your Spec Lite before this line&lt;/h4&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;/section&gt;
</description><pubDate>Thu, 08 Mar 2018 00:00:00 </pubDate></item><item><title>Spec Lite: Remove the Registry API v1</title><link>http://specs.openstack.org/openstack/glance-specs/specs/rocky/approved/glance/remove-registry-v1.html</link><description>

&lt;dl class="field-list simple"&gt;
&lt;dt class="field-odd"&gt;problem&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;During the Queens cycle, the two Glance services that depend upon the
Glance Registry API v1 will be removed (API v1) or refactored (the
scrubber).  Hence, the Registry API will be redundant and should be
removed.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;dependencies&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;The Images API v1 must be removed&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The scrubber must be refactored so it doesn’t use the Registry
API v1&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;solution&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;Remove the Registry API v1 from the codebase.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;impacts&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;DocImpact&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;timeline&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;target for the Q-3 milestone (week of 22 January 2017)&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;link&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/glance/+spec/remove-registry-v1"&gt;https://blueprints.launchpad.net/glance/+spec/remove-registry-v1&lt;/a&gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;reviewers&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;all core reviewers&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
</description><pubDate>Thu, 01 Mar 2018 00:00:00 </pubDate></item><item><title>Spec Lite: Deprecate Images API v1 Support</title><link>http://specs.openstack.org/openstack/glance-specs/specs/rocky/approved/python-glanceclient/deprecate-v1-support.html</link><description>

&lt;dl class="field-list simple"&gt;
&lt;dt class="field-odd"&gt;problem&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;The Images API v1 is targeted to be removed in Rocky, hence there
is no reason to continue carrying v1 support in the glanceclient.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;solution&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;Announce that the Rocky release of the python-glanceclient will
be the last release that will support the Images v1 API and that
support will be removed in the first major release of the S
cycle.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;impacts&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;DocImpact&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;alternatives&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;Continue to support the Images API version 1.  This is not
necessary for interoperability, however, as the Images API
v1 was never included in “DefCore” tests.  Continued support
would not be a good use of the team’s time.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;timeline&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;Early Rocky cycle&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;link&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/python-glanceclient/+spec/deprecate-v1-support"&gt;https://blueprints.launchpad.net/python-glanceclient/+spec/deprecate-v1-support&lt;/a&gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;reviewers&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;all core reviewers&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;assignee&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;jokke&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
</description><pubDate>Thu, 01 Mar 2018 00:00:00 </pubDate></item><item><title>Spec Lite: Switch to Turn Off Schema Validation</title><link>http://specs.openstack.org/openstack/glance-specs/specs/untargeted/python-glanceclient/no-schema-validation.html</link><description>

&lt;dl class="field-list simple"&gt;
&lt;dt class="field-odd"&gt;problem&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;While an API is in EXPERIMENTAL status, the schemas may not
accurately reflect the content of requests and responses,
causing the client to error out.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;solution&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;Introduce a new option controlled by an environment variable
that will turn off schema validation.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;impacts&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;None&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;timeline&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;Q-1 milestone (week of 16 October 2017)&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;link&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/python-glanceclient/+spec/no-schema-validation"&gt;https://blueprints.launchpad.net/python-glanceclient/+spec/no-schema-validation&lt;/a&gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;reviewers&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;all core reviewers&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
</description><pubDate>Thu, 01 Mar 2018 00:00:00 </pubDate></item><item><title>Inject metadata properties automatically to non-admin images</title><link>http://specs.openstack.org/openstack/glance-specs/specs/queens/implemented/glance/inject-automatic-metadata.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/glance/+spec/inject-automatic-metadata"&gt;https://blueprints.launchpad.net/glance/+spec/inject-automatic-metadata&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Cloud operator wants to launch a VM based on certain image metadata properties
on different compute nodes.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;The operator provides public images to the users and users can also add their
own images in glance and use these images to launch VMs. As an operator, all
images provided by an operator should be launched on a specific set of compute
nodes whereas images that are created by non-admin users should be launched
on other set of compute nodes. The decision to launch VMs on certain compute
nodes will be decided based on image metadata. When an operator will create
images, they can specify certain image metadata which will be used by
placement api or scheduler service to decide where the vm should be launched
but if user creates image, there is no way user will know what image metadata
properties to set  and hence in the present placement api and scheduler logic,
it is possible to launch a VM on any compute nodes. This is a big problem.&lt;/p&gt;
&lt;section id="use-case"&gt;
&lt;h3&gt;Use Case:&lt;/h3&gt;
&lt;p&gt;The operator wants user based images to be launched on certain set of compute
nodes (host aggregate groups) based on image metadata properties.&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;Make a provision to inject image metadata to non-admin images while adding
image to glance backend with the help of property protection. We are planning
to introduce two new config options to achieve the same.
1) ‘ignore_user_roles’ is a comma-separated list of roles. Defaults to admin.
2) ‘inject’ defaults to None.&lt;/p&gt;
&lt;p&gt;‘inject’ config option will consist of json format (key: value pair) of image
metadata which an operator wants to add to the newly created images if
user role is not as per mentioned in ‘ignore_user_roles’ config option. If
user role is not same as mentioned in ‘ignore_user_roles’ and ‘inject’ doesn’t
contain any metadata properties, then no metadata will be injected to the
non-admin images.&lt;/p&gt;
&lt;p&gt;We propose to create new config file ‘glance-image-import.conf’ which will
have all config options related to image import tasks stuff. Each pluggable
task can have own section which define its configuration options in this file.&lt;/p&gt;
&lt;p&gt;For example, for injecting metadata properties ‘glance-image-import.conf’
will have ‘property_injections’ section described below;&lt;/p&gt;
&lt;p&gt;[inject_metadata_properties]
ignore_user_roles = admin,…
inject = { “property1”: “value”, “property2”: “value,another value” }&lt;/p&gt;
&lt;p&gt;Note:
When user creates a volume from image, all image metadata will be copied to
volume and made available as volume_image_metadata. Now, when user will copy
back a volume to image, it will attempt to add ‘property1’ metadata and it
will fail as it is only allowed to be created by admin. To address this issue
need to make provision like ignore all properties specified in ‘inject’
config option if the request comes from a user whose roles is not specified
in ‘ignore_user_roles config option. For example when user performs
copy back volume to image then if properties mentioned in inject option
will be silently ignored i.e. newly created image from volume does not contains
special metadata properties mentioned in ‘inject’ config option.&lt;/p&gt;
&lt;p&gt;[some_other_yet_undefined_task]
will_have = “it’s own configs”&lt;/p&gt;
&lt;p&gt;We will use property protection so that non-admin user won’t be able to
add, update or delete the injected metadata properties automatically. Non-admin
users however will be able to view these metadata properties. For example
if ‘inject’ is set to ‘property1=value’ then in property_protections.conf
file, an operator needs to restrict write and delete access for ‘property1’
to non-admin users as described below:&lt;/p&gt;
&lt;p&gt;[property1]
create = admin
read = admin,member,_member_
update = admin
delete = admin&lt;/p&gt;
&lt;p&gt;In glance, users can create images using two ways.
1) create image API
2) Import image API&lt;/p&gt;
&lt;p&gt;In case of import image API, as it uses taskflow, an additional task
‘InjectMetadataProperties’ will be created to inject the metadata. If
‘inject’ property is not None, then only ‘InjectMetadataProperties’ will be
part of the tasks, otherwise it will be simply ignored.&lt;/p&gt;
&lt;p&gt;No changes will be made to create image API. The intent is that the old upload
workflow will only be used by services, it won’t be exposed to end users in
most deployments.&lt;/p&gt;
&lt;p&gt;Note: There is a restriction on how many image metadata properties an user
can set to a image which is configurable using ‘image_property_quota’
config option. If it’s value is 128 and say, if ‘inject’ config option count
is 3, then user would be able to add only 125 metadata items by themselves and
remaining 3 will be injected automatically. If user tries to add more than
125 metadata items in case of import image api call then the task will
marked as failed with appropriate failure message.&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 is a limit on having additional image metadata properties which defaults
to 128. This is configurable using ‘image_property_quota’ option. If an
operator sets this limit to higher value and more metadata properties are
injected, then it will impact performance during image-list or image-show
calls.&lt;/p&gt;
&lt;p&gt;This impact is not specifically a result of the proposal in this spec, it’s
also the case under the current situation.&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;Administrator need to set ‘ignore_user_roles’ and ‘inject’ config options in
‘inject_metadata_properties’ section of ‘glance-image-import.conf’ config file
if metadata properties to be injected for new images for non-admin users.&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;&amp;lt;bhagyashri-shewale&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="reviewers"&gt;
&lt;h3&gt;Reviewers&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Core reviewer(s):&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Erno Kuvaja, Brian Rosmaita&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other reviewer(s):&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 provision to read config options from new glance-image-import.conf&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add two new config options&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add ‘InjectMetadataProperties’ task for import call&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add unit tests for coverage&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add 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;Functional tests will be added to verify that metadata will be injected for
non-admin images only.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Please refer to ‘Other deployer impact’&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>Mon, 26 Feb 2018 00:00:00 </pubDate></item><item><title>Spec Lite: Refactor Glance Scrubber</title><link>http://specs.openstack.org/openstack/glance-specs/specs/queens/implemented/glance/lite-spec-scrubber-refactor.html</link><description>

&lt;dl class="field-list simple"&gt;
&lt;dt class="field-odd"&gt;problem&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;The scrubber code uses the registry v1 client.  This is bad because
it doesn’t support Keystone v3 auth, which is widely used by default.
Additionally, when the Images API v1 is removed, nothing else will be
using the registry v1 client.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;solution&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;Refactor the scrubber so that it doesn’t use the registry at all.
Planning for registry deprecation began in Newton and the
deprecation is being officially announced in Queens.  This
refactoring will allow us to remove the registry on schedule
in the S release.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;impacts&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;None&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;timeline&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;Q-2 milestone or thereabouts (early December)&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;link&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/glance/+spec/scrubber-refactor"&gt;https://blueprints.launchpad.net/glance/+spec/scrubber-refactor&lt;/a&gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;reviewers&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;rosmaita, abhishekk, jokke&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;assignee&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;wangxiyuan&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
</description><pubDate>Mon, 26 Feb 2018 00:00:00 </pubDate></item><item><title>Fake Keystone Server for Functional Tests</title><link>http://specs.openstack.org/openstack/glance-specs/specs/juno/fake-keystone-for-testing.html</link><description>

&lt;p&gt;The URL of the launchpad blueprint:&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/glance/+spec/fake-keystone-for-testing"&gt;https://blueprints.launchpad.net/glance/+spec/fake-keystone-for-testing&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;As keystone is only supported auth method for glance we should be doing our
functional tests against keystone pipeline as well.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Currently we are defaulting the Glance authentication pipeline to noauth.
This is not supported configuration with glance and causes some issues.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Default config cannot be changed to keystone pipeline unless we have
Keystone functionality available during our tests as the servers are spun
up with default configuration as well as with the test specific one.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Functional tests does not reflect to real world as they uses unsupported
authentication pipeline. Also certain functionalities (like using registry
with v2) cannot be tested as noauth does not provide the needed user
information.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Fake Keystone server with minimal functionality would solve this issue without
increasing the overhead for our testing too much:&lt;/p&gt;
&lt;p&gt;Needed functionality would be:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Support for auth token verification (this can be done with pre determined
set of tokens and token management would not be needed)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Support for user - password authentication (this can also be done with pre
determined set of user/password combinations and user management would not
be needed).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Monkey patching the code we are actually testing to act against the design
agreed when implemented. This would allow us to pass the test issues, but
leave a hole for unwanted behaviour to pass tests.&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 would potentially harden the security as the functional tests would be
ran against more real life like configuration.&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 impact on test performance as more processes are needed to run the
tests.&lt;/p&gt;
&lt;p&gt;This can be circumvented by more coarse functional testing as agreed on weekly
Glance meeting (14:39):
&lt;a class="reference external" href="http://eavesdrop.openstack.org/meetings/glance/2014/"&gt;http://eavesdrop.openstack.org/meetings/glance/2014/&lt;/a&gt;
glance.2014-06-05-14.05.log.html&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;Better visibility of how changes affects due to better testing experience.&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;blockquote&gt;
&lt;div&gt;&lt;p&gt;Erno Kuvaja &amp;lt;jokke&amp;gt;&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;Implementation of the Fake Keystone server&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Changing the functional tests using it&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Refactoring the functional tests to circumvent the performance hit / improve
the performance&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;As this is testing functionality/change testing of it would not be needed.&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;None&lt;/p&gt;
&lt;/section&gt;
</description><pubDate>Tue, 23 Jan 2018 00:00:00 </pubDate></item><item><title>Glance Spec Lite</title><link>http://specs.openstack.org/openstack/glance-specs/specs/lite-specs.html</link><description>

&lt;p&gt;Please keep this template section in place and add your own copy of it between the markers.
Please fill only one Spec Lite per commit.&lt;/p&gt;
&lt;section id="title-of-your-spec-lite"&gt;
&lt;h2&gt;&amp;lt;Title of your Spec Lite&amp;gt;&lt;/h2&gt;
&lt;dl class="field-list simple"&gt;
&lt;dt class="field-odd"&gt;problem&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;&amp;lt;What is the driver to make the change.&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;solution&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;&amp;lt;High level description what needs to get done. For example: “We need to
add client function X.Y.Z to interact with new server functionality Z”.&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;impacts&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;&amp;lt;All possible *Impact flags (same as in commit messages) or ‘None’.&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;section id="optionals-please-remove-this-line-and-fill-or-remove-the-rest-until-end-of-template"&gt;
&lt;h3&gt;Optionals (please remove this line and fill or remove the rest until End of Template):&lt;/h3&gt;
&lt;dl class="field-list simple"&gt;
&lt;dt class="field-odd"&gt;how&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;&amp;lt;More technical details than the high level overview of &lt;cite&gt;solution&lt;/cite&gt; if needed.&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;alternatives&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;&amp;lt;Any alternative approaches that might be worth of bringing to discussion.&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;timeline&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;&amp;lt;Estimation of the time needed to complete the work.&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;link&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;&amp;lt;Link to the change in gerrit that already would provide the &lt;cite&gt;solution&lt;/cite&gt;.
After committing the Spec Lite depend the change to the Spec Lite commit.&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;reviewers&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;&amp;lt;If reviewers has been agreed for the functionality, list them here.&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;assignee&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;&amp;lt;If known, list who is going to work on the feature implementation here&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="end-of-template"&gt;
&lt;h3&gt;End of Template&lt;/h3&gt;
&lt;section id="add-your-spec-lite-before-this-line"&gt;
&lt;h4&gt;Add your Spec Lite before this line&lt;/h4&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;/section&gt;
</description><pubDate>Tue, 23 Jan 2018 00:00:00 </pubDate></item><item><title>Glance Spec Lite</title><link>http://specs.openstack.org/openstack/glance-specs/specs/newton/approved/glance/lite-specs.html</link><description>

&lt;p&gt;Please keep this template section in place and add your own copy of it between the markers.
Please fill only one Spec Lite per commit.&lt;/p&gt;
&lt;section id="title-of-your-spec-lite"&gt;
&lt;h2&gt;&amp;lt;Title of your Spec Lite&amp;gt;&lt;/h2&gt;
&lt;dl class="field-list simple"&gt;
&lt;dt class="field-odd"&gt;problem&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;&amp;lt;What is the driver to make the change.&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;solution&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;&amp;lt;High level description what needs to get done. For example: “We need to
add client function X.Y.Z to interact with new server functionality Z”.&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;impacts&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;&amp;lt;All possible *Impact flags (same as in commit messages) or ‘None’.&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;section id="optionals-please-remove-this-line-and-fill-or-remove-the-rest-until-end-of-template"&gt;
&lt;h3&gt;Optionals (please remove this line and fill or remove the rest until End of Template):&lt;/h3&gt;
&lt;dl class="field-list simple"&gt;
&lt;dt class="field-odd"&gt;how&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;&amp;lt;More technical details than the high level overview of &lt;cite&gt;solution&lt;/cite&gt; if needed.&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;alternatives&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;&amp;lt;Any alternative approaches that might be worth of bringing to discussion.&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;timeline&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;&amp;lt;Estimation of the time needed to complete the work.&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;link&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;&amp;lt;Link to the change in gerrit that already would provide the &lt;cite&gt;solution&lt;/cite&gt;.
After committing the Spec Lite depend the change to the Spec Lite commit.&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;reviewers&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;&amp;lt;If reviewers has been agreed for the functionality, list them here.&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;assignee&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;&amp;lt;If known, list who is going to work on the feature implementation here&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="end-of-template"&gt;
&lt;h3&gt;End of Template&lt;/h3&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="return-409-if-setting-location-to-saving-or-deactivated-image"&gt;
&lt;h2&gt;Return 409 if setting location to saving or deactivated image&lt;/h2&gt;
&lt;dl class="field-list simple"&gt;
&lt;dt class="field-odd"&gt;problem&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;Currently, if ‘show_multiple_locations’ is activated,
user can set custom location to an image, even if it
has ‘saving’ or ‘deactivated’ status.
Example: &lt;a class="reference external" href="http://paste.openstack.org/show/506998/"&gt;http://paste.openstack.org/show/506998/&lt;/a&gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;solution&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;Add a check, that looks at the image status and if it’s
different from ‘queued’ or ‘active’ then returns Conflict
error (409 response code).&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;impacts&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;users will get Conflict error, when they try to set location
to image in ‘saving’ or ‘deactivated’ state.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;timeline&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;Expected to be merged within the N-2 time frame.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;link&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;&lt;a class="reference external" href="https://review.openstack.org/#/c/324012/"&gt;https://review.openstack.org/#/c/324012/&lt;/a&gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;assignee&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;Mike Fedosin&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;section id="id1"&gt;
&lt;h3&gt;Return 409 if setting location to saving or deactivated image&lt;/h3&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="use-policy-to-control-deleting-deactivated-images"&gt;
&lt;h2&gt;Use policy to control deleting deactivated images&lt;/h2&gt;
&lt;dl class="field-list simple"&gt;
&lt;dt class="field-odd"&gt;problem&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;Currently, a user is permitted to delete a ‘deactivated’
image. Thus, if an image is suspected dangerous and deactivated
by an administrator, a user could nonetheless remove the data
before a security team has time to review it, thereby removing
evidence of any wrongdoing. This presents a problem for an
administrator who would like an investigation to take place.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;solution&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;Introduce a policy check named &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;delete_deactivated_image&lt;/span&gt;&lt;/code&gt;
to govern whether a user is permitted to delete a ‘deactivated’
image.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;impacts&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;Adds a new policy. The default configuration will preserve
current behaviour, that is, all users will be permitted to
perform the action.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;timeline&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;Expected to be merged within the N-2 time frame.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;link&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;&lt;a class="reference external" href="https://review.openstack.org/#/c/256381"&gt;https://review.openstack.org/#/c/256381&lt;/a&gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;assignee&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;Niall Bunting&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;section id="end-of-policy-to-control-deleting-deactivated-images"&gt;
&lt;h3&gt;End of policy to control deleting deactivated images&lt;/h3&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="add-functionality-to-soft-delete-the-tasks"&gt;
&lt;h2&gt;Add functionality to soft delete the tasks&lt;/h2&gt;
&lt;dl class="field-list simple"&gt;
&lt;dt class="field-odd"&gt;problem&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;Currently there is no mechanism for deleting tasks on regular
basis. Thus, if a task is expired; it still comes up on calling
task list or show. This can hamper the performance as the
number of tasks returned will be more than the number of
tasks that are active. Consequently, it will be tedious for
the user to manage them.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;solution&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;Introduce a method which soft deletes the tasks by marking the
deleted status as true in the database; so that, on calling
task show or list, the expires tasks are not returned.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;impacts&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;Adds a new method. Users will now get only the active tasks.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;timeline&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;Expected to be merged within the N-2 time frame.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;link&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;&lt;a class="reference external" href="https://review.openstack.org/#/c/209255/"&gt;https://review.openstack.org/#/c/209255/&lt;/a&gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;assignee&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;Geetika Batra&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;section id="end-of-add-functionality-to-soft-delete-the-tasks"&gt;
&lt;h3&gt;End of Add functionality to soft delete the tasks&lt;/h3&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="add-vhdx-to-list-of-supported-disk-formats"&gt;
&lt;h2&gt;Add &lt;cite&gt;vhdx&lt;/cite&gt; to list of supported disk formats&lt;/h2&gt;
&lt;dl class="field-list simple"&gt;
&lt;dt class="field-odd"&gt;problem&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;Glance currently support vhd disk formats and is being used in known
deployments. &lt;cite&gt;vhdx&lt;/cite&gt; disks can have much larger storage capacity than
the older &lt;cite&gt;vhd&lt;/cite&gt; format. More info can be found at offcial site
&lt;a class="reference external" href="https://technet.microsoft.com/en-us/library/hh831446(v=ws.11).aspx"&gt;https://technet.microsoft.com/en-us/library/hh831446(v=ws.11).aspx&lt;/a&gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;solution&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;&lt;cite&gt;disk_formats&lt;/cite&gt; configuration option needs to be updated to indicate
that this is a acceptable format. Some documentation updates are
required showing the same and providing info about the official
documentation.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;impacts&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;This will have documentation and upgrade impact. Release note should
be added to indicate interest parties about this addition.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;timeline&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;Expected to be merged within the N-3 time frame.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;link&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;&lt;a class="reference external" href="https://review.openstack.org/#/c/347352"&gt;https://review.openstack.org/#/c/347352&lt;/a&gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;assignee&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;Stuart McLaren&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;section id="end-of-add-vhdx-to-list-of-supported-disk-formats"&gt;
&lt;h3&gt;End of Add &lt;cite&gt;vhdx&lt;/cite&gt; to list of supported disk formats&lt;/h3&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="deprecate-show-multiple-locations-configuration-option"&gt;
&lt;h2&gt;Deprecate &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;show_multiple_locations&lt;/span&gt;&lt;/code&gt; configuration option&lt;/h2&gt;
&lt;dl class="field-list simple"&gt;
&lt;dt class="field-odd"&gt;problem&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;Glance currently has two ways in which locations can be
configured to be exposed to users :- 1) using
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;show_multiple_locations&lt;/span&gt;&lt;/code&gt; configuration option 2) Role Based Access
Control (RBAC) rules for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;delete_image_location&lt;/span&gt;&lt;/code&gt;,
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;get_image_location&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;set_image_location&lt;/span&gt;&lt;/code&gt;. If a cloud operator
chooses to disable exposing multiple locations using 1), the approach
in 2) becomes redundant.  Also, it can be somewhat confusing for
operators to have multiple ways to tune a particular feature. If
proper defaults are set and documentation for setting appropriate
policies exists, configuration option &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;show_multiple_locations&lt;/span&gt;&lt;/code&gt;
doesn’t hold much value.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;solution&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;We choose to deprecate the configuration option
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;show_multiple_locations&lt;/span&gt;&lt;/code&gt;. Moving forward the right way to control
the multiple locations feature will be using the Role Based Access
Control (RBAC) rules for Create, Read, Update and Delete (CRUD) on
locations. The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;policy.json&lt;/span&gt;&lt;/code&gt; file (example:
&lt;a class="reference external" href="http://git.openstack.org/cgit/openstack/glance/tree/etc/policy.json"&gt;http://git.openstack.org/cgit/openstack/glance/tree/etc/policy.json&lt;/a&gt;)
should be used to govern the access a particular &lt;cite&gt;role&lt;/cite&gt; has to the
location(s). This also ensures appropriate security measures are
taken into consideration by operators when using locations feature.
This encourages being aware of the kind of users this sensitive
feature will be exposed to rather than simple switching on/off a
single configuration option. However, for Newton release we will
only be deprecating the configuration option, no default values or
setting will be changed. Currently we disallow using multiple
locations by default, so the value of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;show_multiple_locations&lt;/span&gt;&lt;/code&gt;
option will be kept as &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;False&lt;/span&gt;&lt;/code&gt;. We would like to give some time to
the operators to understand how to control multiple locations using
this new RBAC method. In Ocata, we will be changing the default
values of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;delete_image_location&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;get_image_location&lt;/span&gt;&lt;/code&gt; and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;set_image_location&lt;/span&gt;&lt;/code&gt; policies and will be removing
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;show_multiple_locations&lt;/span&gt;&lt;/code&gt; option from the tree.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;impacts&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;This will have documentation and upgrade impact. Release note should
be added to notify interested parties about this addition.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;timeline&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;Expected to be merged within the N-3 time frame.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;link&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;&lt;a class="reference external" href="https://review.openstack.org/#/c/313936/"&gt;https://review.openstack.org/#/c/313936/&lt;/a&gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;assignee&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;Flavio Percoco&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;section id="end-of-deprecate-show-multiple-locations-configuration-option"&gt;
&lt;h3&gt;End of Deprecate &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;show_multiple_locations&lt;/span&gt;&lt;/code&gt; configuration option&lt;/h3&gt;
&lt;section id="add-your-spec-lite-before-this-line"&gt;
&lt;h4&gt;Add your Spec Lite before this line&lt;/h4&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;/section&gt;
</description><pubDate>Tue, 23 Jan 2018 00:00:00 </pubDate></item><item><title>Glance Store Spec Lite</title><link>http://specs.openstack.org/openstack/glance-specs/specs/newton/approved/glance_store/lite-specs.html</link><description>

&lt;p&gt;Please keep this template section in place and add your own copy of it between the markers.
Please fill only one Spec Lite per commit.&lt;/p&gt;
&lt;section id="title-of-your-spec-lite"&gt;
&lt;h2&gt;&amp;lt;Title of your Spec Lite&amp;gt;&lt;/h2&gt;
&lt;dl class="field-list simple"&gt;
&lt;dt class="field-odd"&gt;problem&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;&amp;lt;What is the driver to make the change.&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;solution&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;&amp;lt;High level description what needs to get done. For example: “We need to
add client function X.Y.Z to interact with new server functionality Z”.&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;impacts&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;&amp;lt;All possible *Impact flags (same as in commit messages) or ‘None’.&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;section id="optionals-please-remove-this-line-and-fill-or-remove-the-rest-until-end-of-template"&gt;
&lt;h3&gt;Optionals (please remove this line and fill or remove the rest until End of Template):&lt;/h3&gt;
&lt;dl class="field-list simple"&gt;
&lt;dt class="field-odd"&gt;how&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;&amp;lt;More technical details than the high level overview of &lt;cite&gt;solution&lt;/cite&gt; if needed.&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;alternatives&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;&amp;lt;Any alternative approaches that might be worth of bringing to discussion.&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;timeline&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;&amp;lt;Estimation of the time needed to complete the work.&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;link&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;&amp;lt;Link to the change in gerrit that already would provide the &lt;cite&gt;solution&lt;/cite&gt;.
After committing the Spec Lite depend the change to the Spec Lite commit.&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;reviewers&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;&amp;lt;If reviewers has been agreed for the functionality, list them here.&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;assignee&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;&amp;lt;If known, list who is going to work on the feature implementation here&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="end-of-template"&gt;
&lt;h3&gt;End of Template&lt;/h3&gt;
&lt;section id="add-your-spec-lite-before-this-line"&gt;
&lt;h4&gt;Add your Spec Lite before this line&lt;/h4&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;/section&gt;
</description><pubDate>Tue, 23 Jan 2018 00:00:00 </pubDate></item><item><title>Database strategy for rolling upgrades</title><link>http://specs.openstack.org/openstack/glance-specs/specs/ocata/implemented/glance/database-strategy-for-rolling-upgrades.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/glance/+spec/database-strategy-for-rolling-upgrades"&gt;https://blueprints.launchpad.net/glance/+spec/database-strategy-for-rolling-upgrades&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This spec outlines a database modification strategy for Glance that will
facilitate zero-downtime rolling upgrades and make it possible for Glance
to assert the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;assert:supports-zero-downtime-upgrade&lt;/span&gt;&lt;/code&gt; tag.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;In order to apply the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;assert:supports-zero-downtime-upgrade&lt;/span&gt;&lt;/code&gt; tag &lt;a class="reference internal" href="#gvv2" id="id1"&gt;&lt;span&gt;[GVV2]&lt;/span&gt;&lt;/a&gt;
to Glance, the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;assert:supports-rolling-upgrade&lt;/span&gt;&lt;/code&gt; tag &lt;a class="reference internal" href="#gvv1" id="id2"&gt;&lt;span&gt;[GVV1]&lt;/span&gt;&lt;/a&gt; must first be
asserted.  It states that&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;The project has a defined plan that allows operators to roll out new code to
subsets of services, eliminating the need to restart all services on new code
simultaneously.&lt;/p&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;In order to assert the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;assert:supports-zero-downtime-upgrade&lt;/span&gt;&lt;/code&gt; tag, Glance
must completely eliminate API downtime of the control plane during the upgrade.
A key issue for Glance in this regard is how to handle database changes
required for release N while release N-1 code is still running.  We outline a
strategy by which this may be accomplished below.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;In what follows, we make the assumption that an operator interested
in rolling upgrades will meet us halfway, that is, will be using an
up-to-date version of the underlying DBMS that supports online schema
changes that allow as much concurrency as possible.&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;We propose an expand and contract strategy to implement database changes
in such a way that a rolling upgrade may be accomplished within the confines
of a single release. Some OpenStack services, such as Cinder, that have
addressed this problem have chosen to make database changes over a sequence of
releases, but we believe that given the structure of Glance and typical usage
patterns, database changes can be made and finalized within a single release.
Such an approach is preferable for an open source project in which the cast of
characters may change considerably from cycle to cycle.&lt;/p&gt;
&lt;p&gt;We first present an overview of the upgrade strategy and then provide a
detailed example of how this will work for a change that will be occurring in
the Ocata release.&lt;/p&gt;
&lt;section id="overview"&gt;
&lt;h3&gt;Overview&lt;/h3&gt;
&lt;p&gt;The following diagram depicts a typical upgrade of an OpenStack service. The
older services are shutdown completely (mostly during a maintenance window),
the new code is deployed and finally the new services are started. Obviously,
this involves some downtime for the users. To minimize/eliminate downtime, the
services can be upgraded in a rolling fashion, that is, upgrading few services
at a time. This results in a situation where both old (say N-1) and new (say N)
services must co-exist for a certain period of time. In a straightforward
upgrade where the new services have no database changes associated with them,
the services can co-exist right from the onset as both rely on the same schema.&lt;/p&gt;
&lt;pre class="literal-block"&gt;​                              |        |         |
​                              |        |         |
​                              |        |         |
​     -----------------------+ |        |         | +---------------------
​                            | |     Deploy N     | |
​                  N-1       | |  (upgrade code   | |     N
​                            | |  and/or config   | |
​     -----------------------+ |  and migrate db) | +---------------------
​                              |        |         |
​                            Stop N-1   |       Start N
​                            Services   |       Services
​                              |        |         |
​                              |        |         |
​                              |        |         |
​                              |        |         |
​                              |        |         |
​                              |        |         |
​
​                               &amp;lt;----------------&amp;gt;
​                                     Downtime
​                               &amp;lt;----------------&amp;gt;&lt;/pre&gt;
&lt;p&gt;However, in the presence of database changes it isn’t yet possible for the
services to co-exist. The primary reason is the way we do database
changes/migrations currently. A typical migration in Glance is an atomic change
that includes both schema and corresponding data migrations together.
While the schema migrations perform necessary additions/removals/modifications
to the schema, data migrations perform corresponding changes to the data.
This approach at times, depending on the nature of schema changes, is
backwards-incompatible. That is, older services may not be able to run with new
schema. This essentially limits the ability for old and new services to
co-exist and consequently prohibits rolling upgrades.&lt;/p&gt;
&lt;p&gt;To achieve rolling upgrades, database migrations need to be done in such a way
that both old and new services can co-exist over a period of time. A well known
strategy is to re-imagine database changes in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;expand&lt;/span&gt; &lt;span class="pre"&gt;and&lt;/span&gt; &lt;span class="pre"&gt;contract&lt;/span&gt;&lt;/code&gt; style
instead of one atomic change. With the expand and contract style, we achieve
the desired schema changes in two distinct steps:&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Expand&lt;/strong&gt;: In the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;expand&lt;/span&gt;&lt;/code&gt; step, we make &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;only&lt;/span&gt; &lt;span class="pre"&gt;additive&lt;/span&gt; &lt;span class="pre"&gt;changes&lt;/span&gt;&lt;/code&gt;
that are required by the new services. This keeps the schema intact for
older services to run along with the new services. The typical schema
changes that fall into this category are adding columns and tables.&lt;/p&gt;
&lt;p&gt;An exception to this additive-only change strategy is that it may
be necessary to remove some constraints in order to allow database
triggers (discussed below) to work.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Contract&lt;/strong&gt;: All the other changes, that is &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;non-additive&lt;/span&gt; &lt;span class="pre"&gt;changes&lt;/span&gt;&lt;/code&gt;,
are grouped into &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;contract&lt;/span&gt;&lt;/code&gt; step. Changes like removing a column, table
and/or constraints are made in this step.&lt;/p&gt;
&lt;p&gt;Additionally, if any constraints were removed during the expand
step, they are restored during the contract phase.  Any database
triggers installed during the expand phase are also removed at this
point.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;This breakup gives us the ability to perform the minimum required changes
first (while keeping schema compatibility with old services) and delay the
other changes until a later point in time. Therefore, we always first expand
the database in order to start a rolling upgrade while the old services are
still running. Once the database is expanded, the new columns and tables are
created. However, they would be empty. At this point, we should start migrating
the data over to the new column. But, at the same time, it is important to
keep the new and old columns in sync. Any writes to old column must be sync-ed
to the new column. And, vice-versa (although we don’t write to the new column
yet, we have to keep the old column in sync when the new services come up and
start writing to the new column while the services co-exist). We use &lt;strong&gt;database
triggers&lt;/strong&gt; to keep the columns in sync.&lt;/p&gt;
&lt;p&gt;We add the triggers to the database along with the additive changes
during the database expand. At this point, we start migrating the data over to
the new column. However, because the old services are live at this point, we
migrate the data in small batches to avoid excessive load on the database and
thereby any interruption to the old services. These migrations can be scheduled
to run during low-traffic hours to minimize impact on older services. Once the
data migrations finish, the new column is populated and ready for use, we start
deploying the new services.&lt;/p&gt;
&lt;p&gt;We deploy services in small batches by taking some nodes out of rotation,
wait for them to drain connections, upgrade the services and put the nodes back
into rotation. It is during this period that old and new services co-exist.
When the new services come up, they start reading from and writing to the new
column. Any data written to the new column is synced over to the old column (by
the triggers added during database expand) and available for older services to
consume. Once all the older services are upgraded, it is now safe to contract
the database. This ensures that we reach the desired state of database schema.
We also drop the database triggers during the database contract because
the old column would cease to exist and only the new column would be in use.&lt;/p&gt;
&lt;pre class="literal-block"&gt;​         ---------------------------------------+
​                                                |
​                         N-1                    |
​                                                |
​         ---------------------------------------+
​
​                 |    |           |    |         |     |
​                 |    |        Finish  |         |     |
​                 |    |         Data   |
​              Expand  |      Migrations| +----------------------------
​             Database |           |    | |
​                 &amp;amp;    |           |    | |     N
​                Add   |           |    | |
​              Triggers|           |    | +----------------------------
​                 |    |           |    |
​                 |    |           | Start N      |     |
​                 |  Start         |  Deploy      | Contract
​                 |  Data          |    |         | Database
​                 | Migrations     |    |         |     &amp;amp;
​                 |    |           |    |         |   Drop
​                 |    |           |    |         |  Triggers
​                 |    |           |    |     Finish N  |
​                 |    |           |    |      Deploy   |
​                 |    |           |    |         |     |
​                 |    |           |    |         |     |&lt;/pre&gt;
&lt;p&gt;To summarize, as shown in the above diagram, we split the database migrations
into schema and data migrations. The schema migrations can be additive or
contractive in nature, or a combination of both. Additive schema migrations are
run before the upgrade begins to prepare the database for new services while it
is still usable by old services.  (This phase is also called “database
expand”.) During database expand, we also add triggers on old and new columns
to keep them in sync. Once the database is expanded, we start migrating the
data over to the new column in small batches.  When the data migrations are
complete, we upgrade the old services in a rolling fashion. Once all the old
services are upgraded, we run the contractive migrations on the database.
(This phase is also called “database contract”.) The triggers are also dropped
during database contract.&lt;/p&gt;
&lt;p&gt;In addition to the description of the process given above, here are a few
constraints on how upgrades will work:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;A typical upgrade is complete only when the entire expand-migrate-contract
cycle for a release is performed.  We do &lt;em&gt;not&lt;/em&gt; propose to support an N-1 to
N upgrade while an N-2 to N-1 upgrade is in progress.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;“Leapfrogging” releases (that is, allowing a direct N-2 to N upgrade,
skipping N-1) is &lt;em&gt;not&lt;/em&gt; supported.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It’s possible that in a single release there may be multiple features, worked
on independently by different developers, that will require some kind of
database modification.  What we are proposing in this spec is that for each
release, there will be a &lt;em&gt;single&lt;/em&gt; expand-migrate-contract operation from the
operator’s point of view.  In other words, all feature teams will have to
coordinate so that all expands are performed, followed by all migrations, and
concluding with all contractions.  This will be easy for features whose
changes are completely independent, but may be more difficult for others.
However, preserving zero-downtime database changes will be a Glance project
priority once this spec has been approved, so such interactions will be
addressed on the specs for features.&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 Glance spec template asks this question in the “Data
model impact” section:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;What database migrations will accompany this change?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This should be modified along the following lines.  (Note: this is
only a suggestion, we can argue about the best wording on the patch
that modifies the spec template.)&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Glance is committed to zero-downtime database migrations.
Explain what database migrations will accompany this change.
Do they have the potential to interfere with the database
migrations for other specs that have been approved for this
cycle?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;p&gt;Keep in mind that our goal here is to achieve the upgrade tags.  While it’s
not &lt;em&gt;prohibited&lt;/em&gt; to exceed them, they do specify a baseline for achievement
that’s been adopted by the OpenStack community.  Hence simply meeting the
requirements for the tags is a worthwhile goal.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="steps"&gt;
&lt;h3&gt;Steps&lt;/h3&gt;
&lt;p&gt;Let’s look at a rolling-upgrade strategy for Glance in more detail. Consider
the case where a database change is made such that data stored in
“the old column” in release N-1 will be stored in “the new column” in
release N. The following are steps that we take to achieve rolling-upgrade.&lt;/p&gt;
&lt;section id="expand-database"&gt;
&lt;h4&gt;Expand Database&lt;/h4&gt;
&lt;p&gt;Goal: Prepare database for N by expanding the database&lt;/p&gt;
&lt;p&gt;As shown in the below diagram, initially, we have N-1 reading from and writing
to the old column. We then expand the schema for N which introduces the new
column while N-1 is still running. This should have minimal to no impact on N-1
services.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;It is important to note that while database expand operations are
required to be strictly additive in nature, adding constraints can
sometimes be disruptive as they are known to lock the table.  This is
alleviated by online DDL capabilities in MySQL 5.6 for InnoDB. So, simple
changes may not be a concern.  (In any case, the plan proposed in this spec
adds constraints during the contract phase only.)&lt;/p&gt;
&lt;/div&gt;
&lt;pre class="literal-block"&gt;​     -----------------------------------------------------------
​
​                               N-1
​
​     -------+-----------------------+---------------------------
​            |                       |
​            |           |           |                          |
​         Read/Write     |        Read/Write                    |
​            |       Expand N        |                          |
​            |           &amp;amp;           |                        Start
​       +----v-----+    Add     +----v-----+----------+        Data
​       |   Old    |  Triggers  |   Old    |   New    |     Migrations
​       +----------+     |      +---------------------+         |
​       |          |     |      |          |          |         |
​       |          |     |      |          |          |         |
​       |          |     |      |          |          |         |
​       |          |     |      |          |          |         |
​       |          |     |      |          |          |         |
​       |          |     |      |          |          |         |
​       |          |     |      |          |          |         |
​       |          |     |      |          |          |         |
​       |          |     |      |          |          |         |
​       |          |     |      |          |          |         |
​       +----------+     |      +----------+----------+         |
​                        |          ^             ^             |
​                        |          |  Triggers   |             |
​                        |          +-------------+             |
​                        |                                      |
​                        | &amp;lt;--------------------------------- &amp;gt; |
​                        |           Expand Database            |
​                        | &amp;lt;--------------------------------- &amp;gt; |&lt;/pre&gt;
&lt;p&gt;While expanding the database, we also add triggers that keep the old and new
columns in sync.&lt;/p&gt;
&lt;p&gt;Deliverable: We propose to make this available by extending the glance-manage
utility with an expand command. The database could be expanded by running
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance-manage&lt;/span&gt; &lt;span class="pre"&gt;db&lt;/span&gt; &lt;span class="pre"&gt;expand&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="migrate-data"&gt;
&lt;h4&gt;Migrate Data&lt;/h4&gt;
&lt;p&gt;Goal: Populate the new column(s) for N to use&lt;/p&gt;
&lt;p&gt;At this point, only release N code is running and it continues to read from and
write to the old column as shown in the below diagram. All writes made by N-1
to the old column are synced with the new column. While the triggers slowly
start populating the new column, we commence the background data migrations to
populate data into the new column in a non-intrusive manner.&lt;/p&gt;
&lt;pre class="literal-block"&gt;​       -------------------------------------------------
​
​                           N-1
​
​       -----------------+-------------------------------
​                        |
​            |           |                          |
​            |        Read/Write                    |
​            |           |                          |
​          Start         |                        Finish
​          Data     +----v-----+----------+        Data
​       Migrations  |   Old    |   New    |     Migrations
​            |      +---------------------+         |
​            |      |          |          |         |
​            |      |          |          |         |
​            |      |          |          |         |
​            |      |          |          |         |
​            |      |          |          |         |
​            |      |          |          |         |
​            |      |          |          |         |
​            |      |          |          |         |
​            |      |          |          |         |
​            |      |          |          |         |
​            |      +----------+----------+         |
​            |          ^             ^             |
​            |          |  Triggers   |             |
​            |          +-------------+             |
​            |                                      |
​            | &amp;lt;--------------------------------- &amp;gt; |
​            |            Migrate Data              |
​            | &amp;lt;--------------------------------- &amp;gt; |&lt;/pre&gt;
&lt;p&gt;Deliverable: We propose to extend the glance-manage utility to migrate the data
in batches. The batch size could be controlled with an optional parameter, for
example, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;max_rows&lt;/span&gt;&lt;/code&gt;.  The parameter would allow operators to schedule
migrations of no more than N rows at a time, in case they have a large database
and want to run the migration only during off-peak times.  Without the optional
parameter, all rows would be migrated.  The utility will return an appropriate
response if it’s run and it finds that there are no rows that need to be
migrated.&lt;/p&gt;
&lt;p&gt;For example: &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance-manage&lt;/span&gt; &lt;span class="pre"&gt;db&lt;/span&gt; &lt;span class="pre"&gt;migrate&lt;/span&gt; &lt;span class="pre"&gt;--max_rows=10&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="deploy"&gt;
&lt;h4&gt;Deploy&lt;/h4&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Goal: Deploy N by upgrading N-1 in a rolling fashion and have both versions&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;co-exist during the deploy&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;As the new column is now ready to use, we start deploying N in small batches.
Release N-1 has no idea that an upgrade is occurring, but the release N code is
co-existing with N-1 services as shown in the below diagram. While N-1 and N
services are using the old and new column respectively, the triggers are
keeping the two columns in sync whenever there is a database write. This
enables N to see the updates made by N-1 and vice-versa.&lt;/p&gt;
&lt;pre class="literal-block"&gt;​                ------------------------------------+
​                                                    |
​                                    N-1             |
​                                                    |
​                --------------+---------------------+    |
​                              |                          |
​                   |          |
​                   |          |   +------------------------------
​                   |          |   |
​                   |          |   |   N
​                   |          |   |
​                   |          |   +-------+----------------------
​                   |          |           |
​                   |        Read/       Read/            |
​                   |        Write       Write            |
​                   |          |           |              |
​                   |          |           |              |
​                   |      +---v------+----v-----+     Finish N
​                   |      |  Old     |   New    |      Deploy
​                Start N   +---------------------+        |
​                Deploy    |          |          |        |
​                   |      |          |          |        |
​                   |      |          |          |        |
​                   |      |          |          |        |
​                   |      |          |          |        |
​                   |      |          |          |        |
​                   |      |          |          |        |
​                   |      |          |          |        |
​                   |      |          |          |        |
​                   |      |          |          |        |
​                   |      +----------+----------+        |
​                   |          ^             ^            |
​                   |          |  Triggers   |            |
​                   |          +-------------+            |
​                   |                                     |
​                   |                                     |
​                   |    &amp;lt;----------------------------&amp;gt;   |
​                   |               Deploy                |
​                   |    &amp;lt;----------------------------&amp;gt;   |
​                   |                                     |
​&lt;/pre&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;As the N-1 and N services co-exist, users may notice inconsistent behavior
in certain situations. Typically, a new release is backwards-compatible
with the previous release. As such, all requests should exhibit similar
behavior across both versions. However, some changes to the API (for
example: bug fixes) may result in different behavior across two releases.
So, a user may witness different responses to similar requests depending
upon which service processes the request.&lt;/p&gt;
&lt;p&gt;Similarly, user requests for new features introduced with the new version,
may fail when they are processed by an older service. While this
inconsistency is not desirable, it could be seen as a decent compromise
over incurring downtime during the upgrade.&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="contract-database"&gt;
&lt;h4&gt;Contract Database&lt;/h4&gt;
&lt;p&gt;Goal: Complete the schema migrations desired in N&lt;/p&gt;
&lt;p&gt;When all the services are upgraded, the old column is unused. The new column
would be the source of truth henceforth. The old column is ready for removal.
At this point, we contract the database, which drops the old column and
triggers added during database expand.&lt;/p&gt;
&lt;pre class="literal-block"&gt;​              |
​              |
​
​         -------------------------------------------
​
​                                N
​
​         -----------------------+-------------------
​                                |
​              |               Read/
​              |               Write
​              |                 |
​              |                 |
​          Contract          +---v----+
​           Database         |   New  |
​              &amp;amp;             +--------+
​            Drop            |        |
​           Triggers         |        |
​              |             |        |
​              |             |        |
​              |             |        |
​              |             |        |
​              |             |        |
​              |             |        |
​              |             |        |
​              |             |        |
​              |             ---------+
​              |
​              |
​              |     &amp;lt;-----------------------&amp;gt;
​              |         Contract Database
​              |     &amp;lt;-----------------------&amp;gt;
​              |&lt;/pre&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;In addition to removing the unused columns and tables, SQL constraints such
as nullability, unique and default must be set here.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Deliverable: We propose to make this available by extending the glance-manage
utility with a contract command. The database could be contracted by running
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance-manage&lt;/span&gt; &lt;span class="pre"&gt;db&lt;/span&gt; &lt;span class="pre"&gt;contract&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="rolling-upgrade-process-for-operators"&gt;
&lt;h3&gt;Rolling Upgrade Process for Operators&lt;/h3&gt;
&lt;p&gt;Following is the process to upgrade Glance with zero downtime:&lt;/p&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;&lt;p&gt;Backup Glance database.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Choose an arbitrary Glance node or provision a new node to install the new
release. If an existing Glance node is chosen, gracefully stop the Glance
services.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Upgrade the above chosen node with new release and update the configuration
accordingly. However, Glance services MUST NOT be started just yet.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Using the upgraded node, expand the database using the command
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance-manage&lt;/span&gt; &lt;span class="pre"&gt;db&lt;/span&gt; &lt;span class="pre"&gt;expand&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Then, schedule the data migrations using the command
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance-manage&lt;/span&gt; &lt;span class="pre"&gt;db&lt;/span&gt; &lt;span class="pre"&gt;migrate&lt;/span&gt; &lt;span class="pre"&gt;--max_rows=&amp;lt;max.&lt;/span&gt; &lt;span class="pre"&gt;row&lt;/span&gt; &lt;span class="pre"&gt;count&amp;gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;Data migrations must be scheduled to run until no more rows are left to
migrate.&lt;/p&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Start the Glance processes on the first node.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Taking one node at a time from the remaining nodes, stop the Glance
processes, upgrade to the new release (and corresponding configuration) and
start the Glance processes.&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;Before stopping the Glance processes on a node, one may choose to wait
until all the existing connections drain out. This could be achieved by
taking the node out of rotation. This way all the requests that are
currently being processed will get a chance to finish processing.
However, some Glance requests like uploading and downloading images
may last a long time. This increases the wait time to drain out all
connections and consequently the time to upgrade Glance completely.
On the other hand, stopping the Glance services before the connections
drain out will present the user with errors. This can at times be seen as
downtime as well. Hence, an operator must be judicious when stopping the
services.&lt;/p&gt;
&lt;/div&gt;
&lt;ol class="arabic simple" start="8"&gt;
&lt;li&gt;&lt;p&gt;Contract the database by running the command
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance&lt;/span&gt; &lt;span class="pre"&gt;manage&lt;/span&gt; &lt;span class="pre"&gt;db&lt;/span&gt; &lt;span class="pre"&gt;contract&lt;/span&gt;&lt;/code&gt; from any one of the nodes.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
&lt;section id="example"&gt;
&lt;h3&gt;Example&lt;/h3&gt;
&lt;p&gt;To understand how this would work in action, consider the following example of
a Glance database change proposed for Ocata.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This does not prescribe the actual Ocata database change.  It is
included here as a realistic example for a sanity check of this
proposal.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;The “old column”: Newton (release N-1): boolean &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;is_public&lt;/span&gt;&lt;/code&gt; column in images
table.  This column has nullable=False and default=False.&lt;/p&gt;
&lt;p&gt;The “new column”: Ocata (release N) : enum (or string … key point is it’s a
different data type) &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;visibility&lt;/span&gt;&lt;/code&gt; column in images table.  This column can
have one of the values ‘public’, ‘private’, ‘shared’, ‘community’.  After the
database contraction has completed, this column would have
nullable=False, and default=’private’.  (During the migrate and deploy phases,
this column will probably have nullable=true with no default.)&lt;/p&gt;
&lt;p&gt;Using the proposed strategy, the database upgrade would proceed as follows.&lt;/p&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;&lt;p&gt;Pre-upgrade: Version N-1 code read/write to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;is_public&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Expand Database: Add the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;visibility&lt;/span&gt;&lt;/code&gt; column and the appropriate triggers
to keep the old and new values in sync.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Migrate Data: Crawl the ‘images’ table.  For any row where
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;visibility&lt;/span&gt;&lt;/code&gt; is null, set the value for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;visibility&lt;/span&gt;&lt;/code&gt; as follows:&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;is_public&lt;/span&gt;&lt;/code&gt; is ‘1’: set visibility to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;public&lt;/span&gt;&lt;/code&gt;&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;is_public&lt;/span&gt;&lt;/code&gt; is ‘0’: if the image has any members, set visibility to
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;shared&lt;/span&gt;&lt;/code&gt;; otherwise set visibility to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;private&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Migrate any data (using triggers) written by N-1 code to the old column
using the above criteria.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Deploy: Deploy N code in a rolling fashion. N code will start using the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;visibility&lt;/span&gt;&lt;/code&gt; column.&lt;/p&gt;
&lt;p&gt;Here’s an analysis of database activity.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Write operations&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The v1 API&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;nothing to worry about, has no concept of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;visibility&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 v2 API&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;visibility&lt;/span&gt;&lt;/code&gt; set to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;public&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;N-1: will put ‘1’ in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;is_public&lt;/span&gt;&lt;/code&gt;
* Triggers will put ‘public’ in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;visibility&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;N: will put ‘public’ in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;visibility&lt;/span&gt;&lt;/code&gt;
* Triggers will put ‘1’ in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;is_public&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;visibility&lt;/span&gt;&lt;/code&gt; set to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;private&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;N-1: will put ‘0’ in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;is_public&lt;/span&gt;&lt;/code&gt;
* Triggers will put ‘private’ in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;visibility&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;N: will put ‘private’ in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;visibility&lt;/span&gt;&lt;/code&gt;
* Triggers will put ‘0’ in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;is_public&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;visibility&lt;/span&gt;&lt;/code&gt; set to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;community&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;N-1: call will fail at API level, will never hit the database&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;N: will put ‘community’ in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;visibility&lt;/span&gt;&lt;/code&gt;
* Triggers will put ‘0’ in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;is_public&lt;/span&gt;&lt;/code&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 essentially means that a community image will be considered
as private image by N-1. Thus, barring the owner, a community
image won’t be visible to any one. Since N-1 has no notion of
community images, this behavior can be seen as consistent with
respect to N-1. However, it may be confusing the owner of the
community image for whom the image will appear as community with
N and private with N-1. Thus, the owner may try to change the
visibility again. To discourage this, we may prohibit any writes
to the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;is_public&lt;/span&gt;&lt;/code&gt; column when it has ‘0’ and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;visibility&lt;/span&gt;&lt;/code&gt;
column has &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;community&lt;/span&gt;&lt;/code&gt;. This could be done again by using the
same triggers that we added during database expand. The first
alternative mentioned in the alternatives section avoids this
situation.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/blockquote&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;visibility&lt;/span&gt;&lt;/code&gt; set to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;shared&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;N-1: call will fail at API level, will never hit the database&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;N: will write ‘shared’ in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;visibility&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Triggers will write ‘0’ in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;is_public&lt;/span&gt;&lt;/code&gt;; this will allow image
sharing to continue to work properly on the release N-1 nodes as
well as the v1 API on all nodes.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Read operations&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Read operations across API versions and releases should remain
unaffected as the triggers keep both old and new columns in sync by
translating the data appropriately.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Contract Database: The only API nodes running are version N.
The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;is_public&lt;/span&gt;&lt;/code&gt; column is no longer in use. Drop &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;is_public&lt;/span&gt;&lt;/code&gt; and add
nullable=True and default=private on &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;visibility&lt;/span&gt;&lt;/code&gt; column.&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;ol class="arabic"&gt;
&lt;li&gt;&lt;p&gt;This is a small variant of the above described strategy. The fundamental
idea behind the above described strategy is: When both versions co-exist,
sync the writes made by one set of services to be available for the others
to consume. We achieve this using triggers. On the other hand, what if we
eliminate the need to sync? That is, what if we disallow any writes to both
old and the new columns while the services co-exist? This can be achieved by
using triggers again. Essentially, the triggers we add during the database
expand step will intercept and disallow writes to the old and new columns.&lt;/p&gt;
&lt;p&gt;For the above given example, all requests attempting to change the
visibility of image will fail for the duration of deploy step where the
services co-exist. Reads would be permitted, however. Once the deploy is
finished and we contract the database (the triggers are dropped here),
writes to new column would be permitted as usual. This gives us a way to
eliminate the need for syncing data across columns. Consequently, there is
much less complexity in the triggers and the upgrade is less error-prone.
However, it is important to note that one may see an increased error rate
during the deploy due to disallowed writes. Although the API will be
responsive throughout this entire period (and hence “up”), the increased
rate of 5xx responses will make it impossible to assert the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;assert:zero-downtime-upgrade&lt;/span&gt;&lt;/code&gt; tag &lt;a class="reference internal" href="#gvv2" id="id3"&gt;&lt;span&gt;[GVV2]&lt;/span&gt;&lt;/a&gt;.  Since being able to assert
this tag is the aim of this spec, this alternative is not acceptable.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A well known alternative replaces the use of triggers by migrating the data
online from within the application. While the triggers approach migrates the
data online on a database write operation, the other approach attempts to
migrate the data on an on-demand basis in the event of a database read
operation.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Approaches taken by other Openstack Projects:&lt;/p&gt;
&lt;p&gt;Nova: See &lt;a class="reference internal" href="#nov1" id="id4"&gt;&lt;span&gt;[NOV1]&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Cinder: See &lt;a class="reference internal" href="#cin1" id="id5"&gt;&lt;span&gt;[CIN1]&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Keystone: See &lt;a class="reference internal" href="#key1" id="id6"&gt;&lt;span&gt;[KEY1]&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Neutron: See &lt;a class="reference internal" href="#neu1" id="id7"&gt;&lt;span&gt;[NEU1]&lt;/span&gt;&lt;/a&gt;, &lt;a class="reference internal" href="#neu2" id="id8"&gt;&lt;span&gt;[NEU2]&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;There would be no impact to REST API contracts as such.&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 background data migration will consume extra database resources, but this
can be managed if the migration script is carefully written.&lt;/p&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;Deployers who intend to deploy Glance the old way, that is with downtime,
remain unaffected.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Each step of the migration requires operator intervention.&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;Any developer working on a feature that requires database changes must write
additional code to support the rolling upgrade strategy outlined in this
document.  By confining the database changes to a single release, however,
developers of release N+1 do not have to worry about completing procedures
begun during the migration of release N-1 to N.&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;alex_bash
hemanthm&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;nikhil&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 documentation for rolling upgrade (developer docs).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Write documentation for rolling upgrade (operator docs).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Introduce expand/contract migration streams and the corresponding
glance-manage CLI.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Work with the developers of Ocata features that require database changes
to implement code to follow the rolling upgrade strategy.  These include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;community images and enhanced image sharing&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;image import&lt;/p&gt;&lt;/li&gt;
&lt;/ul&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;In order to assert the rolling upgrades tag, Glance must have full stack
integration testing with a service arrangement that is representative of a
meaningful-to-operators rolling upgrade scenario.&lt;/p&gt;
&lt;p&gt;Ideally these tests will be able to simulate Glance running at scale, since, as
discussed above, some DBMS problems may not be revealed in a small test
database.&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;Developer documentation: the upgrade strategy.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Operator documentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;configuration options for putting the code into the various modes&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;running the database scripts&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;div role="list" class="citation-list"&gt;
&lt;div class="citation" id="gvv1" role="doc-biblioentry"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id2"&gt;GVV1&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://governance.openstack.org/reference/tags/assert_supports-rolling-upgrade.html"&gt;https://governance.openstack.org/reference/tags/assert_supports-rolling-upgrade.html&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class="citation" id="gvv2" role="doc-biblioentry"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;GVV2&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;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://governance.openstack.org/reference/tags/assert_supports-zero-downtime-upgrade.html"&gt;https://governance.openstack.org/reference/tags/assert_supports-zero-downtime-upgrade.html&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class="citation" id="nov1" role="doc-biblioentry"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id4"&gt;NOV1&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://www.danplanet.com/blog/2015/10/07/upgrades-in-nova-database-migrations/"&gt;http://www.danplanet.com/blog/2015/10/07/upgrades-in-nova-database-migrations/&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class="citation" id="cin1" role="doc-biblioentry"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id5"&gt;CIN1&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/cinder-specs/specs/mitaka/online-schema-upgrades.html"&gt;https://specs.openstack.org/openstack/cinder-specs/specs/mitaka/online-schema-upgrades.html&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class="citation" id="key1" role="doc-biblioentry"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id6"&gt;KEY1&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/keystone-specs/specs/mitaka/online-schema-migration.html"&gt;https://specs.openstack.org/openstack/keystone-specs/specs/mitaka/online-schema-migration.html&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class="citation" id="neu1" role="doc-biblioentry"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id7"&gt;NEU1&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/neutron-specs/specs/liberty/online-schema-migrations.html"&gt;https://specs.openstack.org/openstack/neutron-specs/specs/liberty/online-schema-migrations.html&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class="citation" id="neu2" role="doc-biblioentry"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id8"&gt;NEU2&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://docs.openstack.org/developer/neutron/devref/upgrade.html"&gt;http://docs.openstack.org/developer/neutron/devref/upgrade.html&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
</description><pubDate>Mon, 27 Nov 2017 00:00:00 </pubDate></item><item><title>Archived Priority Lists</title><link>http://specs.openstack.org/openstack/glance-specs/previous-priorities.html</link><description>

&lt;p&gt;During each Project Team Gathering (or “design summit”), we agree on what the
whole community wants to focus on for the upcoming release. This is the
historical archive of the output of those discussions.&lt;/p&gt;
&lt;div class="toctree-wrapper compound"&gt;
&lt;ul&gt;
&lt;li class="toctree-l1"&gt;&lt;a class="reference internal" href="priorities/2023.1-priorities.html"&gt;2023.1 Project Priorities&lt;/a&gt;&lt;/li&gt;
&lt;li class="toctree-l1"&gt;&lt;a class="reference internal" href="priorities/2023.2-priorities.html"&gt;2023.2 Project Priorities&lt;/a&gt;&lt;/li&gt;
&lt;li class="toctree-l1"&gt;&lt;a class="reference internal" href="priorities/2024.1-priorities.html"&gt;2024.1 Project Priorities&lt;/a&gt;&lt;/li&gt;
&lt;li class="toctree-l1"&gt;&lt;a class="reference internal" href="priorities/2024.2-priorities.html"&gt;2024.2 Project Priorities&lt;/a&gt;&lt;/li&gt;
&lt;li class="toctree-l1"&gt;&lt;a class="reference internal" href="priorities/2025.1-priorities.html"&gt;2025.1 Project Priorities&lt;/a&gt;&lt;/li&gt;
&lt;li class="toctree-l1"&gt;&lt;a class="reference internal" href="priorities/2025.2-priorities.html"&gt;2025.2 Project Priorities&lt;/a&gt;&lt;/li&gt;
&lt;li class="toctree-l1"&gt;&lt;a class="reference internal" href="priorities/2026.1-priorities.html"&gt;2026.1 Project Priorities&lt;/a&gt;&lt;/li&gt;
&lt;li class="toctree-l1"&gt;&lt;a class="reference internal" href="priorities/2026.2-priorities.html"&gt;2026.2 Project Priorities&lt;/a&gt;&lt;/li&gt;
&lt;li class="toctree-l1"&gt;&lt;a class="reference internal" href="priorities/mitaka-priorities.html"&gt;Mitaka Project Priorities&lt;/a&gt;&lt;/li&gt;
&lt;li class="toctree-l1"&gt;&lt;a class="reference internal" href="priorities/newton-priorities.html"&gt;Newton Review Priorities&lt;/a&gt;&lt;/li&gt;
&lt;li class="toctree-l1"&gt;&lt;a class="reference internal" href="priorities/ocata-priorities.html"&gt;Ocata Review Priorities&lt;/a&gt;&lt;/li&gt;
&lt;li class="toctree-l1"&gt;&lt;a class="reference internal" href="priorities/pike-priorities.html"&gt;Pike Review Priorities&lt;/a&gt;&lt;/li&gt;
&lt;li class="toctree-l1"&gt;&lt;a class="reference internal" href="priorities/queens-priorities.html"&gt;Queens Review Priorities&lt;/a&gt;&lt;/li&gt;
&lt;li class="toctree-l1"&gt;&lt;a class="reference internal" href="priorities/rocky-priorities.html"&gt;Rocky Review Priorities&lt;/a&gt;&lt;/li&gt;
&lt;li class="toctree-l1"&gt;&lt;a class="reference internal" href="priorities/stein-priorities.html"&gt;Stein Project Priorities&lt;/a&gt;&lt;/li&gt;
&lt;li class="toctree-l1"&gt;&lt;a class="reference internal" href="priorities/train-priorities.html"&gt;Train Project Priorities&lt;/a&gt;&lt;/li&gt;
&lt;li class="toctree-l1"&gt;&lt;a class="reference internal" href="priorities/ussuri-priorities.html"&gt;Ussuri Project Priorities&lt;/a&gt;&lt;/li&gt;
&lt;li class="toctree-l1"&gt;&lt;a class="reference internal" href="priorities/victoria-priorities.html"&gt;Victoria Project Priorities&lt;/a&gt;&lt;/li&gt;
&lt;li class="toctree-l1"&gt;&lt;a class="reference internal" href="priorities/wallaby-priorities.html"&gt;Wallaby Project Priorities&lt;/a&gt;&lt;/li&gt;
&lt;li class="toctree-l1"&gt;&lt;a class="reference internal" href="priorities/xena-priorities.html"&gt;Xena Project Priorities&lt;/a&gt;&lt;/li&gt;
&lt;li class="toctree-l1"&gt;&lt;a class="reference internal" href="priorities/yoga-priorities.html"&gt;Yoga Project Priorities&lt;/a&gt;&lt;/li&gt;
&lt;li class="toctree-l1"&gt;&lt;a class="reference internal" href="priorities/zed-priorities.html"&gt;Zed Project Priorities&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
</description><pubDate>Mon, 30 Oct 2017 00:00:00 </pubDate></item><item><title>Spec Lite: Actually Deprecate the Glance Registry</title><link>http://specs.openstack.org/openstack/glance-specs/specs/queens/implemented/glance/deprecate-registry.html</link><description>

&lt;dl class="field-list simple"&gt;
&lt;dt class="field-odd"&gt;problem&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;A spec to &lt;a class="reference external" href="http://specs.openstack.org/openstack/glance-specs/specs/newton/approved/glance/deprecate-registry.html"&gt;Deprecate the Glance Registry Service&lt;/a&gt; was accepted in
Newton, but it contained the ambiguous statement, “Mark the service
as deprecated and ready for removal in the Q release.”  It’s now
the Q release, so we need to actually deprecate it by announcing
officially that &lt;em&gt;the Registry Service is deprecated in Queens and
subject to removal in the S release.&lt;/em&gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;solution&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;On startup, the Registry Service should output an appropriate
message to the log.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;timeline&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;Q-1 milestone (week of 16 October 2017)&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;link&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/glance/+spec/deprecate-registry"&gt;https://blueprints.launchpad.net/glance/+spec/deprecate-registry&lt;/a&gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;reviewers&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;all core reviewers&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;assignee&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;rosmaita&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
</description><pubDate>Mon, 30 Oct 2017 00:00:00 </pubDate></item><item><title>Spec Lite: Neutralize Language</title><link>http://specs.openstack.org/openstack/glance-specs/specs/untargeted/glance_store/neutralize-language.html</link><description>

&lt;dl class="field-list"&gt;
&lt;dt class="field-odd"&gt;problem&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;The glance_store library is being consumed by another project (Glare)
but much of the language in Exception messages, log messages, and
configuration option help text talks about “images”.&lt;/p&gt;
&lt;p&gt;Additionally, some of the names of configuration options are
image-centric.  (Actually, I could only find one of these):&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;vmware_store_image_dir&lt;/span&gt;&lt;/code&gt; (and its default value is
‘openstack_glance’)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;solution&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Make the language in Exception messages, log messages, and
the configuration option help text neutral, for example, replace
‘image’ by ‘object’ and any other appropriate language changes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Introduce new configuration options for any options with
image-centric names and deprecate the old options using the
facilities oslo.config supplies for this purpose.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;impacts&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;The deprecated options will be listed in a release note.&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
</description><pubDate>Mon, 30 Oct 2017 00:00:00 </pubDate></item><item><title>Spec Lite: Rolling Upgrade Testing</title><link>http://specs.openstack.org/openstack/glance-specs/specs/untargeted/glance/lite-spec-rolling-upgrade-tests.html</link><description>

&lt;dl class="field-list simple"&gt;
&lt;dt class="field-odd"&gt;problem&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/glance/+spec/database-strategy-for-rolling-upgrades"&gt;Zero-downtime database upgrades&lt;/a&gt; were introduced on an EXPERIMENTAL
basis in the Ocata release to facilitate rolling upgrades.  In order
for rolling upgrades to be considered officially supported, and to
allow Glance to assert the associated TC tags, we need to have
in-gate testing of upgrades.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;solution&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;Add in-gate testing of upgrades using Grenade or some other
appropriate framework.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;impacts&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;DocImpact: update the docs to reflect the non-experimental status
of zero-downtime database upgrades.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;link&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/glance/+spec/rolling-upgrade-tests"&gt;https://blueprints.launchpad.net/glance/+spec/rolling-upgrade-tests&lt;/a&gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
</description><pubDate>Sat, 28 Oct 2017 00:00:00 </pubDate></item><item><title>Lite Spec: Community Goal: Control Plane API endpoints deployment via WSGI</title><link>http://specs.openstack.org/openstack/glance-specs/specs/pike/implemented/glance/lite-spec-community-goal-wsgi.html</link><description>

&lt;dl class="field-list simple"&gt;
&lt;dt class="field-odd"&gt;problem&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;Implement the Pike community goal &lt;a class="reference external" href="https://governance.openstack.org/tc/goals/pike/deploy-api-in-wsgi.html"&gt;Control Plane API endpoints deployment
via WSGI&lt;/a&gt;.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;solution&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;Implement a devstack plugin to run the Images API v2 supplied by Glance
in mod_wsgi.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;impacts&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;None.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;link&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;&lt;a class="reference external" href="https://review.openstack.org/#/q/owner:%22Matthew+Treinish%22+AND+branch:master+AND+topic:goal-deploy-api-in-wsgi+AND+(project:openstack/glance+OR+project:openstack-dev/devstack)"&gt;Patches&lt;/a&gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;assignee&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;Matt Treinish&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
</description><pubDate>Thu, 24 Aug 2017 00:00:00 </pubDate></item><item><title>Add ‘protected’ filter to image-list call</title><link>http://specs.openstack.org/openstack/glance-specs/specs/pike/implemented/glance/add-protected-filter.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/glance/+spec/add-protected-filter"&gt;https://blueprints.launchpad.net/glance/+spec/add-protected-filter&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Images contain a boolean ‘protected’ field.  Filtering on this field in the
image-list request is not currently supported.  Operators and users who make
use of the ‘protected’ field to prevent accidental deletion of images, however,
would find such filtering useful.  Not supporting filtering on this field is
counterintuitive as Glance supports filtering on all other image fields.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Use cases:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;An End User wants to list protected images that are accessible to that end
user.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;An End User wants to list non-protected images that are accessible to that
end user.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Add code so that when ‘protected=&amp;lt;value&amp;gt;’ is included in a query string on the
image-list call, the value is converted to a boolean, making it suitable
for database filtering (the ‘protected’ field is a boolean in the database
backend).&lt;/p&gt;
&lt;p&gt;For a user experience consistent with the image-create and image-update calls,
the only accepted values for this parameter will be ‘true’ or ‘false’ in that
exact case combination.  Any other value for this parameter should return a 400
to indicate a bad request.&lt;/p&gt;
&lt;p&gt;To summarize:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Introduce a new query parameter to the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt; &lt;span class="pre"&gt;v2/images&lt;/span&gt;&lt;/code&gt; call, namely,
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;protected&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The parameter will act as a filter on the ‘protected’ field of an Image.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The set of values for the parameter will be strict, that is, the call will
accept only those strings that satisfy the JSON boolean data type (in other
words, only ‘true’ or ‘false’ in that exact case combination).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Unrecognized values will result in a 400 (Bad Request) response with an
appropriate message.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;protected&lt;/span&gt;&lt;/code&gt; query parameter is not present, no filtering will be
done on the ‘protected’ field of Images.  (In other words, there’s no
default value.)&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;&lt;p&gt;Do nothing.  This isn’t really an option, because even though ‘protected’ is
not currently supported as a filter, image-list calls passing a value for
‘protected’ in the query string are accepted and do have an effect (the
API behaves as if &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;protected=False&lt;/span&gt;&lt;/code&gt; has been specified).  This behavior
appears weird to end users.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Implement the filter, but accept a liberal set of values, recognizing, for
example, ‘true’ or ‘false’ in any case combination; ‘yes’ or ‘no’ in any
case combination; and 1 or 0.  This can be accomplished by using the oslo
string utilities, which contains a function &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;bool_from_string&lt;/span&gt;&lt;/code&gt; that
converts strings to an appropriate boolean value &lt;a class="reference internal" href="#apf-1" id="id1"&gt;&lt;span&gt;[APF-1]&lt;/span&gt;&lt;/a&gt;.  Using the oslo
library has an additional bonus in that the usage will be consistent across
other OpenStack projects.&lt;/p&gt;
&lt;p&gt;The downside to this alternative is that it is inconsistent with the
image-create and image-update calls in the Images v2 API.  The latter calls
are governed by the Image json-schema, which clearly specifies a JSON
boolean type as the value of the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;protected&lt;/span&gt;&lt;/code&gt; field, and hence only ‘true’
or ‘false’ in that exact case combination is what these calls accept.  Thus,
liberal acceptance of commonly regarded boolean values in the query string
may cause API users to be surprised when these liberal values don’t work for
image-create or image-update, leading to user dissatisfaction.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Implement the filter, but be extremely lax, that is, any value that isn’t
mapped to the boolean value True by the oslo &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;bool_from_string&lt;/span&gt;&lt;/code&gt; function
would be considered False.  This actually isn’t very user friendly.  For
example, a French language speaker applying the query filter ‘protected=oui’
will receive the complement of what was requested.&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 is a very minor modification to the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GET&lt;/span&gt; &lt;span class="pre"&gt;v2/images&lt;/span&gt;&lt;/code&gt; call.  The
only changes are:&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Parameters which can be passed via the URL now include &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;protected&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&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;p&gt;The only impact on python-glanceclient is that the command&lt;/p&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance&lt;/span&gt; &lt;span class="pre"&gt;image-list&lt;/span&gt; &lt;span class="pre"&gt;--property&lt;/span&gt; &lt;span class="pre"&gt;protected=true&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;will now work correctly.&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;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;p&gt;Primary assignee:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;fengzhr&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Other contributors:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;rosmaita&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;dharinic&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;Implement the change roughly along the lines of
&lt;a class="reference external" href="https://review.openstack.org/#/c/449108/"&gt;https://review.openstack.org/#/c/449108/&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update the api-ref&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Write a release note&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 consistent with the current image-list filtering tests.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Small addition to the v2 image-list documentation in the api-ref.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;div role="list" class="citation-list"&gt;
&lt;div class="citation" id="apf-1" role="doc-biblioentry"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id1"&gt;APF-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://git.openstack.org/cgit/openstack/oslo.utils/tree/oslo_utils/strutils.py"&gt;http://git.openstack.org/cgit/openstack/oslo.utils/tree/oslo_utils/strutils.py&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
</description><pubDate>Thu, 10 Aug 2017 00:00:00 </pubDate></item><item><title>Lite Spec: Introduce Glance Taskflow stopfile feature</title><link>http://specs.openstack.org/openstack/glance-specs/specs/untargeted/glance/lite-spec-task-stopfile.html</link><description>

&lt;dl class="field-list simple"&gt;
&lt;dt class="field-odd"&gt;problem&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;When preparing to take a Glance node down for maintenance or upgrade
it is necessary to allow long-running operations to complete without
allowing new operations to begin. The Taskflow engine does not have
the capability to prevent individual executors from starting new
jobs, and so attempting to take a Glance node out of the Taskflow
processing pool risks a race condition with that executor starting a
job just before the service is terminated which could cause the Task
processing to fail.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;solution&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;Introduce a disable_by_file_path feature to Glance Taskflow which
will prevent the node from picking up new jobs. This allows an
operator or automation engine to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;touch&lt;/span&gt;&lt;/code&gt; the appropriate file
before terminating the service. This feature should depend on the
oslo healthcheck middleware configuration to disable the taskflow
engine. As an additional impact, this work will require Glance to
instantiate a single taskflow engine as a singleton and reuse that
engine instance on all subsequent taskflow operations.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;impacts&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;None&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;timeline&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;Expected to have a fix merged in the Pike cycle before milestone 2.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;link&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;&lt;a class="reference external" href="https://docs.openstack.org/developer/oslo.middleware/healthcheck_plugins.html"&gt;https://docs.openstack.org/developer/oslo.middleware/healthcheck_plugins.html&lt;/a&gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;assignee&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;Open&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
</description><pubDate>Wed, 31 May 2017 00:00:00 </pubDate></item><item><title>HealthCheck Middleware</title><link>http://specs.openstack.org/openstack/glance-specs/specs/liberty/approved/healtcheck-middleware.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/glance/+spec/healthcheck-middleware"&gt;https://blueprints.launchpad.net/glance/+spec/healthcheck-middleware&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;HealthCheck Middleware provides &amp;lt;SERVER&amp;gt;:&amp;lt;PORT&amp;gt;/healthcheck endpoint. This
endpoint behaves similar way as it does in Swift[1]. Normal operations returns
200 OK and if config option disable_path is enabled and that path exists
it will return 503 DISABLED BY FILE.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Currently Glance does not have any reasonable means to provide health check
information for example to HAProxy. Any such deployment causes extensive
logging and causes unnecessary operations in the server end (FE. GET request
to / which leads to version check).&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Take advantage of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo.middleware&lt;/span&gt;&lt;/code&gt;‘s healthcheck middleware by:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Adding a new paste filter - &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;healthcheck&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Adding the new filter to the default Glance API and Registry pipelines&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Disabled functionality would allow using a file in the filesystem to return
503 DISABLED BY FILE response dropping the node from the HAProxy. This would
allow the nodes disabled to finish their current operations and improve
maintenance experience in HA deployments.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Current operations model.&lt;/p&gt;
&lt;p&gt;Take Swift’s slightly smaller implementation and copy it directly into
Glance’s source tree.&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;GET ‘/healthcheck’ 200 OK, 503 DISABLED BY FILE&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;Potential performance improvement as healthcheck is done quite frequently
and the middleware is lightweight filter at the start of the pipeline.&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;healthcheck would be added to the start of the used pipeline to be used.
Optional disable_path=PATH option would be needed to the config files to
enable the discreet disable functionality.&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;jokke
kamil-rykowski&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Core Reviewers:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;kragniz
flaper87
icordasc&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;Code Change
Tests
Config Change
Documentation Change&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;Simple functional tests to verify the responses form the &amp;lt;SRV&amp;gt;:&amp;lt;P&amp;gt;/healthcheck&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Documentation changes are quite minimal explaining the new config option and
functionality.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;[1] _https://github.com/openstack/swift/blob/master/swift/common/middleware/healthcheck.py&lt;/p&gt;
&lt;/section&gt;
</description><pubDate>Thu, 25 May 2017 00:00:00 </pubDate></item><item><title>HTTP Proxy Support for Glance S3 Driver</title><link>http://specs.openstack.org/openstack/glance-specs/specs/liberty/approved/http-proxy-support-for-s3.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/glance/+spec/http-proxy-support-for-s3"&gt;https://blueprints.launchpad.net/glance/+spec/http-proxy-support-for-s3&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Currently the S3 store does not allow operators to connect to an S3 backend
through a proxy. This can create limitations on the ability to connect to the
S3 backend securely from a different network. I propose to add the option to
use a proxy to connect to an S3 backend.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;If glance store is configured to use the S3 backend and the backend is behind
a private network and needs to be accessed remotely, there is no secure way
to access the S3 backend securely.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Boto, the library that is used to make the connection to the S3 backend,
already supports proxy configurations. I propose that we enable the connection
to accept additional config options to give users the option to connect
through a proxy.&lt;/p&gt;
&lt;p&gt;The following configurations would be added:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;s3_store_enable_proxy: Enables the use of a proxy&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;s3_store_proxy_host: The proxy server (required when proxy is enabled)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;s3_store_proxy_port: The port to connect to the proxy&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;s3_store_proxy_user: The username of the proxy connection.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;s3_store_proxy_password: The password to be used to connect through the proxy.&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 user can use system wide proxy parameters, but would limit the ability to
connect from an outside network.&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 would introduce security settings to be modified by user. The ability to
connect through a proxy will provide a good way to secure connections.&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 introduces proxy configuration options in the store configuration.&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;This change will have to be explicitly configured in the store options.&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;cpallares&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="reviewers"&gt;
&lt;h3&gt;Reviewers&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Core reviewer(s):&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;flaper87
sigmavirus24&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other reviewer(s):&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;rosmaita&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 configurations (proxy name, port, user, password, default number of
retries to S3, etc).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Modify connections made to S3 to optionally accept proxy parameters.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create additional unit tests for connections made to the S3 backend using a
proxy.&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 testing will be needed for testing proxy connection.&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 the S3 store will need to be updated to include proxy opts.&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://boto.readthedocs.org/en/latest/ref/s3.html"&gt;Boto S3 Docs&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://wiki.openstack.org/wiki/Security/Guidelines"&gt;OpenStack Security Guidelines&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
</description><pubDate>Thu, 25 May 2017 00:00:00 </pubDate></item><item><title>Glance Image Signing and Verification</title><link>http://specs.openstack.org/openstack/glance-specs/specs/liberty/approved/image-signing-and-verification-support.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/glance/+spec/image-signing-and-verification-support"&gt;https://blueprints.launchpad.net/glance/+spec/image-signing-and-verification-support&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;OpenStack currently does not support the following feature:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Signature validation of uploaded signed images&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Deploying authentication will protect image integrity by verifying that an
image has not been modified after the upload by the user.  This feature
improves the enterprise-ready posture of OpenStack.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;There is no method for users to verify that a previously uploaded image has
not been modified.  An image could potentially be modified in transit (such as
when it is uploaded to Glance or transferred to Nova) or Glance itself could
be untrusted and modify images without a user’s knowledge.  An image that is
modified could include malicious code.  Providing support for image signatures
and signature verification would allow the user to verify that an image has
not been modified prior to booting the image.&lt;/p&gt;
&lt;p&gt;There are several use cases that this feature will support:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;An image is signed by an End User, using the user’s private key.  The user
then uploads the image to Glance, along with the signature created and a
reference to the user’s public key certificate.  Glance uses this
information to verify that the signature is valid, and notifies the user
if the signature is invalid.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;An image is created in Nova, and Nova signs the image at the request of the
End User.  When the image is uploaded to Glance, the signature and public
key certificate reference are also provided.  Glance verifies the signature
before storing the image, and notifies Nova if the signature verification
fails.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A signed image is requested by Nova, and Glance provides the signature and
a reference to the public key certificate to Nova along with the image so
that Nova can verify the signature before booting the image.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;For the initial implementation, this change will use the property feature of
Glance to store the metadata items needed for image signing and verification.
These include a public key certificate reference, and the signature.  These
are provided when the image is created, and are accessible when the image is
uploaded.  Note that this proposed change will only support image uploads with
the Glance API v2 (and will not support using the Glance API v1).  Also note
that multiple formats for the key (such as SubjectPublicKeyInfo) and for the
signature (such as PSS) will be supported.  The format of the signature will
be stored as one of the properties.&lt;/p&gt;
&lt;p&gt;The certificate reference will be used to access the certificate from a key
manager, where the certificate will be stored.  This certificate is added to
the key manager by the end user before uploading the image.  Note that the
signature is done offline.&lt;/p&gt;
&lt;p&gt;Glance already supports computing checksums of images when an image is
uploaded, and this checksum is stored with the image.  This same hash (which
by default is MD5) will be used for the signature verification.&lt;/p&gt;
&lt;p&gt;The checksum hash is computed in glance_store (when the image data is
uploaded), and is then used to verify the signature.  The Glance frontend
should use the reference to the public key certificate to retrieve the
certificate from the key manager, and then use this public key along with the
signature, the computed checksum, and the rest of the signature metadata to
verify the signature.  If the signature verification fails, the image will
transition to a killed state, and the user will be notified that the upload
failed and given a reason why.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;An alternative to using the hash already created in the store backend for the
signature verification/creation is to compute a hash in the store frontend.
However, eventlet.wsgi.Input file-like object that represents the image data
can only be read once, and needs to be read in the store backend in order to
upload the image.  In order to read the image data in the Glance frontend,
Glance could copy the data into a file, use the file to verify/create the
signature, and then give this file to the store backend to upload.  This would
be similar to what is done with the S3 backend [1]. However, this approach
would take significantly more time (during image upload), and there would not
be much gained.&lt;/p&gt;
&lt;p&gt;An alternative to storing a reference to the public key certificate in Glance
would be to store the actual public key certificate in Glance.  However, this
approach would be insecure, since Glance, unlike a dedicated key manager, has
not been created with storing keys or certificates in mind.&lt;/p&gt;
&lt;p&gt;An alternative to using asymmetric keys for integrity and confidentiality is
to use symmetric keys.  However, in order for Glance to be able to verify the
image, it would need to have access to the key used to create the signature.
This access would enable Glance to modify the image and create a new signature
without the user’s knowledge.  Using asymmetric keys enables Glance to verify
the signature without giving Glance the power to modify the image and
signature.&lt;/p&gt;
&lt;p&gt;An alternative to using the Glance properties to store and retrieve the
signature metadata would be to create an API extension that support
signatures. Then, instead of the user setting the metadata using the property
key value pairs, the API extension would be used. Currently, if a user were to
use the metadata keys (for the certificate and signature) for other purposes,
the image uploads would fail.  Another item of note is that an API extension
would allow for the management of multiple signatures per image in a clean
manner, which is not possible with the properties approach. However, the
Images API does not support extensions, so this is not a valid approach.&lt;/p&gt;
&lt;p&gt;Another alternative to using the Glance properties to store and retrieve the
signature metadata would be to use the CMS (cryptographic message syntax)
format as defined in RFC 5652 Section 5.  However, the size for this would be
variable, and could not use the existing Glance properties, which would
require API modifications.  For the initial implementation, Glance properties
will be used, with the plan to migrate to using CMS in a future implementation
as the need for increased flexibility arises.&lt;/p&gt;
&lt;p&gt;An alternative to requiring the user to provide the signature separate from
the image is to support images that already have an embedded signature.
Although this could be included as a future improvement, the initial
implementation will not provide embedded signature support, since it is
advantageous to keep the initial effort focused and small.&lt;/p&gt;
&lt;p&gt;An alternative to using the existing MD5 hash algorithm is to create a
separate configurable hash for use with verifying/creating the signature.
However, creating a separate hash negatively affects the performance, without
providing much benefit.  Note that since there are preferable hash algorithms
to MD5 that are more secure, a separate change is being proposed to allow for
the configuring of this hash algorithm [2].  This will not be included as a
part of this change, in the interest of having a straightforward initial
implementation.&lt;/p&gt;
&lt;p&gt;An alternative to focusing on a single-cloud implementation would be to
include support for multi-clouds in the initial implementation.  If images are
exchanged between different clouds, signature verification could be used to
confirm that images have not be modified.  However, in the interest of a more
simplistic initial implementation, explicit support for multi-clouds will be
saved for future iterations.&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 API changes will be needed for the initial implementation, provided that
other services are able to retrieve all of the properties of a given image.&lt;/p&gt;
&lt;p&gt;Note that the existing API allows for providing the signature metadata as
Glance properties, and returning an error message if verification fails.&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 improves the enterprise-ready posture of OpenStack by enabling
signature signing and verification.&lt;/p&gt;
&lt;p&gt;Although keys are used in this change, the keys themselves are assumed to be
stored in a key manager, and only a reference to the certificate is stored in
Glance.&lt;/p&gt;
&lt;p&gt;This change involves hashing the image data for use in verifying and creating
signatures for the image.&lt;/p&gt;
&lt;p&gt;Note that the signature length is currently limited to 255 bytes, since this
is the maximum size supported for Glance properties.  In turn, this limits
the size of the keys that can be used for signature creation.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;This change will involve adding log messages to indicate the success or
failure of signature verification and creation.&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 user will be required to provide the appropriate information needed for
the signing and verification in order to use this feature.&lt;/p&gt;
&lt;p&gt;There are no changes that need to be made to python-glanceclient.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;The feature will only be used if a user has provided the appropriate
properties during the image upload.  Otherwise, no signature verification or
creation will occur.&lt;/p&gt;
&lt;p&gt;When signature verification and creation do occur, there will be some latency
associated with retrieving the certificate from the key manager.  Since the
hash is already being created for images, the hash creation has no impact to
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;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;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;brianna-poulos&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;dane-fichter&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="reviewers"&gt;
&lt;h3&gt;Reviewers&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Core reviewer(s):&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;flaper87
sigmavirus24
nikhil_k&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other reviewer(s):&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;joel-coffman&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 feature will be tackled in the following stages:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Enable Glance to verify signatures provided by the user during an image
upload initiated by the user.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Enable Glance to verify signatures provided by Nova during an image upload
of a snapshot taken by Nova.&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;The cryptography library, which will be used for hash creation and signature
verification and creation, is already a part of the global-requirements of
OpenStack.  However, it is not a part of Glance, and will need to be added
there.&lt;/p&gt;
&lt;p&gt;Glance currently does not interact with any key managers.  Since a key manager
is needed to manage the keys, changes will need to be made to allow Glance to
retrieve the public key certificate using a key manager.  Specifically,
Castellan [3] will be used to interface with the key manager chosen.  The
initial key manager will be Barbican, but Castellan can be configured to use a
different backend.&lt;/p&gt;
&lt;p&gt;In order to take advantage of the signatures in Glance, Nova will need to
be updated to retrieve the signatures from Glance and verify them.  However,
Glance does not depend on Nova to have this support in order to have the
feature added.  The spec for this in Nova [4] has not yet been approved.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Before Nova support for this feature is added, unit tests will be sufficient.
Once Nova support is added, Tempest tests should ensure that the interaction
between Nova and Glance works 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;Instructions for how to use the change will need to be documented.  These
include instructions for the user on how to create keys and signatures
offline before providing this information during the creation of an image.&lt;/p&gt;
&lt;p&gt;This documentation will also include descriptions for each of the following
signature metadata properties:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;signature: the signature of the “checksum hash” encoded in base64 format&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;signature_hash_method: the hash method used to create the signature&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;signature_key_type: the key type used in creating the signature&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;valid values are: “RSA-PSS”&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;signature_certificate_uuid: the uuid used to retrieve the certificate from
castellan&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;mask_gen_algorithm: only used for RSA-PSS, defines the mask generation
algorithm used in the signature generation, optional and defaults to “MGF1”&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;valid values are: “MGF1”&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;pss_salt_length: only used for RSA-PSS, defines the salt length used in the
signature generation, optional and defaults to PSS.MAX_LENGTH&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;cryptography: &lt;a class="reference external" href="https://cryptography.io/en/latest/"&gt;https://cryptography.io/en/latest/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;[1] &lt;a class="reference external" href="http://goo.gl/Y3u3lK"&gt;http://goo.gl/Y3u3lK&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;[2] &lt;a class="reference external" href="https://review.openstack.org/191542"&gt;https://review.openstack.org/191542&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;[3] &lt;a class="reference external" href="http://git.openstack.org/cgit/openstack/castellan"&gt;http://git.openstack.org/cgit/openstack/castellan&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;[4] &lt;a class="reference external" href="https://review.openstack.org/#/c/188874/"&gt;https://review.openstack.org/#/c/188874/&lt;/a&gt;&lt;/p&gt;
&lt;/section&gt;
</description><pubDate>Thu, 25 May 2017 00:00:00 </pubDate></item><item><title>Tag Metadata Definitions - python-glanceclient Changes</title><link>http://specs.openstack.org/openstack/glance-specs/specs/liberty/approved/metadefs-tags-cli.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/glance/+spec/metadefs-tags-cli"&gt;https://blueprints.launchpad.net/glance/+spec/metadefs-tags-cli&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This blueprint adds in supporting code for Metadata Definition (metadef) tags.
The metadef tag catalog was approved and added into the Glance server in the
Kilo release.&lt;/p&gt;
&lt;p&gt;The implemented Kilo spec is here for reference:
&lt;a class="reference external" href="https://github.com/openstack/glance-specs/blob/master/specs/kilo/metadefs-tags.rst"&gt;https://github.com/openstack/glance-specs/blob/master/specs/kilo/metadefs-tags.rst&lt;/a&gt;&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;This blueprint specifies the CRUD details for the metadef tags.&lt;/p&gt;
&lt;p&gt;The bulk of the work for this blueprint was committed within the Kilo time
frame, but, did not make it out of the review process in time for the release.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;We are proposing enhancements to the python-glanceclient to allow metadef
tags to be created, retrieve, updated and deleted.&lt;/p&gt;
&lt;p&gt;The following sub-commands will be added to python-glanceclient:&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;o md-tag-create –name &amp;lt;NAME&amp;gt; &amp;lt;NAMESPACE&amp;gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Adds tag &amp;lt;NAME&amp;gt; to namespace &amp;lt;NAMESPACE&amp;gt;. Retains all other tag names.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;o md-tag-create-multiple –names &amp;lt;NAMES&amp;gt; [–delim &amp;lt;DELIM&amp;gt;] &amp;lt;NAMESPACE&amp;gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Replaces all tags in the &amp;lt;NAMESPACE&amp;gt; with those listed in &amp;lt;NAMES&amp;gt;.
The delimeter used in the list can be overidden with the single char &amp;lt;DELIM&amp;gt;
Comma is the default delimter.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;o md-tag-delete &amp;lt;NAMESPACE&amp;gt; &amp;lt;TAG&amp;gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Deletes the tag &amp;lt;TAG&amp;gt; from the namespace.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;o md-tag-list &amp;lt;NAMESPACE&amp;gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;List all tags associated with the namespace.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;o md-tag-show &amp;lt;NAMESPACE&amp;gt; &amp;lt;TAG&amp;gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Shows the details of the specified tag.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;o md-tag-update –name &amp;lt;NAME&amp;gt; &amp;lt;NAMESPACE&amp;gt; &amp;lt;TAG&amp;gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Renames the tag associated with &amp;lt;NAMESPACE&amp;gt; &amp;lt;TAG&amp;gt; to the new &amp;lt;NAME&amp;gt;.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;o md-namespace-tags-delete &amp;lt;NAMESPACE&amp;gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Deletes all tags associated with the namespace.&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;The sub-commands will be allowed when specified with –os-image-api-version
of 2. Example: glance –os-image-api-version 2 md-tag-list &amp;lt;NAMESPACE&amp;gt;&lt;/p&gt;
&lt;p&gt;This is consistent with how the other metadef commands have been implemented.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;An alternative to the “help” listing of metadef related sub-commands has been
suggested to lessen the amount of “md” related subcommands. This should be
handled in a separate bug if done.&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 following DB schema is the implemented schema in Kilo.
Constraints not shown for readability.&lt;/p&gt;
&lt;p&gt;Basic Schema:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;CREATE TABLE `metadef_tags` (
  `id`                     int(11) NOT NULL AUTO_INCREMENT,
  `namespace_id`           int(11) NOT NULL,
  `name`                   varchar(80) NOT NULL,
  `created_at`             timestamp NOT NULL,
  `updated_at`             timestamp
)
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;None.
The python-glanceclient will use the metadef Tag REST API created in Kilo.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;API Version&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;All URLS will be under the v2 Glance API.  If it is not explicitly specified
assume /v2/&amp;lt;url&amp;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;We intend to expose this via Horizon and are working on related blueprints.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None anticipated.&lt;/p&gt;
&lt;p&gt;This is expected to be called from Horizon when an admin wants to annotate
tags onto things likes images and instances. This API would be hit for them to
get available tags or create new ones.&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 (New API)&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;wayne-okuma&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="reviewers"&gt;
&lt;h3&gt;Reviewers&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Core reviewer(s):&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;zhiyan
Ian Cordasco (sigmavirus24)
Stuart McLaren&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other reviewer(s):&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;lakshmi-sampath
travis-tripp&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;blockquote&gt;
&lt;div&gt;&lt;p&gt;Changes would be made to:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;The python-glanceclient to support the new sub-commands&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;Same dependencies as Glance.&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 for all possible code with a goal of being able to
isolate functionality as much as possible.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Docs needed for new API extension and usage&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://www.youtube.com/watch?v=Dhrthnq1bnw"&gt;Youtube summit recap of Graffiti Juno POC demo that included tags.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="http://docs.openstack.org/developer/glance/metadefs-concepts.html"&gt;Current glance metadata definition catalog documentation.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Simple application category tags (no hierarchy)&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Images, volumes, software applications can be assigned to a category.
Similarly, a flavor or host aggregate could be “tagged” with supporting a
category of application, such as “BigData” or “Encryption”. Using the
matching of categories, flavors or host aggregates that support that category
of application can be easily paired up.&lt;/p&gt;
&lt;p&gt;Note: If a resource type doesn’t provide a “Tag” mechanism (only key value
pairs), a blueprint should be added to support tags on that type of resource.
In lieu of that, a key of “tags” with a comma separated list of tags as the
value be set on the resource&lt;/p&gt;
&lt;/section&gt;
</description><pubDate>Thu, 25 May 2017 00:00:00 </pubDate></item><item><title>Migrate glance-replicator to requests for HTTPS Support</title><link>http://specs.openstack.org/openstack/glance-specs/specs/liberty/approved/migrate-replicator-to-requests.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/glance/+spec/migrate-replicator-to-requests"&gt;https://blueprints.launchpad.net/glance/+spec/migrate-replicator-to-requests&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;As operators and users become more security conscious, it is important to
support deployments of Glance served only over HTTPS. In its current state,
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance-replicator&lt;/span&gt;&lt;/code&gt; uses &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;httplib&lt;/span&gt;&lt;/code&gt; and thus does not properly verify
HTTPS connections. This allows for various and very serious attacks to be
performed while the user of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance-replicator&lt;/span&gt;&lt;/code&gt; attempts to communicate with
Glance.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Many deployments currently support both HTTP and HTTPS connections to Glance’s
API. As best practices evolve, it will become more common that Glance and
other OpenStack services are served only over HTTPS with valid X.509
certificates. Currently, if an operator were to deploy Glance and serve it
using only HTTPS, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance-replicator&lt;/span&gt;&lt;/code&gt; would still allow for a large range of
attacks by an observer since it does not verify the certificate that the
server provides.&lt;/p&gt;
&lt;p&gt;Among other things, the user’s connection to Glance could easily be
intercepted by a man-in-the-middle serving a phony certificate who would then
proxy or even alter the data sent over the connection. Since the typical user
of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance-replicator&lt;/span&gt;&lt;/code&gt; is an administrator, any service token they have
could then be intercepted and used, which is dangerous given the privileges
associated with an administrator.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;This specification proposes that the code using &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;httplib&lt;/span&gt;&lt;/code&gt; in
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance-replicator&lt;/span&gt;&lt;/code&gt; be rewritten to use &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;requests&lt;/span&gt;&lt;/code&gt;. &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;requests&lt;/span&gt;&lt;/code&gt; supports
automatic certificate verification on all HTTPS connections and allows users
to provide custom certificate bundles for self-signed certificates.&lt;/p&gt;
&lt;p&gt;Given that an operator may choose to sign their own ceritificates for their
deployment of Glance, this specification also proposes the addition of a
command-line option to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance-replicator&lt;/span&gt;&lt;/code&gt; to allow the operator to specify
a custom certificate bundle to use when verifying the certificate.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;One alternative to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;requests&lt;/span&gt;&lt;/code&gt; that’s already used in other OpenStack
projects is &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;httplib2&lt;/span&gt;&lt;/code&gt;. This library provides a nearly identical API to
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;httplib&lt;/span&gt;&lt;/code&gt; and performs certificate verifcation. The library, however, is
being actively replaced by many of these same projects by &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;requests&lt;/span&gt;&lt;/code&gt;.
Reducing the number of dependencies that an operator needs to install is also
very favorable.&lt;/p&gt;
&lt;p&gt;An alternative to making the user specify their custom certificate bundle is
to provide a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance-replicator.conf&lt;/span&gt;&lt;/code&gt; file. This would be an entirely new
file. Adding yet another configuration file may add to confusion as to which
files are necessary when Glance is deployed as a whole.&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;For deployments of Glance being served over HTTPS, this will improve the
security of the user’s connection.&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 who have not properly configured HTTPS may receive errors. Since
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance-replicator&lt;/span&gt;&lt;/code&gt; previously did not generate errors, this may be an
unpleasant experience for the user. It is the position of the author of this
specification that an option to insecurely connect to Glance is a poor choice
since the errors will encourage the operators to properly configure Glance to
be served over HTTPS.&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;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;icordasc&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;junhongl&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="reviewers"&gt;
&lt;h3&gt;Reviewers&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Core reviewer(s):&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;flaper87
flwang&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other reviewer(s):&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;nikhil-komawar
kragniz&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 &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance-replicator&lt;/span&gt;&lt;/code&gt; to drop a some of its conventions surrounding
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;httplib&lt;/span&gt;&lt;/code&gt;&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;httplib&lt;/span&gt;&lt;/code&gt; with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;requests&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add option to specify a custom certificate bundle&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add documentation to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance-replicator&lt;/span&gt;&lt;/code&gt; surrounding the new option and
features&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;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;requests-mock&lt;/span&gt;&lt;/code&gt; will be used to write unit tests for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance-replicator&lt;/span&gt;&lt;/code&gt;
to ensure that proper coverage is achieved.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance-replicator&lt;/span&gt;&lt;/code&gt;’s man page will need to be updated regarding the new
configuration options. We should note the two current ways of setting a custom
certificate:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;requests&lt;/span&gt;&lt;/code&gt; will look for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;REQUESTS_CA_BUNDLE&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CURL_CA_BUNDLE&lt;/span&gt;&lt;/code&gt;
environment variables&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance-replicator&lt;/span&gt;&lt;/code&gt; option.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;Bugs:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://bugs.launchpad.net/glance/+bug/1408940"&gt;https://bugs.launchpad.net/glance/+bug/1408940&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
</description><pubDate>Thu, 25 May 2017 00:00:00 </pubDate></item><item><title>Remove custom client SSL handling</title><link>http://specs.openstack.org/openstack/glance-specs/specs/liberty/approved/remove-special-client-ssl-handling.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/python-glanceclient/+spec/remove-custom-client-ssl-handling"&gt;https://blueprints.launchpad.net/python-glanceclient/+spec/remove-custom-client-ssl-handling&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The Glance client currently supports disabling SSL compression via
the –no-ssl-compression argument. This spec proposes deprecating this
special handling of SSL.&lt;/p&gt;
&lt;p&gt;Note: This is transport layer compression, not application layer (http)
compression.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Custom SSL handling was introduced because disabling SSL layer compression
provided an approximately five fold performance increase in some
cases. Without SSL layer compression disabled the image transfer would be
CPU bound – with the CPU performing the DEFLATE algorithm.  This would
typically limit image transfers to &amp;lt; 20 MB/s. When –no-ssl-compression
was specified the client would not negotiate any compression algorithm
during the SSL handshake with the server which would remove the CPU
bottleneck and transfers could approach wire speed.&lt;/p&gt;
&lt;p&gt;In order to support ‘–no-ssl-compression’ two totally separate code
paths exist depending on whether this is True or False.  When SSL
compression is disabled, rather than using the standard ‘requests’
library, we enter some custom code based on pyopenssl and httplib in
order to disable compression.&lt;/p&gt;
&lt;p&gt;This spec proposes removing the custom code because:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;It is a burden to maintain&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;Eg adding new code such as keystone session support is more complicated&lt;/p&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;It can introduce additional failure modes&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;We have seen some bugs related to the ‘custom’ certificate checking&lt;/p&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Newer Operating Systems disable SSL for us.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;Eg. While Debian 7 defaulted to compression ‘on’, Debian 8 has compression
‘off’. This makes both servers and client less likely to have compression
enabled.&lt;/p&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Newer combinations of ‘requests’ and ‘python’ do this for us&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;Requests disables compression when backed by a version of python which
supports it (&amp;gt;= 2.7.9). This makes clients more likely to disable
compression out-of-the-box.&lt;/p&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;It is (in principle) possible to do this on older versions too&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;If pyopenssl, ndg-httpsclient and pyasn1 are installed on older
operating system/python combinations, the requests library should
disable SSL compression on the client side.&lt;/p&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Deprecate the ‘–no-ssl-compression’ option. Remove the custom http
handling code and print a warning when ‘–no-ssl-compression’ is
specified.&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;Do not deprecate&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The cost/benefit of not deprecating would mean that custom code paths
would have to be maintained for a small number of corner cases (that
can be addressed by other means).&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Add dependencies on ndg-httpsclient and pyasn1.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This is a possibility for legacy installations, but this should not
be needed for the vast majority of cases.&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;Certificate checking will no longer be done by custom glance client code,
but by the ‘requests’ library. I verified that for older python installs
(2.7) certificate checking is performed correctly by the requests library.&lt;/p&gt;
&lt;p&gt;Systems that have SSL compression enabled may be vulnerable to the CRIME
(&lt;a class="reference external" href="https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2012-4929"&gt;https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2012-4929&lt;/a&gt;) attack.
Installations which are security conscious should be running the Glance
server with SSL disabled.&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;SSL potentially not being disabled.
A new deprecation warning.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;If SSL is not disabled user’s will experience a performance hit – until
they use one of the alternative methods to disable 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;Deprecation warnings.
Will need to use an alternative method to disable SSL if appropriate.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;Should simplify things.&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;Stuart McLaren&lt;/p&gt;
&lt;/section&gt;
&lt;section id="reviewers"&gt;
&lt;h3&gt;Reviewers&lt;/h3&gt;
&lt;p&gt;Ian Cordasco&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;Client change&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;(small) nova/cinder 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;There is limited https testing in the gate by default.
Some manual functional testing will be done, and devstack will be
spun up with https enabled.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;The cli help will be updated. Any relevant .rst docs will be updated also.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;Previous effort:&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://review.openstack.org/#/c/23424"&gt;https://review.openstack.org/#/c/23424&lt;/a&gt;&lt;/p&gt;
&lt;/section&gt;
</description><pubDate>Thu, 25 May 2017 00:00:00 </pubDate></item><item><title>Reuse the deleted image-member before create a new one</title><link>http://specs.openstack.org/openstack/glance-specs/specs/liberty/approved/reuse-the-deleted-image-member-before-create.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/glance/+spec/reuse-the-deleted-image-member"&gt;https://blueprints.launchpad.net/glance/+spec/reuse-the-deleted-image-member&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Check the deleted image-member before create a new one, then update it if it
exists, otherwise, create a new one.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;If glance backend database is not MySQL or PostgreSQL,the unique constraint
of image-member only includes image-id and member. In this case, if an
image-member is deleted, then create it again with the same parameters, glance
initiates a query to see if there is already an existing one, but the
result does not include the record which was marked as deleted, glance will
try to create a new one with the same parameters, then it will fail with
duplicate error.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Use only one record to maintain the member-ship between a pair of image and
tenant. When create a new image-member, at first check all existing
image-member records including the deleted image-member, then update it if it
exists, otherwise, create a new one.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Unify the unique constraint for image-member like we did for MySQL and
PostgreSQL in 022_image_member_index.py, it has migrated unique constraint of
image-member for MySQL and PostgreSQL, now its unique constraint includes
image-id, member and deleted_at. Currently the column “deleted_at” is
nullable. For other databases like DB2, its unique constraint is more
restricted than MySQL. The columns under unique constrains should be
“NOT NULL”, otherwise, an error occurs. Thus, we can not create the same unique
constraint for this kinds of database.&lt;/p&gt;
&lt;p&gt;We would alter “deleted_at” column to “not nullable” in migration. That means
we have to insert a default timestamp value for the new created image-member,
an active member with a no-blank timestamp for “deleted_at” would confuse
user.&lt;/p&gt;
&lt;p&gt;Another solution is migrating the unique constraint from (image-id, member,
deleted_at) to (image-id, member,created_at) for MySQL and PostgreSQL, from
(image-id, member) to (image-id, member,created_at) for other databases.
created_at is not nullable, so the new constraint will be applicable to all
databases. This solution needs data migration for different database.&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;When create a new image-member, it will search all image-member records
including the deleted items. But if we enable this patch, it will very rare to
see many deleted image-member, as the membership will be kept by only one
record. The only case is, multiple deleted image-members were created before
applying this patch, we could make a migration script in another patch to
remove them.&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;Configuration options will change:&lt;/p&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;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;Long Quan Sha&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="reviewers"&gt;
&lt;h3&gt;Reviewers&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Core reviewer(s):&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;nikhil-komawar
Ian Cordasco&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other reviewer(s):&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Kamil Rykowski
Abhishek Kekane&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;Reuse the deleted image-member when create a new one&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;Verify the deleted image-member is updated when create a new one&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;Proposed patch:&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://review.openstack.org/190895"&gt;https://review.openstack.org/190895&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;unique constraint for PostgreSQL, the same as MySQL:&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="http://www.postgresql.org/docs/8.1/static/ddl-constraints.html"&gt;http://www.postgresql.org/docs/8.1/static/ddl-constraints.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;unique constraint for DB2:&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://www-01.ibm.com/support/knowledgecenter/SSEPGG_9.7.0/com.ibm.db2.luw.admin.dbobj.doc/doc/c0020151.html"&gt;https://www-01.ibm.com/support/knowledgecenter/SSEPGG_9.7.0/com.ibm.db2.luw.admin.dbobj.doc/doc/c0020151.html&lt;/a&gt;&lt;/p&gt;
&lt;/section&gt;
</description><pubDate>Thu, 25 May 2017 00:00:00 </pubDate></item><item><title>Scrub Images in Parallel</title><link>http://specs.openstack.org/openstack/glance-specs/specs/liberty/approved/scrub-images-in-parallel.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/glance/+spec/scrub-images-in-parallel"&gt;https://blueprints.launchpad.net/glance/+spec/scrub-images-in-parallel&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This change proposal introduces a way for the scrubber to scrub images in
parallel when delayed delete is enabled.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;As of today, when delayed delete is enabled, images are being scrubbed
serially while the image locations, if multiple, are being scrubbed in
parallel. For the general case, this may not achieve much performance gain as
the number of images is likely to be more than the number of image locations
per image. Consequently, the scrubber can fall behind when the number of
pending_delete images increase.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;This change will attempt to parallelize image scrubbing while leaving image
locations to be scrubbed serially.&lt;/p&gt;
&lt;p&gt;A new config option would be introduced to offer the flexibility to choose
between serial or parallel scrubbing. Also, using this config option, one can
regulate the degree of parallelism to a desired level.&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;One can run multiple scrubbers to keep up with the increase in pending_delete
images. However, in that case, scrubbers may race as they all get the same
set of images from the registry. This may not be a bad option if one can
ignore all the errors in the logs. Nevertheless, scrubbing images serially
is still inefficient.&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;As mentioned in the performance impact section, while setting the degree of
parallelism one should take into account any rate-limits enforced by the
backend store. If the degree of parallelism is set to go beyond the
rate-limits, an attacker may be able to force the scrubber hit the rate-limits
by creating and deleting several images in a short span of time.&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;When using parallel scrubbing one must take into account any rate-limits on the
backend store. Depending on extent of parallelism desired, scrubber may hit the
rate-limits of the backend store and may eventually slowdown or fail.&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 would have to set the new configuration option introduced with this
change proposal to be able to scrub images in parallel.&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;hemanth-makkapati&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;jesse-j-cook&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="reviewers"&gt;
&lt;h3&gt;Reviewers&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Core reviewer(s):&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;nikhil-komawar&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other reviewer(s):&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;flaper87
brian-rosmaita&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;Use eventlet to parallelize image scrubbing&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Monkey-patch required modules for eventlet&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Test on devstack&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;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;The new configuration option would require documentation.&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, 25 May 2017 00:00:00 </pubDate></item><item><title>Add created and updated time filtering to v2 API</title><link>http://specs.openstack.org/openstack/glance-specs/specs/liberty/approved/v2-additional-filtering.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/glance/+spec/v2-additional-filtering"&gt;https://blueprints.launchpad.net/glance/+spec/v2-additional-filtering&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This spec introduces a feature to the Glance v2 API for filtering image lists
based on when they were created or last updated using a comparative operators.&lt;/p&gt;
&lt;p&gt;The introduction of this feature is important because it provides a migration
path for consumers of the Glance v1 API who depend on changes-since filtering
to begin consuming the v2 API instead.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;From the v2 API list images spec protected properties such as &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;created_at&lt;/span&gt;&lt;/code&gt;
and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;updated_at&lt;/span&gt;&lt;/code&gt; are not identified as available for comparison operator
filtering the way &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;size_min&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;size_max&lt;/span&gt;&lt;/code&gt; effectively are. &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;&lt;/p&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;created_at&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;updated_at&lt;/span&gt;&lt;/code&gt; fields are not indexed resulting in
full-table scans in the database when the default sort &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; on image lists is
used or the changes-since filter from v1 is used.&lt;/p&gt;
&lt;p&gt;Further, v2 does not support the changes-since filter which was available in
v1 &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;. This creates a situation where functionality available in the v1 API
is not available in the v2 API and this limits operators and users ability to
usefully filter images.&lt;/p&gt;
&lt;p&gt;To promote the adoption of the Glance v2 API providing feature parity would be
helpful. As a complete replacement for the v1 API becomes available so too
does the option to begin deprecation of the v1 API. To advance both of these
ends, feature parity is important.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Two new filters are proposed to be added for the image list endpoint of the
v2 API: the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;created_at&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;updated_at&lt;/span&gt;&lt;/code&gt; times for images.&lt;/p&gt;
&lt;p&gt;With the proposed feature we enable consumers of the v2 API to quickly
identify old instance snapshots for clean-up and other potential use cases.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Something must be done to address the missing &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;changes-since&lt;/span&gt;&lt;/code&gt; filter to
address priorities of both the Nova and Glance projects as expressed through
the Liberty summit.&lt;/p&gt;
&lt;p&gt;We could implement changes-since as it exists in v1 API instead of making the
functionality more rich by allowing many comparative operators.&lt;/p&gt;
&lt;p&gt;We could exclude the created_at filter from the feature at this time, but the
additional effort to include it is minimal, and it is possible that other
potential use cases may benefit as well as taking the opportunity to raise an
index on the column to benefit the default sort.&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;Modify the Image domain class to raise indexes for the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;created_at&lt;/span&gt;&lt;/code&gt; and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;updated_at&lt;/span&gt;&lt;/code&gt; columns on the images DB table.&lt;/p&gt;
&lt;p&gt;The additional indexes raised will impose a longer upgrade window for larger
Glance installs while the indexes are built.&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;Following the pattern of existing filters, the new filters may be specified as
query parameters, using the field to filter as the key and the filter criteria
as the value in the parameter.&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Changes apply exclusively to Image API v2 Image entity listings:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;GET /v2/images/{image_id}&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;Filter by adding optional query parameters:&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;created_at&lt;/span&gt;     &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Specifies&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;limit&lt;/span&gt; &lt;span class="n"&gt;returned&lt;/span&gt; &lt;span class="n"&gt;images&lt;/span&gt; &lt;span class="n"&gt;based&lt;/span&gt; &lt;span class="n"&gt;on&lt;/span&gt; &lt;span class="n"&gt;when&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;image&lt;/span&gt;
                 &lt;span class="n"&gt;was&lt;/span&gt; &lt;span class="n"&gt;created&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;value&lt;/span&gt; &lt;span class="n"&gt;expressed&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;an&lt;/span&gt; &lt;span class="n"&gt;ISO&lt;/span&gt; &lt;span class="mi"&gt;8601&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
&lt;span class="n"&gt;updated_at&lt;/span&gt;     &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Specifies&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;limit&lt;/span&gt; &lt;span class="n"&gt;returned&lt;/span&gt; &lt;span class="n"&gt;images&lt;/span&gt; &lt;span class="n"&gt;based&lt;/span&gt; &lt;span class="n"&gt;on&lt;/span&gt; &lt;span class="n"&gt;when&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;image&lt;/span&gt;
                 &lt;span class="n"&gt;was&lt;/span&gt; &lt;span class="n"&gt;last&lt;/span&gt; &lt;span class="n"&gt;updated&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;value&lt;/span&gt; &lt;span class="n"&gt;expressed&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;an&lt;/span&gt; &lt;span class="n"&gt;ISO&lt;/span&gt; &lt;span class="mi"&gt;8601&lt;/span&gt;
                 &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;These filters will be added using syntax that conforms to the latest
guidelines from the OpenStack API Working Group, and any applicable draft
guidelines &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;. This implies support for optional comparison operators with
the implied default comparison operator being ‘equals’ for exact matches.&lt;/p&gt;
&lt;p&gt;An example of an acceptable criteria using an optional comparison operator:&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;gte&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;1985&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;04&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="n"&gt;T23&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;50.52&lt;/span&gt;&lt;span class="n"&gt;Z&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;This represents any time at or after 20 minutes and 50.52 seconds after the
23rd hour of April 12th, 1985 in UTC.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;In all cases, literal expressions in any of these filters will be
treated as case-insensitive.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Both new filters will support access control through oslo.policy enforcement
to allow a deployer to restrict usage of these filters. Because these filters
support this access control, no guarantee is given for availability of these
filters for all API consumers. Performance or security concerns around these
filters in any given deployment can be addressed through the use of custom
policy rules. Standard response codes will apply when access to the filter is
forbidden.&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;Update python-glanceclient as needed.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;The appropriate indexes will also be updated on each row create and/or update
to the associated image row. This is considered a minimal impact.&lt;/p&gt;
&lt;p&gt;Performance for sort operations on the indexed columns would be improved.&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;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;steve-lewis&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="reviewers"&gt;
&lt;h3&gt;Reviewers&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Core reviewer(s):&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;flwang
flaper87&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other reviewer(s):&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;Registry changes to support new filters&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;API changes to expose new filters&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add Policy enforcement hooks&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 as appropriate.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Docs needed for new API filters and usage as well as the additional policy
options.&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;&lt;a class="reference external" href="http://developer.openstack.org/api-ref-image-v2.html"&gt;Image service API v2&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;&lt;a class="reference external" href="http://specs.openstack.org/openstack/glance-specs/specs/kilo/sorting-enhancements.html"&gt;Glance sorting enhancements&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;&lt;a class="reference external" href="http://developer.openstack.org/api-ref-image-v1.html"&gt;Image service API v1&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;&lt;a class="reference external" href="https://review.openstack.org/#/c/177468/"&gt;API Working Group filtering guidelines draft&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;/aside&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Nova blueprint to use Images V2 API
&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/use-glance-v2-api"&gt;https://blueprints.launchpad.net/nova/+spec/use-glance-v2-api&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Nova change request supporting the blueprint
&lt;a class="reference external" href="https://review.openstack.org/#/c/144875/"&gt;https://review.openstack.org/#/c/144875/&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
</description><pubDate>Thu, 25 May 2017 00:00:00 </pubDate></item><item><title>Use keystoneclient Sessions</title><link>http://specs.openstack.org/openstack/glance-specs/specs/liberty/glanceclient/session-objects.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/python-glanceclient/+spec/session-objects"&gt;https://blueprints.launchpad.net/python-glanceclient/+spec/session-objects&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Keystoneclient sessions are being used as a common base library to standardize
handling of tokens and authentication credentials going beyond a basic username
and password.&lt;/p&gt;
&lt;p&gt;This improves security as a single point of update for these issues and means
that additional authentication mechanisms may be added transparently to
individual clients.&lt;/p&gt;
&lt;p&gt;Glanceclient should adopt sessions as other clients have.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;The OpenStack clients all grew rather organically. Each handled their own
authentication and this was copied and pasted between every service. This
results in:&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;inconsistencies with what parameters are accepted between clients.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A security issue when bugs are found and need to be patched in each client.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Inconsistent use of the service catalog, regions etc.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Problems adding new features as they become available in keystone.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;Glanceclient is structured differently from the other clients. It is one of the
few that nicely separates the responsibilities of the CLI and the library.
However it does do custom HTTPS handling and other security related fixes that
are not reused amongst other components.&lt;/p&gt;
&lt;p&gt;Because of offloading to the CLI it does not handle things like token
refreshing, and puts the onus of operating the service catalog onto the user -
generally other services.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;I want to bring glanceclient more inline with other clients. Now that there is
the facilities that things like the service catalog can be managed consistently
by other libraries there is less of an excuse for glanceclient to avoid using
this information.&lt;/p&gt;
&lt;p&gt;This will involve creating a different type of HTTPClient in the event that
session and other options are detected. This will allow glanceclient to
continue to operate as it does today unless users opt-in by using new
parameters. These new parameters are managed by the keystoneclient Adapter
object and so will simply involve passing kwargs through.&lt;/p&gt;
&lt;p&gt;The CRUD layers of glanceclient and the requests path will be unaffected.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Glanceclient can continue to operate as it does now. This is not as bad as
other clients as it pushes this configuration back on the service, rather than
incorrectly handling options internally. However this makes it a special case
and glanceclient will not benefit from the efforts to standardize
authentication flows and options that the other services gain.&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 will reimplement how glanceclient handles authentication, token
management and how you select endpoints. It handles this though by offloading
these concepts to keystoneclient so that any security issues can be handled
there.&lt;/p&gt;
&lt;p&gt;It will deprecate the custom HTTPs handling that glanceclient does. It is my
understanding that this custom handling was largely to disable BEAST style
attacks by preventing the client from advertising SSL compression capabilities.
Whilst compatibility will be maintained for the current client it may not be
possible to maintain this functionality when using a common handling logic.&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 flow on effect here is that other services that have credentials and
parameters in config files that are used to talk to glance will be standardized
with other services.&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 change the parameters that are provided when establishing a
glanceclient. The new parameters are standardized across all the other
OpenStack client libraries. Existing parameters will obviously be maintained
and deprecated in time.&lt;/p&gt;
&lt;p&gt;This will greatly assist integration with service to service communication as
auth_token middleware is providing an auth plugin that can be used directly, as
well as standardizing the options that are used for all the clients.&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;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;jamielennox&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;Other contributors:&lt;/p&gt;
&lt;/section&gt;
&lt;section id="reviewers"&gt;
&lt;h3&gt;Reviewers&lt;/h3&gt;
&lt;p&gt;I would appreciate anyone who wants to be a point of contact for review.&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Core reviewer(s):&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;None at this time&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;There are some initial changes to testing that are required to fit the new
model. These are considered generally useful and not necessarily specific to
this review.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add session handling and handling of existing parameters to the glanceclient.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Convert the glanceclient CLI to use the standard parameters and option
handling. In other projects I have done this for we have not always completed
this step. Most clients are moving towards the OpenStackClient project for
CLI and are not worried about significant refactoring of their CLI
applications.&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 can unit test these changes. It should also be possible to use a
testscenarios approach such that existing CRUD tests are run with both a
traditionally created client and a client created with a session.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Update documentation on how to instantiate a Client.&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, 25 May 2017 00:00:00 </pubDate></item><item><title>Lite Spec: Remove Glare code from the Glance repository</title><link>http://specs.openstack.org/openstack/glance-specs/specs/pike/implemented/glance/lite-spec-glare-ectomy.html</link><description>

&lt;dl class="field-list"&gt;
&lt;dt class="field-odd"&gt;problem&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;Glare became a separate project with its own code repository during
Newton. The code was copied out of the Glance tree, but remained in
the Glance repository. It is no longer being maintained within
Glance, and that has begun to cause some problems, for example,
blocking a recent stevedore upper constraints change; see Change-Id:
&lt;a class="reference external" href="https://review.openstack.org/#q,I141b17f9dd2acebe2b23f8fc93206e23bc70b568,n,z"&gt;I141b17f9dd2acebe2b23f8fc93206e23bc70b568&lt;/a&gt;.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;solution&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;Remove all Glare code from the Glance repository and drop all
artifacts tables from the Glance database.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;impacts&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;No API Impact as the Glare API was EXPERIMENTAL in both versions
that ran on the code being removed (‘/v3’ on the Glance endpoint in
Liberty, ‘/v0.1’ on its own endpoint in Mitaka).&lt;/p&gt;
&lt;p&gt;As a courtesy to projects/packagers/deployers that may have consumed
Glare from the Glance code repository, an &lt;a class="reference external" href="http://lists.openstack.org/pipermail/openstack-dev/2017-February/112427.html"&gt;openstack-dev announcement&lt;/a&gt;
and an &lt;a class="reference external" href="http://lists.openstack.org/pipermail/openstack-operators/2017-February/012689.html"&gt;openstack-operators announcement&lt;/a&gt;
were sent out on 16 February 2017.  There has been no response so
far.&lt;/p&gt;
&lt;p&gt;A detailed release note will be included in the patch.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;timeline&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;Pike-1&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;link&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;Change-Id: &lt;a class="reference external" href="https://review.openstack.org/#q,I3026ca6287a65ab5287bf3843f2a9d756ce15139,n,z"&gt;I3026ca6287a65ab5287bf3843f2a9d756ce15139&lt;/a&gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;assignee&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;rosmaita&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
</description><pubDate>Thu, 25 May 2017 00:00:00 </pubDate></item><item><title>Glance Spec Lite</title><link>http://specs.openstack.org/openstack/glance-specs/specs/ocata/approved/glance/lite-specs.html</link><description>

&lt;section id="replace-mox-with-mock-for-unit-test"&gt;
&lt;h2&gt;Replace mox with mock for unit test&lt;/h2&gt;
&lt;dl class="field-list simple"&gt;
&lt;dt class="field-odd"&gt;problem&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Mox&lt;/span&gt;&lt;/code&gt; does not support python 3. We have a shim module ‘mox3’ that was
built a couple of years ago, is unmaintained, and as it gets tested
more heavily is showing race conditions under python3.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;solution&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;Replace &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;mox&lt;/span&gt;&lt;/code&gt; with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;mock&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;impacts&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;This change will use &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;mock&lt;/span&gt;&lt;/code&gt; instead of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;mox&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;timeline&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;Expected to be merged within the Ocata time frame.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;link&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;&lt;a class="reference external" href="https://review.openstack.org/#/c/407959/"&gt;https://review.openstack.org/#/c/407959/&lt;/a&gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;assignee&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;Howard Lee&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;section id="end-of-replace-mox-with-mock-for-unit-test"&gt;
&lt;h3&gt;&lt;cite&gt;End of&lt;/cite&gt; Replace mox with mock for unit test&lt;/h3&gt;
&lt;/section&gt;
&lt;/section&gt;
</description><pubDate>Fri, 03 Feb 2017 00:00:00 </pubDate></item><item><title>Glance Expand/Contract migrations with Alembic</title><link>http://specs.openstack.org/openstack/glance-specs/specs/ocata/implemented/glance/alembic-migrations.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/glance/+spec/alembic-migrations"&gt;https://blueprints.launchpad.net/glance/+spec/alembic-migrations&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This spec outlines the motivation and implementation details for porting
Glance database migrations from SQLAlchemy-based scripts to Alembic.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Existing database migrations are implemented in Glance using SQLAlchemy-
migrate scripts. This approach makes designing migrations for rolling upgrades
(&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; &amp;amp; &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;) extremely uncomfortable. The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;expand&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;contract&lt;/span&gt;&lt;/code&gt;
migrations would have to be created in strict sequential order with all of the
latter following all of the former. This places unnecessary restrictions on
the order of migrations and becomes very error prone as multiple schema changes
are introduced in a single cycle. Essentially, using SQLAlchemy-migrate
constrains &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;expand&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;contract&lt;/span&gt;&lt;/code&gt; migrations to be run atomically and does
not easily facilitate separating them into phases as required during rolling
upgrades.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;We are proposing to port the migration flows to be handled by Alembic &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;.
There are numerous benefits to this change. Alembic allows labeling the
various migration scripts with designated branch names (e.g. &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;expand&lt;/span&gt;&lt;/code&gt; and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;contract&lt;/span&gt;&lt;/code&gt;), which makes it easier to group the two types of changes and
run them separately.&lt;/p&gt;
&lt;p&gt;Another benefit is that Alembic migrations are chained in the manner of linked
list. This is accomplished by explicitly specifying revision dependencies in
each migration script. This will allow developers to get away from dependence
on numeric ordering of migration scripts and obviate the need for placeholder
migrations for retroactive backports, of the like: &lt;a class="reference external" href="https://git.openstack.org/cgit/openstack/glance/tree/glance/db/sqlalchemy/migrate_repo/versions/023_placeholder.py"&gt;023_placeholder&lt;/a&gt;. To facilitate this feature, a new
naming convention is proposed for migration scripts:&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;div class="line-block"&gt;
&lt;div class="line"&gt;&lt;em&gt;&amp;lt;cycle&amp;gt;_&amp;lt;branch-label&amp;gt;&amp;lt;##&amp;gt;_&amp;lt;short-desc&amp;gt;.py&lt;/em&gt;&lt;/div&gt;
&lt;div class="line"&gt;e.g. &lt;em&gt;ocata_expand01_add_visibility_column.py&lt;/em&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;Additionally, Alembic supports automatic generation of migration scripts using
SQLAlchemy’s ORM. In the future, developers are encouraged to utilize this
feature to minimize their interaction with the underlying DBMS and rely on the
Python code to define the new schema.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;The best aleternative available is to continue using SQLAlchemy-migrate
scripts. The downsides of this appropach are outlined in the
&lt;a class="reference internal" href="#problem-description"&gt;Problem description&lt;/a&gt; section above.&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;Performance of existing offline migration flows is not expected to be
impacted in a signifficant way.&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 API of the glance-manage command-line utility remains backwards compatible.
However, the operators will notice that the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;db_version&lt;/span&gt;&lt;/code&gt; command returns a
named head revision rather than a number. This change will be documented.
Additionally, the operators will need to be made aware of the new
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;db_expand&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;db_contract&lt;/span&gt;&lt;/code&gt;, and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;db_data_migrate&lt;/span&gt;&lt;/code&gt; APIs in the
glance-manage command-line utility. Refer to 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="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;Going forward, any time a database schema change is implemented, developers
will need to create Alembic migration scripts conforming to the established
naming convention and making sure to link each new revision to the
appropriate down revision.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;p&gt;A new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;alembic_migrations&lt;/span&gt;&lt;/code&gt; folder is added under &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance/db/sqlalchemy&lt;/span&gt;&lt;/code&gt;
This folder will contain all the necessary code to implement
Alembic based migrations, including:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Alembic configuration and environment files. For details see:
&lt;a class="reference external" href="http://alembic.zzzcomputing.com/en/latest/tutorial.html#the-migration-environment"&gt;Migration Environment&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;helper scripts for creating initial Glance DB schema&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;versions&lt;/span&gt;&lt;/code&gt; directory, containing migration scripts added in different
release cycles&lt;/p&gt;&lt;/li&gt;
&lt;/ul&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;hemanthm
abashmak&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;Implement Alembic migration infrastructure and scripts for existing
database migrations (up to Newton).&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;expand/contract&lt;/span&gt;&lt;/code&gt; migrations for new Ocata features &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;/li&gt;
&lt;li&gt;&lt;p&gt;Update the glance-manage utility to utilize Alembic for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;db_sync&lt;/span&gt;&lt;/code&gt;
and related commands. Add &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;db_expand&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;db_contract&lt;/span&gt;&lt;/code&gt; commands
to prepare for rolling upgrades.&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;A new Python module will be added to Glance’s requirements list:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;alembic&lt;/em&gt; - version &lt;em&gt;0.8.7&lt;/em&gt; or hihger&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 and new database migration tests (unit and functional) will be
ported and/or added to exercise the updated glance-manage utility and
test the integrity of Alembic-based migration 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 new database version names resulting from the move to Alembic will need to
be documented to make developers aware of the change to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;db_version&lt;/span&gt;&lt;/code&gt; output.&lt;/p&gt;
&lt;p&gt;Also, as part of the drive to enable the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;assert:supports-zero-downtime&lt;/span&gt;
&lt;span class="pre"&gt;-upgrade&lt;/span&gt;&lt;/code&gt; tag &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;, this change will introduce and implement new API methods
for the glance-manage utility: &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;db_expand&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;db_contract&lt;/span&gt;&lt;/code&gt;, and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;db_data_migrate&lt;/span&gt;&lt;/code&gt;. These will need to be thoroughly documented and their
usage explained in the glance-manage reference as well as the upgrade guide.
It is advised to wait until Glance is able to assert the zero-downtime upgrade
tag to add documentation for the new commands.&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;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.openstack.org/331489"&gt;Glance rolling upgrades&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://review.openstack.org/331740"&gt;Database strategy for rolling upgrades&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="http://alembic.zzzcomputing.com/en/latest/"&gt;Alembic’s documentation&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://specs.openstack.org/openstack/glance-specs/specs/newton/approved/glance/community_visibility.html"&gt;Community images&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;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://governance.openstack.org/reference/tags/assert_supports-zero-downtime-upgrade.html"&gt;Supports zero-downtime upgrade tag&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;/aside&gt;
&lt;/section&gt;
</description><pubDate>Fri, 03 Feb 2017 00:00:00 </pubDate></item><item><title>Add community-level image sharing</title><link>http://specs.openstack.org/openstack/glance-specs/specs/ocata/implemented/glance/community_visibility.html</link><description>

&lt;p&gt;&lt;em&gt;This spec is mostly based on an earlier blueprint created by Iccha Sethi, and
later picked up by Louis Taylor. We at Symantec have already implemented a
similar function within our local environment.  We want to re-target this
feature to Newton release.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The blueprint may be found at:
&lt;a class="reference external" href="https://blueprints.launchpad.net/glance/+spec/community-level-v2-image-sharing"&gt;https://blueprints.launchpad.net/glance/+spec/community-level-v2-image-sharing&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This feature will allow image owners to share images across multiple
tenants/projects without explicitly creating members individually through the
glance API V2. “Community images” will not appear in users’ default image
listings.&lt;/p&gt;
&lt;p&gt;This new feature adds a new value for the visibility of an image to the
underlying data model, named &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;community&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, there is no provision for an image to be available for use by users
other than the owner of the image, unless the image is either made public or
explicitly shared by the owner of the image with other users. If the number of
users who require access to the image is large, the overhead of explicit
sharing can become a burden on the owner of the image. Also, if such images
are not needed by the majority of users, then the image listing results will be
spammed if they are all made public.&lt;/p&gt;
&lt;p&gt;Public images appear in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;image-list&lt;/span&gt;&lt;/code&gt; for all users. This can be undesirable
because:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;An open source project wants to make a prepared VM image available so users
simply boot an instance from that image to use the project’s software. The
developers of the project are too busy writing software to worry about the
hassle of maintaining a list of “customers” as they’d have to do with
current v2 image sharing. At the same time, the cloud provider hosting the
prepared image doesn’t want to make this image public, as that would imply
a support relationship that doesn’t exist between image consumers and the
cloud provider. Moreover, if too many such images get published,
then image listing will be spammed as this type of image should not be seen
by most of the users.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A cloud provider wants to discourage users from using a public image that is
getting old. For example, an image which is missing some security patches or
is no longer supported by the vendor. The cloud provider doesn’t want to
delete the image because some users still require it. Users could need the
old image to rebuild a server, or because they have custom patches for that
particular image.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;In both cases, the vendor can make the image a “community” image and alleviate
the challenges presented above. This means that:&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;a) The community image won’t appear in users’ default image lists. This
means they won’t know about it unless they are motivated to seek it out, for
example by asking other users for the UUID.&lt;/p&gt;
&lt;p&gt;b) Since the image is no longer “public,” it doesn’t imply the same level of
support from the vendor as a provider-supplied public image.&lt;/p&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;An additional value for the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;visibility&lt;/span&gt;&lt;/code&gt; enum will be added in the JSON
schema, named &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;'community'&lt;/span&gt;&lt;/code&gt;.  This makes the possible values of
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;visibility&lt;/span&gt;&lt;/code&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="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'public'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'private'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'shared'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'community'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Images with these &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;visibility&lt;/span&gt;&lt;/code&gt; values have the following properties:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;public&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Who: all users:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;have this image in the default &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;image-list&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;can see &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;image-detail&lt;/span&gt;&lt;/code&gt; for this image&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;can boot from this image&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;private&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Who: users with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tenant_id&lt;/span&gt; &lt;span class="pre"&gt;==&lt;/span&gt; &lt;span class="pre"&gt;owner_tenant_id&lt;/span&gt;&lt;/code&gt; only:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;have this image in the default &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;image-list&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;see &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;image-detail&lt;/span&gt;&lt;/code&gt; for this image&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;can boot from this image&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;shared&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Who: users with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tenant_id&lt;/span&gt; &lt;span class="pre"&gt;==&lt;/span&gt; &lt;span class="pre"&gt;owner_tenant_id&lt;/span&gt;&lt;/code&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;have this image in the default &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;image-list&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;can see &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;image-detail&lt;/span&gt;&lt;/code&gt; for this image&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;can boot from this image&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;can see full member list for this image&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Who: users with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tenant_id&lt;/span&gt;&lt;/code&gt; in the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;member-list&lt;/span&gt;&lt;/code&gt; with
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;member_status&lt;/span&gt; &lt;span class="pre"&gt;==&lt;/span&gt; &lt;span class="pre"&gt;'accepted'&lt;/span&gt;&lt;/code&gt; of the image:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;have this image in the default &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;image-list&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;can see &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;image-detail&lt;/span&gt;&lt;/code&gt; for this image&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;can boot from this image&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;can see a member list containing only themselves for this image&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Who: users with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tenantId&lt;/span&gt;&lt;/code&gt; in the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;member-list&lt;/span&gt;&lt;/code&gt;
with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;member_status&lt;/span&gt; &lt;span class="pre"&gt;==&lt;/span&gt; &lt;span class="pre"&gt;'pending'&lt;/span&gt;&lt;/code&gt; or &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;member_status&lt;/span&gt; &lt;span class="pre"&gt;==&lt;/span&gt; &lt;span class="pre"&gt;'rejected'&lt;/span&gt;&lt;/code&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;do not have this image in their default &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;image-list&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;can see &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;image-detail&lt;/span&gt;&lt;/code&gt; for this image&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;can boot from this image&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;can see a member list containing only themselves for this image&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;community&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Who: users with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tenant_id&lt;/span&gt; &lt;span class="pre"&gt;==&lt;/span&gt; &lt;span class="pre"&gt;owner_tenant_id&lt;/span&gt;&lt;/code&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;have this image in the default &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;image-list&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;can see &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;image-detail&lt;/span&gt;&lt;/code&gt; for this image&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;can boot from this image&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Who: all users:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;do not have this image in their default &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;image-list&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;can see &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;image-detail&lt;/span&gt;&lt;/code&gt; for this image&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;can boot from this image&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;section id="membership-behaviour-and-transitions"&gt;
&lt;h3&gt;Membership Behaviour and Transitions&lt;/h3&gt;
&lt;p&gt;After much discussion, it has been decided that this topic is complex enough
to break out into its own separate proposal. Between the significant number
of state transitions, and the problem use cases brought up by several people,
fully designing what the “correct” behaviour shall be is outside the scope of
this spec.&lt;/p&gt;
&lt;p&gt;The behaviour for the initial implementation for community images shall
respect the current paradigm in glance - where changing visiblities does not
affect an image’s internal member-list.  To be precise, consistent with current
behavior:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;An image’s member-list persists even when the visibility of an image has
changed to a value that renders the member-list inert.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Image member operations (that is, creating image members or changing
the member_status of image members) are allowed only when an image has a
visibility under which the member-list is &lt;em&gt;not&lt;/em&gt; inert.  The justification
for this is that it is confusing to users to be able to perform member
operations on an image when these operations have no effect on the
accessibility of the image.&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;section id="adding-image-aliases"&gt;
&lt;h4&gt;Adding image aliases&lt;/h4&gt;
&lt;p&gt;A completely different way of solving the usecase for cloud providers
(discouraging users from using an older version of a public image) could be to
create a mechanism to make an image alias, which could point at the newest
version of the public image. There is an abandoned blueprint for this feature
&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, however, is much harder to implement and does not fit with the
other use cases.&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;&lt;a class="reference external" href="https://blueprints.launchpad.net/glance/+spec/glance-image-aliases"&gt;https://blueprints.launchpad.net/glance/+spec/glance-image-aliases&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;/aside&gt;
&lt;/section&gt;
&lt;section id="adding-a-special-case-of-image-sharing"&gt;
&lt;h4&gt;Adding a special case of image sharing&lt;/h4&gt;
&lt;p&gt;Another method of implementing this functionality is to add a membership record
for an image that has a target of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;"community"&lt;/span&gt;&lt;/code&gt; (i.e. it is shared with all
tenants) with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;membership_status&lt;/span&gt; &lt;span class="pre"&gt;=&lt;/span&gt; &lt;span class="pre"&gt;"community"&lt;/span&gt;&lt;/code&gt;. This marks it as a community
image very simply and requires few modifications to existing code.&lt;/p&gt;
&lt;p&gt;This respects the current anti-spam provisions in the glance v2 API. When an
image owner makes an image a “community” image, any other tenant should be able
to boot an instance from that image. The image will not show up in any
tenant’s default image-list.&lt;/p&gt;
&lt;p&gt;This method can cause a few corner cases which result in surprising API calls
and some less than desirable mappings between data model level and API level
values of visibility.&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;section id="schema-changes"&gt;
&lt;h4&gt;Schema changes&lt;/h4&gt;
&lt;p&gt;The visibility of the image will be stored in the database within the images
table inside a new column named &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;visibility&lt;/span&gt;&lt;/code&gt;. The visibility will be in the
set of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;['public',&lt;/span&gt; &lt;span class="pre"&gt;'private',&lt;/span&gt; &lt;span class="pre"&gt;'shared',&lt;/span&gt; &lt;span class="pre"&gt;'community']&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The default value for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;visibility&lt;/span&gt;&lt;/code&gt; is &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;shared&lt;/span&gt;&lt;/code&gt;.  (See &lt;a class="reference internal" href="#other-impact"&gt;&lt;span class="std std-ref"&gt;Other end user impact&lt;/span&gt;&lt;/a&gt;
for a discussion.)&lt;/p&gt;
&lt;p&gt;This change makes the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;is_public&lt;/span&gt;&lt;/code&gt; column redundant. If no v1 code actually
uses &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;is_public&lt;/span&gt;&lt;/code&gt;, the column will be removed.&lt;/p&gt;
&lt;p&gt;Appropriate indexes will be added to facilitate quick responses.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="database-migrations"&gt;
&lt;h4&gt;Database migrations&lt;/h4&gt;
&lt;p&gt;(Note: this is a statement of expected outcomes, not an algorithm for
performing the migration.)&lt;/p&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;&lt;p&gt;All rows with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;is_public&lt;/span&gt;&lt;/code&gt; == 1:&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;visibility&lt;/span&gt;&lt;/code&gt; = &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;public&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For all unique &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;image_id&lt;/span&gt;&lt;/code&gt; in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;image_members&lt;/span&gt;&lt;/code&gt; where &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;deleted&lt;/span&gt;&lt;/code&gt; != 1 and
for which &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;is_public&lt;/span&gt;&lt;/code&gt; == 0 for that image:&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;visibility&lt;/span&gt;&lt;/code&gt; = &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;shared&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For all other images:&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;visibility&lt;/span&gt;&lt;/code&gt; = &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;private&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;(See &lt;a class="reference internal" href="#other-impact"&gt;&lt;span class="std std-ref"&gt;Other end user impact&lt;/span&gt;&lt;/a&gt; for further discussion.)&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;The changes described in this document will require an API version bump.&lt;/p&gt;
&lt;section id="image-discovery"&gt;
&lt;h4&gt;Image discovery&lt;/h4&gt;
&lt;p&gt;If you want to list all community images, and only community images, then you
would use:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;GET /v2/images?visibility=community
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;All other appropriate filters will be respected. Of note is the use of an
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;owner&lt;/span&gt;&lt;/code&gt; parameter. This, when supplied together with the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;visibility=community&lt;/span&gt;&lt;/code&gt; filter, allows a user to request only those community
images owned by that particular tenant:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;GET /v2/images?visibility=community&amp;amp;owner={owner_tenant_id}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Note that &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;visiblity&lt;/span&gt;&lt;/code&gt; will be considered a core property of the image object,
and as such included within image lists generated via the v2 interface.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="making-an-image-a-community-image"&gt;
&lt;h4&gt;Making an image a “community image”&lt;/h4&gt;
&lt;p&gt;As permitted by the new policy.json rule &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;communitize_images&lt;/span&gt;&lt;/code&gt;, an admin or
owner would use the existing image-update call to change an image’s visiblity
to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;'community'&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;PATCH&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;v2&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;images&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;image_id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Request body:&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;"op"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"replace"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"path"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"/visibility"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"community"&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 and other behaviour remains the same as was previously defined for
this call.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="removing-community-level-access-from-an-image"&gt;
&lt;h4&gt;Removing community level access from an image&lt;/h4&gt;
&lt;p&gt;An admin or owner of an image can remove community-level access from an image
by using the image-update call. For example, instead of setting it to
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;'community'&lt;/span&gt;&lt;/code&gt; as before, we set it to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;'private'&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;PATCH&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;v2&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;images&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;image_id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Request body:&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;"op"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"replace"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"path"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"/visibility"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"private"&lt;/span&gt; &lt;span class="p"&gt;}]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;An admin or user with permission to publicize an image could replace community
visibility with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;public&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;As in the above case, the response and other behaviour remains the same as
was previously defined for this call.&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;See “other deployer impact”.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;Current notifications contain the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;is_public&lt;/span&gt;&lt;/code&gt; attribute, which is true if and
only if the image is a public image. This must be maintained for backwards
compatibility.&lt;/p&gt;
&lt;p&gt;An additional attribute of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;visibility&lt;/span&gt;&lt;/code&gt; will be added for each image to
indicate its visiblity, with possible values of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;['public',&lt;/span&gt; &lt;span class="pre"&gt;'private',&lt;/span&gt;
&lt;span class="pre"&gt;'shared',&lt;/span&gt; &lt;span class="pre"&gt;'community']&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;span id="other-impact"/&gt;&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;Consistent with current functionality, when a visibility is specified at the
time of image creation, that visibility will be respected.  If the user
creating the image does not have appropriate permissions to set the specified
visibility value on an image, the image-create call will fail as it does now.&lt;/p&gt;
&lt;section id="default-visibility"&gt;
&lt;h4&gt;Default visibility&lt;/h4&gt;
&lt;p&gt;In order to preserve backward compatibility with the current workflow for
sharing an image, the default &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;visibility&lt;/span&gt;&lt;/code&gt; of an image will be &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;shared&lt;/span&gt;&lt;/code&gt;:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;An image with shared visibility and no image members is not accessible to
anyone other than the image owner, so this respects the current behavior.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Currently, when an image is created with default visibility, the owner can
immediately add members to the image to share it.  By making the default
visibility value &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;shared&lt;/span&gt;&lt;/code&gt;, we preserve this behavior.  If the default
visibility were &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;private&lt;/span&gt;&lt;/code&gt;, then this behavior would be broken as the
image owner would have to make an API call to change the visibility of
the image to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;shared&lt;/span&gt;&lt;/code&gt; before members could be added.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Although the Image API v1 is deprecated in Newton, it still exists and
will likely be deployed in clouds using the Ocata release of OpenStack.
Since the v1 API has no concept of visibility, there’s no way for a user
to change the visibility to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;shared&lt;/span&gt;&lt;/code&gt; so that an image can have members
added to it.  By making the default visibility &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;shared&lt;/span&gt;&lt;/code&gt;, we achieve the
following desirable results:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A v1 user can create an image and add members using the current workflow,
that is, sharing an image is simply a matter of putting a member on it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In deployments using both v1 and v2 of the Image API, if an image is
created using v1 and then an image-show call is made in v2, the visibility
of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;shared&lt;/span&gt;&lt;/code&gt; makes it clear to the v2 user that the image is in a state
where it can both accept members and be accessed by any existing members.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If the default visibility value were &lt;em&gt;not&lt;/em&gt; &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;shared&lt;/span&gt;&lt;/code&gt;, then v1 would need to be
modified so that &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;private&lt;/span&gt;&lt;/code&gt; images could accept members and be accessed by
members.  This, however, would create a situation where an image would behave
radically differently depending upon whether you tried to access it by the v1
or the v2 API.  We don’t want to do that.&lt;/p&gt;
&lt;p&gt;A key question here is whether changing the default visibility from &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;private&lt;/span&gt;&lt;/code&gt;
to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;shared&lt;/span&gt;&lt;/code&gt; introduces a backward incompatibility into the v2 API.  Here are
three arguments that it does not:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;The current situation is that the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;visibility&lt;/span&gt;&lt;/code&gt; of an image created by a
non-admin user has &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;visibility&lt;/span&gt;&lt;/code&gt; != &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;public&lt;/span&gt;&lt;/code&gt;.  That situation is
preserved.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If we &lt;em&gt;don’t&lt;/em&gt; make the default visibility &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;shared&lt;/span&gt;&lt;/code&gt;, then we are in fact
introducing a backward incompatibility in that any current user scripts that
create an image and then immediately add members to it will break.  (This
was in fact a problem with an earlier version of this spec.  While the API
working group agreed that it was a “minor” backward incompatibility that
would be permissible, they pointed out that Glance users were likely to be
annoyed by the workflow change.  The change in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;visibility&lt;/span&gt;&lt;/code&gt; value is a
lesser of two evils.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What we want to be the case is that when a user creates an image without
specifying a visibility, the image behaves the same way it does now.  Images
that behave in that way have the visibility that we now call &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;shared&lt;/span&gt;&lt;/code&gt;.
This is to be expected; previously, we had insufficient keywords to identify
the various accessibility statuses of images; now we do, and we should
use these keywords appropriately.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The conclusion is that setting the default visibility to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;private&lt;/span&gt;&lt;/code&gt; would
have a greater end user impact than the proposal to make the default visibility
value &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;shared&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Note that if the v2 API is used to set the visibility of an image to
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;private&lt;/span&gt;&lt;/code&gt;, if the v1 API is used to share the image, the request will fail
with a 409 (as it will if a member-related call is made to the v2 API).  This
is appropriate, as someone has explicitly disabled sharing for that image.&lt;/p&gt;
&lt;p&gt;One final point implicit in the foregoing is worth stating explicitly.  If the
v1 API is used to update the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;is_public&lt;/span&gt;&lt;/code&gt; property of an image, it will have
the following effect upon the image’s visibility:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;If the call updates &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;is_public&lt;/span&gt;&lt;/code&gt; to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;True&lt;/span&gt;&lt;/code&gt;, then the corresponding v2
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;visibility&lt;/span&gt;&lt;/code&gt; of the image will be &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;public&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If the call sets &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;is_public&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;, then the corresponding v2
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;visibility&lt;/span&gt;&lt;/code&gt; of the image will be set to the default value, that is,
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;shared&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This will preserve backward-compatible behavior in the v1 API.  The arguments
advanced previously in favor of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;shared&lt;/span&gt;&lt;/code&gt; being the default visibility apply
to this case as well.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="migration-of-the-visibility-of-existing-images"&gt;
&lt;h4&gt;Migration of the visibility of existing images&lt;/h4&gt;
&lt;p&gt;The issue of how the database migration should work was sufficiently
controversial that an operators’ survey was taken to gather data &lt;a class="reference internal" href="#sur1" id="id3"&gt;&lt;span&gt;[SUR1]&lt;/span&gt;&lt;/a&gt;.  The
results of the survey were reported in &lt;a class="reference internal" href="#sur2" id="id4"&gt;&lt;span&gt;[SUR2]&lt;/span&gt;&lt;/a&gt; (along with a recommendation for
the migration path that, as you’ll see if you read on, was ultimately
rejected).  Briefly, operators were evenly split on whether images with
visibility &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;private&lt;/span&gt;&lt;/code&gt; should all be migrated to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;shared&lt;/span&gt;&lt;/code&gt; or whether only
those images with members should be migrated to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;shared&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;We’ve had a lot of discussion on this (see the comments on &lt;a class="reference internal" href="#ger1" id="id5"&gt;&lt;span&gt;[GER1]&lt;/span&gt;&lt;/a&gt; for a
sample).  In the end, the compromise we reached is reflected in this spec.  The
primary justification for this migration path is that it’s worth trading some
minor incompatibilities between pre-Ocata and Ocata image sharing in order to
avoid end user confusion when they first use Glance after a deployment has been
upgraded to Ocata and suddenly see that all the images they own now have a
visibility of ‘shared’.&lt;/p&gt;
&lt;p&gt;Thus, the end user impact of an upgrade to the Glance Ocata release will be the
following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Any existing “private” image with a non-empty member-list will be found
to have visibility ‘shared’.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Any existing “private” image that has no image members will be found to
have visibility ‘private’.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Incompatibility: v2: Unlike pre-Ocata, the visibility of the image must be
changed to ‘shared’ before the member-create call will succeed.  v1: Users
must explicitly set &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;is_public&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 the member-create
call will succeed.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Any images created after the upgrade for which a visibility is not specified
at the time of image creation will have visibility ‘shared’.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Inconsistency: The member-create call will immediately work for newly
created images with default visibility, whereas migrated images will have
to be dealt with as described above.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Pre-Ocata, an end user had “private” images that might actually be shared.
The user had to do an API call to see the member-list to determine whether
other users could access that image.  In Ocata, an end user will have images
with visibility &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;shared&lt;/span&gt;&lt;/code&gt; that may not actually be accessible to other
users.  The user must do an API call to see whether the image has a non-empty
member list.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Incompatibility: The workflow required to determine whether an image is
accessible to other users is roughly the same, but it now depends upon
&lt;em&gt;two&lt;/em&gt; aspects: (1) the visibility must be ‘shared’, and (2) the image’s
member-list must be non-empty.&lt;/p&gt;
&lt;p&gt;The upside to this incompatibility is that in the Glance Ocata release, a
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;visibility&lt;/span&gt;&lt;/code&gt; value of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;private&lt;/span&gt;&lt;/code&gt; will actually mean “private” instead
of “private or shared”.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div role="list" class="citation-list"&gt;
&lt;div class="citation" id="sur1" role="doc-biblioentry"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id3"&gt;SUR1&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-operators/2016-November/012107.html"&gt;http://lists.openstack.org/pipermail/openstack-operators/2016-November/012107.html&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class="citation" id="sur2" role="doc-biblioentry"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id4"&gt;SUR2&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-operators/2016-December/012235.html"&gt;http://lists.openstack.org/pipermail/openstack-operators/2016-December/012235.html&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class="citation" id="ger1" role="doc-biblioentry"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id5"&gt;GER1&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/396919/"&gt;https://review.openstack.org/#/c/396919/&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="client-changes"&gt;
&lt;h4&gt;Client changes&lt;/h4&gt;
&lt;p&gt;OpenStackClient, as well as the library portion of python-glancelient, will
be updated to expose this feature. The CLI glanceclient will not be supported.&lt;/p&gt;
&lt;p&gt;Users will be able to see all community images by using
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;openstack&lt;/span&gt; &lt;span class="pre"&gt;image&lt;/span&gt; &lt;span class="pre"&gt;list&lt;/span&gt; &lt;span class="pre"&gt;--community&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;An option to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;openstack&lt;/span&gt; &lt;span class="pre"&gt;image&lt;/span&gt; &lt;span class="pre"&gt;set&lt;/span&gt;&lt;/code&gt; will be added named &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;--visibility&lt;/span&gt;
&lt;span class="pre"&gt;&amp;lt;VISIBILITY_STATUS&amp;gt;&lt;/span&gt;&lt;/code&gt;, where &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;VISIBILTY_STATUS&lt;/span&gt;&lt;/code&gt; may be one of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;{public,&lt;/span&gt;
&lt;span class="pre"&gt;private,&lt;/span&gt; &lt;span class="pre"&gt;shared,&lt;/span&gt; &lt;span class="pre"&gt;community}&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;For example, to make an image a community image:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;$&lt;span class="w"&gt; &lt;/span&gt;openstack&lt;span class="w"&gt; &lt;/span&gt;image&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;--visibility&lt;span class="w"&gt; &lt;/span&gt;community&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;IMAGE&amp;gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;To make the image private again:&lt;/p&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;$&lt;span class="w"&gt; &lt;/span&gt;openstack&lt;span class="w"&gt; &lt;/span&gt;image&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;--visibility&lt;span class="w"&gt; &lt;/span&gt;private&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;IMAGE&amp;gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&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 ability to create community images is moderated using policy.json. As
mentioned above, a new rule will be created called &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;communitize_image&lt;/span&gt;&lt;/code&gt;, which
will have the default configuration of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[role:admin&lt;/span&gt; &lt;span class="pre"&gt;or&lt;/span&gt; &lt;span class="pre"&gt;rule:owner]&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Also users from Horizon will be able to see community images through
a separate tab. Details regarding the Horizon feature can be found at:
&lt;a class="reference external" href="https://blueprints.launchpad.net/horizon/+spec/glance-community-images"&gt;https://blueprints.launchpad.net/horizon/+spec/glance-community-images&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&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;timothy-symanczyk&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="reviewers"&gt;
&lt;h3&gt;Reviewers&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Core reviewer(s):&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;brian-rosmaita
nikhil-komawar&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 db API to use &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;visibility&lt;/span&gt;&lt;/code&gt; rather than &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;is_public&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add functionality for storing the community state in the interfaces to both
db backends:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;sqlalchemy&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;simple&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add functionality to enable this and accept the image using the API&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add unit tests to test various inputs to the API&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add functional tests for the lifecycle of community images&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update OpenStackClient to use the new API functionality&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Bump the API version&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;A tempest test must be added to cover creating a community image and it
transitioning between public and private states.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;New features must be documented in both glance and OpenStackClient.&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.openstack.org/p/newton-glance-image-sharing"&gt;https://etherpad.openstack.org/p/newton-glance-image-sharing&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://wiki.openstack.org/wiki/Glance-v2-community-image-sharing"&gt;https://wiki.openstack.org/wiki/Glance-v2-community-image-sharing&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://wiki.openstack.org/wiki/Glance-v2-community-image-sharing-faq"&gt;https://wiki.openstack.org/wiki/Glance-v2-community-image-sharing-faq&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://wiki.openstack.org/wiki/Glance-v2-community-image-visibility-design"&gt;https://wiki.openstack.org/wiki/Glance-v2-community-image-visibility-design&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://wiki.openstack.org/wiki/Glance-v2-community-image-sharing-use-cases"&gt;https://wiki.openstack.org/wiki/Glance-v2-community-image-sharing-use-cases&lt;/a&gt; (old)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://wiki.openstack.org/wiki/Glance-v2-community-image-sharing-use-cases-newton"&gt;https://wiki.openstack.org/wiki/Glance-v2-community-image-sharing-use-cases-newton&lt;/a&gt; (new)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/glance/+spec/community-level-v2-image-sharing"&gt;https://blueprints.launchpad.net/glance/+spec/community-level-v2-image-sharing&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
</description><pubDate>Fri, 03 Feb 2017 00:00:00 </pubDate></item><item><title>Glance Spec Lite</title><link>http://specs.openstack.org/openstack/glance-specs/specs/ocata/implemented/glance/lite-specs.html</link><description>

&lt;section id="return-409-if-removing-replacing-the-location-of-an-image-that-s-not-active"&gt;
&lt;h2&gt;Return 409 if removing/replacing the location of an image that’s not &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;active&lt;/span&gt;&lt;/code&gt;&lt;/h2&gt;
&lt;dl class="field-list simple"&gt;
&lt;dt class="field-odd"&gt;problem&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;When &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;show_multiple_locations&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;, users currently
can remove or replace locations of an image irrespective of the image
status. This can result in bad experiences for the users:- 1) If one
tries to change or remove the location for an image while it is in
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;saving&lt;/span&gt;&lt;/code&gt; state, Glance would be trying to write data to a previously
saved location while the user updates the custom location. This results
in a race condition. 2) For images that are in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;queued&lt;/span&gt;&lt;/code&gt; state and no
image data has been uploaded yet, there is no need for an image
location to be removed and permitting users to remove the image
location can result in a bad experience. However users can be allowed
to replace the image location to maintain backward compatibility and
also because replacing could mean replacing an empty location by a
non-empty image location. 3) For images in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;deactivated&lt;/span&gt;&lt;/code&gt; state, it
is essential that image locations are not updated as it does not abide
with the purpose of the image state being set to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;deactivated&lt;/span&gt;&lt;/code&gt; and
may cause security concerns.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;solution&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;1) Return Conflict Error (409 response code) if an attempt to remove
the image location is made when the status of the image
is anything but &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;active&lt;/span&gt;&lt;/code&gt;. 2) Return Conflict Error (409 response
code) if an attempt to replace the image location is made when the
status of the image is anything but &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;queued&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;impacts&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;A Conflict Error will be thrown preventing users from removing an
image location when the image status is not &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;active&lt;/span&gt;&lt;/code&gt; and replacing
an image location when the image status is not &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;queued&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;timeline&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;Expected to be merged within the ocata-1 time frame.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;link&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;&lt;a class="reference external" href="https://review.openstack.org/#/c/366995/"&gt;https://review.openstack.org/#/c/366995/&lt;/a&gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;assignee&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;Nikhil Komawar, Dharini Chandrasekar&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;section id="end-of-return-409-if-removing-replacing-the-location-of-an-image-that-s-not-active"&gt;
&lt;h3&gt;&lt;cite&gt;End of&lt;/cite&gt; Return 409 if removing/replacing the location of an image that’s not &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;active&lt;/span&gt;&lt;/code&gt;&lt;/h3&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="expand-hypervisor-type-metadata-with-virtuozzo-hypervisor"&gt;
&lt;h2&gt;Expand &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hypervisor_type&lt;/span&gt;&lt;/code&gt; metadata with Virtuozzo hypervisor&lt;/h2&gt;
&lt;dl class="field-list simple"&gt;
&lt;dt class="field-odd"&gt;problem&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;Currently it is not possible to require Virtuozzo hypervisor
by specifying hypervisor_type metadata, though Nova has had
Virtuozzo support since the Kilo release.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;solution&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;We need to expand etc/metadefs/compute-hypervisor.json
hypervisor_type property with the appropriate identifier, ‘vz’,
as defined in
&lt;a class="reference external" href="http://git.openstack.org/cgit/openstack/nova/tree/nova/compute/hv_type.py"&gt;http://git.openstack.org/cgit/openstack/nova/tree/nova/compute/hv_type.py&lt;/a&gt;.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;impacts&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;This will have documentation impact. Release note should
be added to notify interested parties about this addition.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;timeline&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;Expected to be merged within the O-2 time frame.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;link&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;&lt;a class="reference external" href="https://review.openstack.org/#/c/341623/"&gt;https://review.openstack.org/#/c/341623/&lt;/a&gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;assignee&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;Maxim Netratov&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;section id="end-of-expand-hypervisor-type-metadata-with-virtuozzo-hypervisor"&gt;
&lt;h3&gt;&lt;cite&gt;End of&lt;/cite&gt; Expand &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;hypervisor_type&lt;/span&gt;&lt;/code&gt; metadata with Virtuozzo hypervisor&lt;/h3&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="add-ploop-to-the-list-of-supported-disk-formats"&gt;
&lt;h2&gt;Add &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ploop&lt;/span&gt;&lt;/code&gt; to the list of supported disk formats&lt;/h2&gt;
&lt;dl class="field-list simple"&gt;
&lt;dt class="field-odd"&gt;problem&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;Currently ‘ploop’ format is not among supported by default disk
formats, even though it’s been supported by Nova since the Kilo release.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;solution&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;&lt;cite&gt;disk_formats&lt;/cite&gt; configuration option needs to be updated to add
‘ploop’ as one of the supported format.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;impacts&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;This will have documentation impact. Release note should
be added to notify interested parties about this addition.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;timeline&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;Expected to be merged within the O-2 time frame.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;link&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;&lt;a class="reference external" href="https://review.openstack.org/#/c/341633/"&gt;https://review.openstack.org/#/c/341633/&lt;/a&gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;assignee&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;Maxim Netratov&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;section id="end-of-add-ploop-to-list-of-supported-disk-formats"&gt;
&lt;h3&gt;&lt;cite&gt;End of&lt;/cite&gt; Add &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ploop&lt;/span&gt;&lt;/code&gt; to list of supported disk formats&lt;/h3&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="use-range-http-header-instead-of-content-range-for-parsing-requests"&gt;
&lt;h2&gt;Use &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Range&lt;/span&gt;&lt;/code&gt; HTTP header instead of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Content-Range&lt;/span&gt;&lt;/code&gt; for parsing requests&lt;/h2&gt;
&lt;dl class="field-list simple"&gt;
&lt;dt class="field-odd"&gt;problem&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;When a HTTP request for a partial image download is sent, currently
the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Content-Range&lt;/span&gt;&lt;/code&gt; header is parsed to get the byte range from the
request. Per RFC 7233 specification, the desired byte range
should be specified in HTTP requests using the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Range&lt;/span&gt;&lt;/code&gt; header
rather than the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Content-Range&lt;/span&gt;&lt;/code&gt; header. The latter is reserved for
responses to such requests. Current implementation requires users to
send requests that are not compatible with this specification.
For example, a user has to give “bytes 12-30/32” instead of
“bytes=12-32”.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;solution&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;Parse the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Range&lt;/span&gt;&lt;/code&gt; header from HTTP requests and send a
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Content-Range&lt;/span&gt;&lt;/code&gt; entity header with the server response.
Deprecate and retain the current support for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Content-Range&lt;/span&gt;&lt;/code&gt;
header requests for backward compatibility reasons.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;impacts&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;Users will be able to send partial download requests using the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Range&lt;/span&gt;&lt;/code&gt; header in the requests with the appropriate value formats.
For developers, the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Range&lt;/span&gt;&lt;/code&gt; webob parser does not have a length
attribute. We will have to pass the image size explicitly and perform
checks to identify an unsatisfiable byte range request from the
parsed &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Range&lt;/span&gt;&lt;/code&gt; header. This change will also require an API
version bump.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;timeline&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;Expected to be merged within the Ocata time frame.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-odd"&gt;link&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-odd"&gt;&lt;p&gt;&lt;a class="reference external" href="https://review.openstack.org/#/c/367528/"&gt;https://review.openstack.org/#/c/367528/&lt;/a&gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt class="field-even"&gt;assignee&lt;span class="colon"&gt;:&lt;/span&gt;&lt;/dt&gt;
&lt;dd class="field-even"&gt;&lt;p&gt;Dharini Chandrasekar&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;section id="end-of-use-range-http-header-instead-of-content-range-for-parsing-requests"&gt;
&lt;h3&gt;&lt;cite&gt;End of&lt;/cite&gt; Use &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Range&lt;/span&gt;&lt;/code&gt; HTTP header instead of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Content-Range&lt;/span&gt;&lt;/code&gt; for parsing requests&lt;/h3&gt;
&lt;/section&gt;
&lt;/section&gt;
</description><pubDate>Fri, 03 Feb 2017 00:00:00 </pubDate></item><item><title>Image Metadata API calls</title><link>http://specs.openstack.org/openstack/glance-specs/specs/api/v2/image-metadata-api-v2.html</link><description>

&lt;p&gt;The following calls allow you to create, modify, and delete image
metadata records.&lt;/p&gt;
&lt;section id="create-image"&gt;
&lt;h2&gt;Create image&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;POST /v2/images&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Request body must be JSON-encoded and conform to the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;image&lt;/span&gt;&lt;/code&gt; JSON
schema. 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="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;"e7db3b45-8db7-47ad-8109-3fb55c2c24fd"&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;"Ubuntu 12.10"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"tags"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"ubuntu"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"quantal"&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;Successful HTTP response is 201 Created with a Location header
containing the newly-created URI for the image. The response body shows
the created &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;image&lt;/span&gt;&lt;/code&gt; entity. 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="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;"e7db3b45-8db7-47ad-8109-3fb55c2c24fd"&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;"Ubuntu 12.10"&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;"queued"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"visibility"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"public"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"tags"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"ubuntu"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"quantal"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="s2"&gt;"created_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"2012-08-11T17:15:52Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"updated_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"2012-08-11T17:15:52Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"self"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"/v2/images/e7db3b45-8db7-47ad-8109-3fb55c2c24fd"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"file"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"/v2/images/e7db3b45-8db7-47ad-8109-3fb55c2c24fd/file"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"schema"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"/v2/schemas/image"&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-an-image"&gt;
&lt;span id="image-update"/&gt;&lt;h2&gt;Update an image&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;PATCH /v2/images/{image_id}&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Request body must conform to the
‘application/openstack-images-v2.1-json-patch’ media type, documented in
Appendix B. Using &lt;strong&gt;PATCH
/v2/images/e7db3b45-8db7-47ad-8109-3fb55c2c24fd&lt;/strong&gt; as 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="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"op"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"replace"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"path"&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;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"Fedora 17"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"op"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"replace"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"path"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"/tags"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"fedora"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"beefy"&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 body shows the updated &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;image&lt;/span&gt;&lt;/code&gt; entity. 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="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;"e7db3b45-8db7-47ad-8109-3fb55c2c24fd"&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;"Fedora 17"&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;"queued"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"visibility"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"public"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"tags"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"fedora"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"beefy"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="s2"&gt;"created_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"2012-08-11T17:15:52Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"updated_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"2012-08-11T17:15:52Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"self"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"/v2/images/e7db3b45-8db7-47ad-8109-3fb55c2c24fd"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"file"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"/v2/images/e7db3b45-8db7-47ad-8109-3fb55c2c24fd/file"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"schema"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"/v2/schemas/image"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The PATCH method can also be used to add or remove image properties. To
add a custom user-defined property such as “login-user” to an image, use
the following example request.&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="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"op"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"add"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"path"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"/login-user"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"kvothe"&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;Similarly, to remove a property such as “login-user” from an image, use
the following example request.&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="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"op"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"remove"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"path"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"/login-user"&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;See Appendix B for more details about the
‘application/openstack-images-v2.1-json-patch’ media type.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Property protections&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Version 2.2 of the Images API acknowledges the ability of a cloud
provider to employ &lt;em&gt;property protections&lt;/em&gt;. Thus, there may be image
properties that may not be updated or deleted by non-admin users.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="add-an-image-tag"&gt;
&lt;h2&gt;Add an image tag&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;PUT /v2/images/{image_id}/tags/{tag}&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The tag you want to add should be encoded into the request URI. For
example, to tag image e7db3b45-8db7-47ad-8109-3fb55c2c24fd with
‘miracle’, you would &lt;strong&gt;PUT
/v2/images/e7db3b45-8db7-47ad-8109-3fb55c2c24fd/tags/miracle&lt;/strong&gt;. The
request body is ignored.&lt;/p&gt;
&lt;p&gt;An image tag can be up to 255 characters in length. See the ‘image’
json-schema to determine which characters are allowed.&lt;/p&gt;
&lt;p&gt;An image can only be tagged once with a specific string. Multiple
attempts to tag an image with the same string will result in a single
instance of that string being added to the image’s tags list.&lt;/p&gt;
&lt;p&gt;An HTTP status of 204 is returned.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="delete-an-image-tag"&gt;
&lt;h2&gt;Delete an image tag&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;DELETE /v2/images/{image_id}/tags/{tag}&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The tag you want to delete should be encoded into the request URI. For
example, to remove the tag ‘miracle’ from image
e7db3b45-8db7-47ad-8109-3fb55c2c24fd, you would &lt;strong&gt;DELETE
/v2/images/e7db3b45-8db7-47ad-8109-3fb55c2c24fd/tags/miracle&lt;/strong&gt;. The
request body is ignored.&lt;/p&gt;
&lt;p&gt;An HTTP status of 204 is returned. Subsequent attempts to delete the tag
will result in a 404.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="list-images"&gt;
&lt;h2&gt;List images&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;GET /v2/images&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Request body ignored.&lt;/p&gt;
&lt;p&gt;Response body will be a list of images available to the client. 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="p"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;"images"&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;"da3b75d9-3f4a-40e7-8a2c-bfab23927dea"&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;"cirros-0.3.0-x86_64-uec-ramdisk"&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="s2"&gt;"visibility"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"public"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"size"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2254249&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"checksum"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"2cec138d7dae2aa59038ef8c9aec2390"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"tags"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"ping"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"pong"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="s2"&gt;"created_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"2012-08-10T19:23:50Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"updated_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"2012-08-10T19:23:50Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"self"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"/v2/images/da3b75d9-3f4a-40e7-8a2c-bfab23927dea"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"file"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"/v2/images/da3b75d9-3f4a-40e7-8a2c-bfab23927dea/file"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"schema"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"/v2/schemas/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;"0d5bcbc7-b066-4217-83f4-7111a60a399a"&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;"cirros-0.3.0-x86_64-uec"&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="s2"&gt;"visibility"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"public"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"size"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;25165824&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"checksum"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"2f81976cae15c16ef0010c51e3a6c163"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"tags"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
            &lt;span class="s2"&gt;"created_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"2012-08-10T19:23:50Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"updated_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"2012-08-10T19:23:50Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"self"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"/v2/images/0d5bcbc7-b066-4217-83f4-7111a60a399a"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"file"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"/v2/images/0d5bcbc7-b066-4217-83f4-7111a60a399a/file"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"schema"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"/v2/schemas/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;"e6421c88-b1ed-4407-8824-b57298249091"&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;"cirros-0.3.0-x86_64-uec-kernel"&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="s2"&gt;"visibility"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"public"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"size"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;4731440&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"checksum"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"cfb203e7267a28e435dbcb05af5910a9"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"tags"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
            &lt;span class="s2"&gt;"created_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"2012-08-10T19:23:49Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"updated_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"2012-08-10T19:23:49Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"self"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"/v2/images/e6421c88-b1ed-4407-8824-b57298249091"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"file"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"/v2/images/e6421c88-b1ed-4407-8824-b57298249091/file"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"schema"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"/v2/schemas/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;"first"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"/v2/images?limit=3"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"next"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"/v2/images?limit=3&amp;amp;marker=e6421c88-b1ed-4407-8824-b57298249091"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"schema"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"/v2/schemas/images"&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="get-images-schema"&gt;
&lt;h2&gt;Get images schema&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;GET /v2/schemas/images&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Request body ignored.&lt;/p&gt;
&lt;p&gt;The response body contains a json-schema document that shows an
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;images&lt;/span&gt;&lt;/code&gt; entity (a container of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;image&lt;/span&gt;&lt;/code&gt; entities). 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="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;"images"&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;"images"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="s2"&gt;"items"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"array"&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;"image"&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;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"string"&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="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
                    &lt;span class="s2"&gt;"visibility"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"enum"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"public"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"private"&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="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
                    &lt;span class="s2"&gt;"protected"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"boolean"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
                    &lt;span class="s2"&gt;"tags"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                        &lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"array"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="s2"&gt;"items"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
                    &lt;span class="p"&gt;},&lt;/span&gt;
                    &lt;span class="s2"&gt;"checksum"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
                    &lt;span class="s2"&gt;"size"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"integer"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
                    &lt;span class="s2"&gt;"created_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
                    &lt;span class="s2"&gt;"updated_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
                    &lt;span class="s2"&gt;"file"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
                    &lt;span class="s2"&gt;"self"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
                    &lt;span class="s2"&gt;"schema"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
                &lt;span class="p"&gt;},&lt;/span&gt;
                &lt;span class="s2"&gt;"additionalProperties"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"string"&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="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"href"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{self}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"rel"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"self"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
                    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"href"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{file}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"rel"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"enclosure"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
                    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"href"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{schema}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"rel"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"describedby"&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="s2"&gt;"schema"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="s2"&gt;"next"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="s2"&gt;"first"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="p"&gt;}&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="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"href"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{first}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"rel"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"first"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"href"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{next}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"rel"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"next"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"href"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{schema}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"rel"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"describedby"&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="get-image-schema"&gt;
&lt;h2&gt;Get image schema&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;GET /v2/schemas/image&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Request body ignored.&lt;/p&gt;
&lt;p&gt;The response body contains a json-schema document that shows an
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;image&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;&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;"image"&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;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"string"&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="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="s2"&gt;"visibility"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"enum"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"public"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"private"&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="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="s2"&gt;"protected"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"boolean"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="s2"&gt;"tags"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"array"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"items"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="s2"&gt;"checksum"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="s2"&gt;"size"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"integer"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="s2"&gt;"created_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="s2"&gt;"updated_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="s2"&gt;"file"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="s2"&gt;"self"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="s2"&gt;"schema"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="s2"&gt;"additionalProperties"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"string"&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="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"href"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{self}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"rel"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"self"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"href"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{file}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"rel"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"enclosure"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"href"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{schema}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"rel"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"describedby"&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;
</description><pubDate>Sun, 29 Jan 2017 00:00:00 </pubDate></item><item><title>CIM Namespace Metadata</title><link>http://specs.openstack.org/openstack/glance-specs/specs/mitaka/implemented/cim-namespace-metadata-definitions.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/glance/+spec/cim-namespace-metadata-definitions"&gt;https://blueprints.launchpad.net/glance/+spec/cim-namespace-metadata-definitions&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The OpenStack Kilo release introduced support for defining metadata
definitions and associating the same with different resource types.
To make workloads interoperable across OpenStack clouds, it is
necessary to adopt a common set of metadata, particularly for
hardware architecture, instruction sets, and their extensions.
The Common Information Model(CIM)[A] and the Distributed Management
Task Force (DMTF)[2] have defined a pretty exhaustive list. We
propose including the same into OpenStack.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;A standard well known set of metadata tags are useful in describing
cloud resources such as images, flavors, compute nodes and more in
the interest of making orchestration across clouds interoperable.
This is yet another step in our cloud federation story.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;I have a workload running on OpenStack cloud-A and would like it
to run no differently on OpenStack cloud-B. Flavors that specify the
properties using a common standard set of descriptors will enable this.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A Network Virtual Function vendor would like to provide an appliance
with metadata that different clouds can be expected to provide the same
level of performance, to meet its typically stringent latency needs.
Several vendors use the Open Virtualization Format (OVF) to package
their appliances, which uses the CIM format, a DMTF standard.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We would like to introduce the CIM namespace for metadata in OpenStack to foster
cloud interoperability.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;The CIM schema files for processor, resources, virtualization,
and storage [C - F] shall be parsed and json files added to
the Glance etc/metadefs directory.
The tool to parse shall also be added in the glance code base to facilitate
gathering updates to the schema files in future OpenStack releases should
there be any, though this is expected to be few and far between.&lt;/p&gt;
&lt;p&gt;The Instruction set extensions shall ignore the enabled/disabled item.
The reasoning here is that other than virtualization related instructions,
namely VT-d, VT-x, few instruction extensions are disabled after the
cloud provider expended money on buying the latest platforms.&lt;/p&gt;
&lt;p&gt;In this incarnation of the solution, we shall not introduce semantics
such as relationships between the various metadata tags. For instance,
while describing hardware, a compute host that belongs to a certain
processor architecture can only manifest instructions available in the same.&lt;/p&gt;
&lt;p&gt;In this release we shall ignore the version of the CIM schema files.
The expectation is that they will add elements, not remove elements, nor
change the type of element values. We already have support in Glance to
upload, overwrite, and merge metadata definitions [K]. This shall come
in handy when a new CIM version of tags is introduced. We could add an
API call that indicates the CIM version number supported for each of
the CIM metadata definition files.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Manually create in each cloud the CIM namespace metadata
using the metadata add API, a tedious error prone task that must be
replicated in each and every OpenStack cloud instance.&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 introduction of additional json files in the Glance etc/metadefs
directories generated from parsing the CIM schema files for [C],
[D], [E], and [F].&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;Ease of use.
The Horizon metadata for CIM namespace would look like the images captured
in [G], [H], [I], and [J] for processor related CIM namespace elements.
Goodness of elastic search is available via Searchlight APIs.&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;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;Lin Yang (lin-a-yang)&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="reviewers"&gt;
&lt;h3&gt;Reviewers&lt;/h3&gt;
&lt;p&gt;Core reviewer(s):
*  Flavio Percoco
*  Ian Cordasco
*  Nikhil Komawar&lt;/p&gt;
&lt;p&gt;Other reviewer(s):&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Zhi Yan Liu&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Travis Tripp&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;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;CIM schema to json file&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;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Tests to confirm our parsing is valid&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Tests to confirm the metadata has been uploaded correctly in OpenStack&lt;/p&gt;&lt;/li&gt;
&lt;/ol&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 stating that the CIM namespace is being introduced.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ol class="upperalpha simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://www.dmtf.org/"&gt;https://www.dmtf.org/&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://www.dmtf.org/standards/cim"&gt;https://www.dmtf.org/standards/cim&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="http://schemas.dmtf.org/wbem/cim-html/2/CIM_VirtualSystemSettingData.html"&gt;http://schemas.dmtf.org/wbem/cim-html/2/CIM_VirtualSystemSettingData.html&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="http://schemas.dmtf.org/wbem/cim-html/2/CIM_ResourceAllocationSettingData.html"&gt;http://schemas.dmtf.org/wbem/cim-html/2/CIM_ResourceAllocationSettingData.html&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="http://schemas.dmtf.org/wbem/cim-html/2/CIM_StorageAllocationSettingData.html"&gt;http://schemas.dmtf.org/wbem/cim-html/2/CIM_StorageAllocationSettingData.html&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="http://schemas.dmtf.org/wbem/cim-html/2/CIM_ProcessorAllocationSettingData.html"&gt;http://schemas.dmtf.org/wbem/cim-html/2/CIM_ProcessorAllocationSettingData.html&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://wiki.openstack.org/wiki/File:CIM_namespace.JPG"&gt;https://wiki.openstack.org/wiki/File:CIM_namespace.JPG&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://wiki.openstack.org/wiki/File:CIM_namespace1.JPG"&gt;https://wiki.openstack.org/wiki/File:CIM_namespace1.JPG&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://wiki.openstack.org/wiki/File:CIM_namespace2.JPG"&gt;https://wiki.openstack.org/wiki/File:CIM_namespace2.JPG&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://wiki.openstack.org/wiki/File:CIM_namespace3.JPG"&gt;https://wiki.openstack.org/wiki/File:CIM_namespace3.JPG&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/159532/"&gt;https://review.openstack.org/#/c/159532/&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</description><pubDate>Mon, 24 Oct 2016 00:00:00 </pubDate></item><item><title>Migrate the HTTP Store to Use Requests</title><link>http://specs.openstack.org/openstack/glance-specs/specs/mitaka/implemented/http-store-on-requests.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/glance/+spec/http-store-on-requests"&gt;https://blueprints.launchpad.net/glance/+spec/http-store-on-requests&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Currently, the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance_store&lt;/span&gt;&lt;/code&gt; uses &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;httplib&lt;/span&gt;&lt;/code&gt; to talk to the backing HTTP
Store. In the case where the store is served over plain-text (&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;http://&lt;/span&gt;&lt;/code&gt;)
this isn’t an issue. In the event that the store is served over TLS
(&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;https://&lt;/span&gt;&lt;/code&gt;) then the connection was not verified by &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;httplib&lt;/span&gt;&lt;/code&gt;.  In
order to provide verification of the connection on all versions of Python,
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance_store&lt;/span&gt;&lt;/code&gt; is moving to use Requests.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Currently, the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance_store&lt;/span&gt;&lt;/code&gt; uses &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;httplib&lt;/span&gt;&lt;/code&gt; to talk to the backing HTTP
Store. In the case where the store is served over plain-text (&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;http://&lt;/span&gt;&lt;/code&gt;)
this isn’t an issue. In the event that the store is served over TLS
(&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;https://&lt;/span&gt;&lt;/code&gt;) then the connection was not verified by &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;httplib&lt;/span&gt;&lt;/code&gt; &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;.
If an operator is serving their store over HTTPS, they may be expecting Glance
to verify the connection when downloading the image which is not the case.&lt;/p&gt;
&lt;p&gt;At the moment, when Glance downloads an image from the backing store, it does
not verify the checksum. If an attacker can properly position themselves, they
can intercept the connection by providing a fake (a.k.a., spoofed) certificate.
This allows the attacker to essentially perform a denial of service attack by
providing bad image data on the behalf of the store. This assumes that the
service consuming Glance’s images validates the checksum provided by Glance in
the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Content-MD5&lt;/span&gt;&lt;/code&gt; header. (This also assumes the attacker cannot change that
value in the database or before the header reaches the service making the
request.) If an attacker is properly positioned, they can also easily perform
surveillance of the system, even if they choose not to poison the data.&lt;/p&gt;
&lt;p&gt;Further, the attacker could monitor Glance long enough to generate a malicious
image with the appropriate checksum (since it is currently MD5 which is
no longer cryptographically secure and is increasingly easy to create a
collision &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; &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; &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;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;In order to provide verification of the connection on all versions of Python,
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance_store&lt;/span&gt;&lt;/code&gt; should use Requests. A refactor has already taken place, but
in order to provide proper backwards compatibility the HTTP Store needs new
configuration options.&lt;/p&gt;
&lt;p&gt;Users will need:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A way to disable HTTPS Verification&lt;/p&gt;
&lt;p&gt;This spec proposes naming that option &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;disable_https_verification&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A way to provide a certificate bundle for verification&lt;/p&gt;
&lt;p&gt;This spec proposes naming that option &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;https_ca_bundle&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A way to provide proxy information&lt;/p&gt;
&lt;p&gt;This spec proposes naming that option &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;http_proxy_information&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In order to reduce the impact on upgrades, this spec proposes defaulting the
new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;disable_https_verification&lt;/span&gt;&lt;/code&gt; option to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;True&lt;/span&gt;&lt;/code&gt; with logged warnings
that it will be changing to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;False&lt;/span&gt;&lt;/code&gt; by default in the next cycle. There will
be an accompanying OpenStack Security Note (OSSN) written for this case.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;The &lt;a class="reference external" href="https://review.openstack.org/177948"&gt;Encrypted and Authenticated Image Support&lt;/a&gt; specification might seem to
be an alternative but that merely secures the image data, it does not secure
the transport.&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 will improve the security of the system.&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 HTTP Store’s certificate expires, users will be unable to download
images.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;By using sessions in Requests, multiple requests will be faster due to
Requests implementation of connection pooling.&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 using self-signed certificates for their HTTP Store will need to
provide the certificate as part of a bundle to be used by &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance_store&lt;/span&gt;&lt;/code&gt; for
verification.&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;icordasc&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="reviewers"&gt;
&lt;h3&gt;Reviewers&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Core reviewer(s):&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;nikhil-komawar
flaper87&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other reviewer(s):&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;sabari&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;Re-factor the HTTP Store to use Requests&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add configuration options and documentation described above&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Write and publish an OSSN&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 be added to the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance_store&lt;/span&gt;&lt;/code&gt; library to ensure that
operators can disable verification or provide their own bundle.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;New configuration options will be added and explained.&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;&lt;a class="reference external" href="https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-9365"&gt;CVE-2014-9365&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;&lt;a class="reference external" href="http://www.mathstat.dal.ca/~selinger/md5collision/"&gt;http://www.mathstat.dal.ca/~selinger/md5collision/&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;&lt;a class="reference external" href="https://en.wikipedia.org/wiki/MD5#Collision_vulnerabilities"&gt;https://en.wikipedia.org/wiki/MD5#Collision_vulnerabilities&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;&lt;a class="reference external" href="https://eprint.iacr.org/2013/170.pdf"&gt;https://eprint.iacr.org/2013/170.pdf&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;/aside&gt;
&lt;/section&gt;
</description><pubDate>Fri, 21 Oct 2016 00:00:00 </pubDate></item><item><title>Add distinction layer in domain model</title><link>http://specs.openstack.org/openstack/glance-specs/specs/newton/approved/glance/add-distinction-layer.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/glance/+spec/add-distinction-layer"&gt;https://blueprints.launchpad.net/glance/+spec/add-distinction-layer&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;To improve the stability and performance it is suggested to make changes in
the domain by adding distinction layer, which will store all changes of the
object and pass to DB only modified attributes.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Current Glance Images v2 architectures have a defect associated with risks of
race conditions arising under heavy load on the system. Here is an example of
the race condition:
Suppose an image has properties &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;{"foo":&lt;/span&gt; &lt;span class="pre"&gt;"bar",&lt;/span&gt; &lt;span class="pre"&gt;"goo":&lt;/span&gt; &lt;span class="pre"&gt;"far"}&lt;/span&gt;&lt;/code&gt;.
User1 wants to change &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;{"foo":&lt;/span&gt; &lt;span class="pre"&gt;"baz"}&lt;/span&gt;&lt;/code&gt;.
User2 wants to change &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;{"goo":&lt;/span&gt; &lt;span class="pre"&gt;"yuck"}&lt;/span&gt;&lt;/code&gt;.
If user1 and user2 make concurrent requests, they both get the same data to
work with.
Suppose user1’s change gets written first, resulting in:
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;{"foo":&lt;/span&gt; &lt;span class="pre"&gt;"baz",&lt;/span&gt; &lt;span class="pre"&gt;"goo":&lt;/span&gt; &lt;span class="pre"&gt;"far"}&lt;/span&gt;&lt;/code&gt;.
Then user2’s change is written, resulting in:
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;{"foo":&lt;/span&gt; &lt;span class="pre"&gt;"bar",&lt;/span&gt; &lt;span class="pre"&gt;"goo":&lt;/span&gt; &lt;span class="pre"&gt;"yuck"}&lt;/span&gt;&lt;/code&gt;.
User1’s change has been reverted, which is not desired behavior.&lt;/p&gt;
&lt;p&gt;Besides this, there is an issue of unreasonably increased load on the database
when updating. This problem occurs because all image fields are being updated
each time whether they’ve been modified or not, so there is lots of
unnecessary traffic on the database. Also there is an issue an issue with
changing the status of the image.&lt;/p&gt;
&lt;p&gt;These issues do not appear at low load, but in the future, with wider use,
it can lead to serious problems, such as loss of information and unstable
behaviour.&lt;/p&gt;
&lt;p&gt;A more detailed description of the problems can be found on
references &lt;a class="footnote-reference brackets" href="#id16" id="id1" 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; and &lt;a class="footnote-reference brackets" href="#id17" id="id2" 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="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;When updating of image the original image is retrieved from the database.
Distinction layer creates dict representation of modified image and compares
it with the original one. Then it passes to DB layer dict of modified
attributes.&lt;/p&gt;
&lt;p&gt;Continuing the example from the previous section, consider the situation after
user1’s update has been processed and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;{"foo":&lt;/span&gt; &lt;span class="pre"&gt;"baz"}&lt;/span&gt;&lt;/code&gt; in the database.
User2’s distinction layer image record contains &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;{"foo":&lt;/span&gt; &lt;span class="pre"&gt;"bar"}&lt;/span&gt;&lt;/code&gt;, since that
was the state of the image when the fetch occurred.  However, since user2’s
change request doesn’t touch &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;foo&lt;/span&gt;&lt;/code&gt;, only &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;{"goo":&lt;/span&gt; &lt;span class="pre"&gt;"yuck"}&lt;/span&gt;&lt;/code&gt; will be written
to the database.
Thus the final image record will have &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;{"foo":&lt;/span&gt; &lt;span class="pre"&gt;"baz",&lt;/span&gt; &lt;span class="pre"&gt;"goo":&lt;/span&gt; &lt;span class="pre"&gt;"yuck"}&lt;/span&gt;&lt;/code&gt;
as both users intend. Of course, if user2 does actually change the value
of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;foo&lt;/span&gt;&lt;/code&gt;, then user2’s change will be persisted in the database, but this is
expected behavior.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;There have been attempts to solve the problem using inheritance.
References on commits &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;, &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;. But commits were abandoned, because
inheritance is contrary to the Glance design strategy of favoring flat
hierarchies and preferring aggregation over inheritance.&lt;/p&gt;
&lt;p&gt;Alternatively, it was suggested to forbid updates while an image is in
“saving” state. But this idea was rejected, because images tend to be in
status ‘saving’ for a relatively long period, and users expect to be able
to modify the image record during this time.
Also it fixes only a special case, when status is ‘saving’, but the whole
problem with race conditions and unreasonably increased load on the database
is still 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;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;Performance tests were conducted.
We used the database: MySQL Ver 14.14 Distrib 5.5.47
We determined the time spent in update one parameter of image. Tests showed
the dependence of the execution time of the number of requests.
Test code is presented in &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;.&lt;/p&gt;
&lt;p&gt;We tested two versions of the code:
1) “master” branch;
2) commit “Add distinction layer” &lt;a class="footnote-reference brackets" href="#id15" 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;p&gt;The results are presented in table &lt;a class="footnote-reference brackets" href="#id13" id="id7" 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 graph &lt;a class="footnote-reference brackets" href="#id14" id="id8" 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;Graph showed the dependence of the execution time of the number of requests:
* Blue line - “master” branch;
* Red line - commit “Add distinction layer” &lt;a class="footnote-reference brackets" href="#id15" id="id9" 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;p&gt;The testing concluded that the use of distinction layer accelerates update
average of 34.54%.&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;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;dshakhray&lt;/p&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;/section&gt;
&lt;section id="reviewers"&gt;
&lt;h3&gt;Reviewers&lt;/h3&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;mfedosin
nikhil
rosmaita&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;ol class="arabic simple"&gt;
&lt;li&gt;&lt;dl class="simple"&gt;
&lt;dt&gt;Implement distinction layer:&lt;/dt&gt;&lt;dd&gt;&lt;ol class="loweralpha simple"&gt;
&lt;li&gt;&lt;p&gt;Create a distinction layer and add it to ‘gateway.py’&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add classes ImageProxy, ImageRepoProxy, ImageFactoryProxy.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add to ImageRepoProxy class methods get, add, save.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add the class ImageRepoProxy additional methods to implement the logic.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Make the appropriate changes in the ‘db/simple/api.py’,
‘db/simple/api.py’, ‘db/__init__.py’.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add related functional and unit tests.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Write a documentation about this layer.&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 will be added as appropriate.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;All changes have to be described in detail in the related documentation
section.&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="#id3"&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.openstack.org/#/c/123799/"&gt;Fix incorrect status update during upload in v2&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;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.openstack.org/#/c/123722/"&gt;v2 update image persists only modified attributes&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;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://paste.openstack.org/show/497360/"&gt;Script for performance tests&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;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="http://paste.openstack.org/show/497353/"&gt;Table of performance test results&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="#id8"&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://drive.google.com/file/d/0B0Tzc8_HuQodS1VMbGpUZHhEYUE/view?usp=sharing"&gt;Graph of performance test results&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;6&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="#id9"&gt;2&lt;/a&gt;)&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://review.openstack.org/#/c/315483/"&gt;Commit “Add distinction layer”&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="#id1"&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://bugs.launchpad.net/glance/+bug/1371728"&gt;Concurrency Update issue in v2&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="#id2"&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://bugs.launchpad.net/glance/+bug/1372564"&gt;Incorrect status change after image uploading in v2&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;/aside&gt;
&lt;/section&gt;
</description><pubDate>Fri, 17 Jun 2016 00:00:00 </pubDate></item><item><title>Newton Review Priorities</title><link>http://specs.openstack.org/openstack/glance-specs/priorities/newton-priorities.html</link><description>
&lt;span id="newton-priorities"/&gt;
&lt;p&gt;The list of Newton review priorities:&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;Priority&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Owner(s)&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Specs&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;DefCore Updates&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;a class="reference external" href="https://launchpad.net/~nikhil-komawar"&gt;Nikhil Komawar&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td/&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Image Import Refactor&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;a class="reference external" href="https://launchpad.net/~rosmaita"&gt;Brian Rosmaita&lt;/a&gt;,
&lt;a class="reference external" href="https://launchpad.net/~nikhil-komawar"&gt;Nikhil Komawar&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;a class="reference external" href="https://review.openstack.org/#/c/232371/"&gt;image refactor&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Nova V1 -&amp;gt; V2 Support&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;a class="reference external" href="https://launchpad.net/~flaper87"&gt;Flavio Percoco&lt;/a&gt;,
&lt;a class="reference external" href="https://launchpad.net/~mfedosin"&gt;Mike Fedosin&lt;/a&gt;,
&lt;a class="reference external" href="https://launchpad.net/~sbiswas7"&gt;Sudipta Biswas&lt;/a&gt;,
&lt;a class="reference external" href="https://launchpad.net/~nikhil-komawar"&gt;Nikhil Komawar&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;a class="reference external" href="https://review.openstack.org/#/c/229891/"&gt;nova.image refactor&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Image Sharing&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;a class="reference external" href="https://launchpad.net/~timothy-symanczyk"&gt;Timothy Symanczyk&lt;/a&gt;,
&lt;a class="reference external" href="https://launchpad.net/~rosmaita"&gt;Brian Rosmaita&lt;/a&gt;,
&lt;a class="reference external" href="https://launchpad.net/~nikhil-komawar"&gt;Nikhil Komawar&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;a class="reference external" href="https://review.openstack.org/#/c/271019/"&gt;image sharing&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;In Tree API Docs&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;a class="reference external" href="https://launchpad.net/~rosmaita"&gt;Brian Rosmaita&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;a class="reference external" href="https://review.openstack.org/#/c/312259/"&gt;api-ref docs&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;section id="side-priorities"&gt;
&lt;h2&gt;Side Priorities&lt;/h2&gt;
&lt;p&gt;The following are important, but subject to reviewer bandwidth given the
previously stated priorities:&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;Priority&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Owner(s)&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Specs&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;Improved Help Text
For Config Options&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;a class="reference external" href="https://launchpad.net/~hemanth-makkapati"&gt;Hemanth Makkapati&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;a class="reference external" href="https://bugs.launchpad.net/glance/+bug/1570946"&gt;helptext&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
</description><pubDate>Thu, 12 May 2016 00:00:00 </pubDate></item><item><title>Public glance_store’s API refactor</title><link>http://specs.openstack.org/openstack/glance-specs/specs/newton/approved/glance_store/public-api-refactor.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/glance_store/+spec/public-api-refactor"&gt;https://blueprints.launchpad.net/glance_store/+spec/public-api-refactor&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The glance_store library was pulled out of Glance some cycles ago. In the
process, the code was not changed at all and the refactor of such code was put
on-hold for future cycles as the main goal was to have a working library as soon
as possible.&lt;/p&gt;
&lt;p&gt;The above forced the Glance team to ship a library with an API that was never
meant to be public, hence the adoption of the library in other projects has been
advised against.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;The glance_store public API is based on functions with inconsistent signatures,
which may or may not behave the same depending on the passed arguments.&lt;/p&gt;
&lt;p&gt;These set of functions worked well when the library was part of Glance but they
don’t anymore. Just to name a few examples:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;There are multiple ways to store data: &lt;cite&gt;add_to_backend&lt;/cite&gt; and
&lt;cite&gt;store_add_to_backend&lt;/cite&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Each store needs to implement a &lt;cite&gt;StoreLocation&lt;/cite&gt; class&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It’s possible to get a store class from a scheme (&lt;cite&gt;get_store_from_scheme&lt;/cite&gt;), an
URI (&lt;cite&gt;get_store_from_uri&lt;/cite&gt;) or well, from a location (&lt;em&gt;shrugs&lt;/em&gt;)
(&lt;cite&gt;get_store_from_location&lt;/cite&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The above might not strike as critical issues but they do cause a bad experience
for consumers of this library.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;The proposal is to refactor this API and provide a more consistent, backwards
compatible and clean API. The proposed change is to have a single class capable
of doing what the current set of functions do following some of the principles
in the current API:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;It &lt;em&gt;must&lt;/em&gt; be stateless&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It &lt;em&gt;must&lt;/em&gt; be capable of storing, reading and deleting data from the store.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Some functions are going to be entirely deprecated as part of this change:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;cite&gt;verify_default_store&lt;/cite&gt; Users should not need this function and it should’ve
never been public to begin with.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;cite&gt;get_store_from_(scheme|uri|location)&lt;/cite&gt; Users shouldn’t need to access the
store driver at all. These 2 functions should’ve never been public to begin
with.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The existing functions are going to be marked as deprecated and they’ll be
refactored to use the new class instead. This will help us testing the behavior
of the new implementation and it’ll verify we’re not breaking backwards
compatibility. For example, functions like &lt;cite&gt;get_from_backend&lt;/cite&gt; will use the new
class but the tests for this function won’t be changed during the Newton release.&lt;/p&gt;
&lt;p&gt;It’s important to note that this spec doesn’t propose changing &lt;em&gt;any&lt;/em&gt; of the
driver’s code. It’ll focus on the &lt;strong&gt;public&lt;/strong&gt; API. Future enhancements of
glance_store will take care of the internal API’s like driver’s.&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;Rewrite the whole library at once. We’ve attempted to do this and we’ve never
gotten past the spec step.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Do nothing. This would leave us with a library that exposes unnecessary
functionality and provides a bad experience for users.&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;N/A… I mean, none that I’m aware of besides the usual stuff (“don’t mess this
up”)&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;It’ll make devs happy/happier.&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;Flavio Percoco (flaper87)&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Anyone? Pretty please?&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="reviewers"&gt;
&lt;h3&gt;Reviewers&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Core reviewer(s):&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Anyone? Pretty please?&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;Other reviewer(s):&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 new class and tests for it&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Rewrite the existing functions&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Mark the functions to remove in the Q release as deprecated&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;Existing tests won’t be changed. New tests will be written and we’ll rely on
Glance’s gate to ensure backwards compatibility until we improve our gate story
in glance_store.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Docs will be written for this new class&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
</description><pubDate>Wed, 11 May 2016 00:00:00 </pubDate></item><item><title>Remove DB downgrade</title><link>http://specs.openstack.org/openstack/glance-specs/specs/newton/approved/glance/remove-db-downgrade.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/glance/+spec/remove-db-downgrade"&gt;https://blueprints.launchpad.net/glance/+spec/remove-db-downgrade&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;SQL Migrations are the accepted method for OpenStack projects to ensure that
a given schema is consistent across deployments. Often these migrations include
updating of the underlying data as well as modifications to the schema. It is
inadvisable to perform a downwards migration in any environment. As the bp[1]
has been approved through openstack-specs after Kilo, and many projects, such
as Nova, have implemented it, Glance should do it as well.&lt;/p&gt;
&lt;p&gt;This spec proposed the work and Glance team would like to give users a cycle
to deprecate downgrade in their environments. So we will remove them during
Newton. In Mitaka, we’ll add a deprecation warning to the DB downgrade.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Many migrations in OpenStack include data-manipulation to ensure the data
conforms to the new schema; often these data-migrations are difficult or
impossible to reverse without significant overhead. Performing a downgrade of
the schema with such data manipulation can lead to inconsistent or broken
state. The possibility of bad-states, relatively minimal testing, and no demand
for support renders a downgrade of the schema an unsafe action.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;1.Add a deprecation warning in Mitaka[3].
2.Remove the downgrade script in Newton.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Downgrade paths can continue to be supported.&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 make a full database backup of their production data before
attempting any upgrade[2].&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;Glance could not be downgrade any more after Newton and it’s still work before
it.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;As the downgrade will be remove in the future.There is no need to write new
downgrade script any more.&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;blockquote&gt;
&lt;div&gt;&lt;p&gt;wangxiyuan(wxy)&lt;/p&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;/section&gt;
&lt;section id="reviewers"&gt;
&lt;h3&gt;Reviewers&lt;/h3&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;Flavio Percoco(flaper87)
Nikhil Komawar(nikhil)&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;Add a deprecation warning for users.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Remove CLI script for downgrade.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Remove downgrade migration.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Document change.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add tests code to check there’s no downgrade any more and avoid deployer to
add new downgrade script.&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;Write a test to confirm there is no downgrade in Glance any more.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;To show that downgrade is deprecated now and will not be supported after
Newton. And to indicate how to roll back the DB after that.&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="http://specs.openstack.org/openstack/openstack-specs/specs/no-downward-sql-migration.html"&gt;http://specs.openstack.org/openstack/openstack-specs/specs/no-downward-sql-migration.html&lt;/a&gt;
[2]:&lt;a class="reference external" href="http://docs.openstack.org/openstack-ops/content/ops_upgrades-roll-back.html"&gt;http://docs.openstack.org/openstack-ops/content/ops_upgrades-roll-back.html&lt;/a&gt;
[3]:&lt;a class="reference external" href="https://bugs.launchpad.net/glance/+bug/1501233"&gt;https://bugs.launchpad.net/glance/+bug/1501233&lt;/a&gt;&lt;/p&gt;
&lt;/section&gt;
</description><pubDate>Mon, 09 May 2016 00:00:00 </pubDate></item><item><title>Buffered Reader for Swift Driver</title><link>http://specs.openstack.org/openstack/glance-specs/specs/mitaka/approved/buffered-reader-for-swift-driver.html</link><description>

&lt;p&gt;Include the URL of your launchpad blueprint:
&lt;a class="reference external" href="https://blueprints.launchpad.net/glance/+spec/buffered-reader-for-swift-driver"&gt;https://blueprints.launchpad.net/glance/+spec/buffered-reader-for-swift-driver&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This change proposal introduces a buffering wrapper around image data for use
during image uploads. This wrapper helps improve the reliability of
image uploads by providing the ability to recover from errors occurring during
the upload process. The recovering ability comes from buffering the image
segments before uploading to swift. When an error occurs, Swift client resumes
the upload process from the last successful position determined using ‘seek’
and ‘tell’ operations on the buffered image segment.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;What is the problem?
Nova uploads image data to glance via a gzip stream. Glance’s swift backend
driver reads segments of data from the gzip stream and uploads it to Swift
cluster using the swift client. During this process, if an error occurs while
uploading data to Swift cluster, swift client aborts the upload as it is
incapable of recovering from errors. This eventually triggers the Swift driver
to delete all the data uploaded thus far.&lt;/p&gt;
&lt;p&gt;Why is the problem a problem?
Being unable to recover from errors
- Has a direct and negative impact on the reliability of snapshots.
- Leads to wastage of network bandwidth utilized to upload data leading up to
the error&lt;/p&gt;
&lt;p&gt;Why is swift client incapable of recovering from errors? Why not improve it
instead?
Swift client is actually equipped to recover from socket errors, 401s, 408s,
rate-limit errors, 5XXs and others. It handles a decent range of errors and
indeed tries to recover from each of the errors in an appropriate way.  When
an error occurs, swift client tries to resume the upload by repositioning the
input source to last successful position by using the reset function [0]. The
reset function itself utilizes the ‘seek’ and ‘tell’ operations [1] on the
input source to determine the appropriate position from which the upload shall
be resumed. This approach works really well when swiftclient is working with
a file on disk or any other input source that supports ‘seek’ and ‘tell’
operations. However, in the case of image uploads from nova to glance, the
input source is a data stream, which unfortunately doesn’t support the ‘seek’
and ‘tell’ operations. This leads to swift client aborting the upload. So,
providing ‘seek’ and ‘tell’ operations on the image data source would help
solve this issue automatically by virtue of swift client’s retry mechanism.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Introduce a wrapper around image data, in the shape of a reader class called
BufferedReader, that supports ‘seek’ and ‘tell’ operations.&lt;/p&gt;
&lt;p&gt;Currently, glance uploads image data to Swift as Dynamic Large Object (DLO),
which holds the data in several smaller objects called segments.
Glance’s swift driver uses the swift client to upload each segment
individually to the backend storage. However, before passing on the image
segments to swift client, the swift driver wraps [2] the segments with
ChunkReader class [3], which enables the swift client to upload the image
segment in smaller chunks, usally 64KB in size.&lt;/p&gt;
&lt;p&gt;In the proposed approach, instead of wrapping every segment with ChunkReader,
we wrap it with BufferedReader, which buffers the image segment by tee-ing
image data to a temporary file as it’s being uploaded to Swift. As the image
segment is available on disk, BufferedReader proxies the ‘read’, ‘seek’ and
‘tell’ operations to the underlying temporary file. The temporary file is
deleted if the image segment is uploaded successfully or when the upload is
aborted after exhausting retries. If the segment fails to upload successfully,
swift client’s retry mechanism resumes the upload by repositioning the input
using ‘seek’ and ‘tell’ operations that are now available.&lt;/p&gt;
&lt;p&gt;We propose to introduce the BufferedReader as a configurable option, while
leaving the default behavior as is. Using this configuration option, the
amount of disk space used for buffering can be regulated as well. If the
allotted space for buffering is full, BufferedReader reverts to default
behavior, i.e. data is uploaded to Swift without being buffered.&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;An alternative is to use memory buffering instead of disk buffering. With
memory buffering, there’ll be a substantial increase in the memory footprint,
which may degrade the API performance. Also, disk is a cheaper resource than
memory but not necessarily faster.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A solution is proposed in [4] to solve this problem for 401s specifically.
This proposal basically works by ensuring the token is not nearing
expiration. If it is expiring soon, it renews the token. Though this works
well for 401 in particular, a similar approach may not be possible for other
errors.&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;Notifications won’t be added, modified or deleted.&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;With buffering to disk, there is an additional cost involved with writing to
and reading from disk. This may potentially add a performance penalty to image
uploads. However, the bulk of time elapsed for image upload is spent in
transferring data over the network. In comparison, read and write operations
to disk are relatively much quicker. With some thorough testing, the
performance impact of this approach can be studied in further detail.&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 the image data is buffered to disk, there will be more disk utilization on
the API than before. The disk utilization will be equivalent to:
(image segment size * number of simultaneous snapshots)&lt;/p&gt;
&lt;p&gt;Deployers need to take the extra disk utilization into account while using
this feature. Additional care should be taken so that this disk utilization
doesn’t impact the disk space available for glance cache in any way.&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;hemanth-makkapati&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;belliott
jesse-j-cook&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="reviewers"&gt;
&lt;h3&gt;Reviewers&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Core reviewer(s):&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;nikhil-komawar
stuart-mclaren&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other reviewer(s):&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;brian-rosmaita
mfedosin&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 BufferedReader class&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Make the reader class configurable and leave the default behavior as-is&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Test on devstack&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 dependencies as such but [4] is a related effort.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;The new configuration option would require documentation.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;[0] &lt;a class="reference external" href="https://github.com/openstack/python-swiftclient/blob/stable/kilo/swiftclient/client.py#L1296-L1297"&gt;https://github.com/openstack/python-swiftclient/blob/stable/kilo/swiftclient/client.py#L1296-L1297&lt;/a&gt;
[1] &lt;a class="reference external" href="https://github.com/openstack/python-swiftclient/blob/stable/kilo/swiftclient/client.py#L1376-L1381"&gt;https://github.com/openstack/python-swiftclient/blob/stable/kilo/swiftclient/client.py#L1376-L1381&lt;/a&gt;
[2] &lt;a class="reference external" href="https://github.com/openstack/glance_store/blob/master/glance_store/_drivers/swift/store.py#L546-L550"&gt;https://github.com/openstack/glance_store/blob/master/glance_store/_drivers/swift/store.py#L546-L550&lt;/a&gt;
[3] &lt;a class="reference external" href="https://github.com/openstack/glance_store/blob/master/glance_store/_drivers/swift/store.py#L928-L942"&gt;https://github.com/openstack/glance_store/blob/master/glance_store/_drivers/swift/store.py#L928-L942&lt;/a&gt;
[4] &lt;a class="reference external" href="https://review.openstack.org/#/c/199049/"&gt;https://review.openstack.org/#/c/199049/&lt;/a&gt;&lt;/p&gt;
&lt;/section&gt;
</description><pubDate>Thu, 24 Mar 2016 00:00:00 </pubDate></item><item><title>Swift Multi-tenant Store Service Token Support</title><link>http://specs.openstack.org/openstack/glance-specs/specs/mitaka/approved/swift-multi-tenant-store-service-token-support.html</link><description>

&lt;p&gt;This is a proposal for how Composite Tokens (aka Service Tokens) can be
used by Glance to improve the Swift Multi-Tenant store.&lt;/p&gt;
&lt;p&gt;Specifically, to:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Guarantee consistency between the Glance database and the Swift store.
(For example remove the ability for users to delete image objects
without Glance knowing.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Store images separately from users’ regular Swift data, preventing
noise in their account, and more clearly abstracting the Glance API.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Ensure policy enforcement&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Remove the potential for namespace collisions&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Blueprint:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/glance/+spec/swift-multi-tenant-store-service-token-support"&gt;https://blueprints.launchpad.net/glance/+spec/swift-multi-tenant-store-service-token-support&lt;/a&gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Glance uses Swift to store data on behalf of users.&lt;/p&gt;
&lt;p&gt;There are two approaches to how the data is stored:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;Single-tenant&lt;/em&gt;. Objects are stored in a single dedicated Swift account
(i.e., all data belonging to all users is stored in the same account).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;Multi-tenant&lt;/em&gt;. Objects are stored in the end-user’s Swift account (project).
Typically, dedicated container(s) are created to hold the objects.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There are advantages and limitations with both approaches as described in the
following table:&lt;/p&gt;
&lt;table class="docutils align-default"&gt;
&lt;tbody&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Item&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Feature/Topic&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Single-
Tenant&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Multi-
Tenant&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;1&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Fragile to password leak (CVE-2013-1840)&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Yes&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;2&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Fragile to token leak (*)&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Yes&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;3&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Fragile to container deletion&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Yes&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;4&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Fragile to service user deletion&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Yes&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;5&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;“Noise” in Swift account&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;Yes&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;6&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Namespace collisions (user and service
picking same name)&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;Yes&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;7&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Guarantee of consistency (Glance
database vs swift account) ($), (+)&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Yes&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;8&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Policy enforcement (e.g., Image Download)&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Yes&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;9&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Fair Swift rate limiting (users unaffected
by others’ Swift use)&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;Yes&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;(*) “Fragile” here means that a single leaked token could be used to&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;access all users’ image data.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;($) Users can delete objects which underpin images in the multi-tenant&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;case.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;(+) If delayed delete is enabled it’s not clear that the multi-tenant&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;case will ‘scrub’ properly. This is not being considered as part
of this spec.&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Optionally require a Service Token when accessing image data stored in a
multi-tenant Swift store.&lt;/p&gt;
&lt;p&gt;This proposal uses the “Service Token Composite Authorization” support in
the Keystone middleware &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;p&gt;This proposal also uses the Swift support for multiple reseller prefixes
which allow storing objects in project-specific accounts while retaining
control over how those objects are accessed via Composite Tokens &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;.&lt;/p&gt;
&lt;p&gt;The changes will apply to all accesses to the Swift backend (upload,
download etc).&lt;/p&gt;
&lt;p&gt;Example: Existing Image Download:&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;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="mf"&gt;1.&lt;/span&gt; &lt;span class="n"&gt;Get&lt;/span&gt; &lt;span class="n"&gt;Glance&lt;/span&gt; &lt;span class="n"&gt;Image&lt;/span&gt; &lt;span class="mi"&gt;123&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&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="n"&gt;glance&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;9292&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;v2&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;images&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;123&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;
        &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;AUTH&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;TOKEN&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;token&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="n"&gt;project&lt;/span&gt; &lt;span class="s1"&gt;'abc'&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;v&lt;/span&gt;&lt;span class="o"&gt;---------+&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;     &lt;span class="n"&gt;Glance&lt;/span&gt;      &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="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;Get&lt;/span&gt; &lt;span class="n"&gt;Swift&lt;/span&gt; &lt;span class="n"&gt;Object&lt;/span&gt; &lt;span class="n"&gt;Data&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&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="n"&gt;swift&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;8080&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;v1&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;AUTH_abc&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;glance_123&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;123&lt;/span&gt;
        &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;AUTH&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;TOKEN&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;token&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="n"&gt;project&lt;/span&gt; &lt;span class="s1"&gt;'abc'&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;v&lt;/span&gt;&lt;span class="o"&gt;---------+&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;      &lt;span class="n"&gt;Swift&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 proposed access model has two changes:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Rather than using the standard &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;AUTH_&lt;/span&gt;&lt;/code&gt; Swift reseller prefix a specialized
prefix, eg &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;IMAGE_&lt;/span&gt;&lt;/code&gt; will be used.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A service token will be generated and supplied with the Swift request&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Example: Proposed Image Download:&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;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="mf"&gt;1.&lt;/span&gt; &lt;span class="n"&gt;Get&lt;/span&gt; &lt;span class="n"&gt;Glance&lt;/span&gt; &lt;span class="n"&gt;Image&lt;/span&gt; &lt;span class="mi"&gt;456&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&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="n"&gt;glance&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;9292&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;v2&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;images&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;456&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;
        &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;AUTH&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;TOKEN&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;token&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="n"&gt;project&lt;/span&gt; &lt;span class="s1"&gt;'abc'&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;v&lt;/span&gt;&lt;span class="o"&gt;---------+&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;     &lt;span class="n"&gt;Glance&lt;/span&gt;      &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="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;Get&lt;/span&gt; &lt;span class="n"&gt;Swift&lt;/span&gt; &lt;span class="n"&gt;Object&lt;/span&gt; &lt;span class="n"&gt;Data&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&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="n"&gt;swift&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;8080&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;v1&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;IMAGE_abc&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;glance_456&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;456&lt;/span&gt;
        &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;AUTH&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;TOKEN&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;token&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="n"&gt;project&lt;/span&gt; &lt;span class="s1"&gt;'abc'&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;X&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;-&lt;/span&gt;&lt;span class="n"&gt;TOKEN&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;token&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;Glance&lt;/span&gt; &lt;span class="n"&gt;service&lt;/span&gt; &lt;span class="n"&gt;project&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;v&lt;/span&gt;&lt;span class="o"&gt;---------+&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;      &lt;span class="n"&gt;Swift&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 service token will be generated much as a token for the single-tenant
Swift store is today, ie credentials will be stored as part of Glance’s
configuration. Unlike the single-tenant store credentials, if the
multi-tenant service account credentials leak they will not give direct
access to all images.&lt;/p&gt;
&lt;p&gt;The combination of the user and service token will allow access for for
project &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;abc&lt;/span&gt;&lt;/code&gt; under the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;IMAGE_&lt;/span&gt;&lt;/code&gt; reseller prefix. Specifically, Swift
will verify that the service token contains the particular role required
to access the relevant reseller prefix. (For more detailed information
see the relevant Swift spec &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;).&lt;/p&gt;
&lt;p&gt;The Swift reseller prefix can be operator defined, and will be part of
both the Swift and Glance configuration.&lt;/p&gt;
&lt;p&gt;Requests to Swift for the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;IMAGE_&lt;/span&gt;&lt;/code&gt; prefix which do not contain a suitably
scoped service token will return HTTP Forbidden (403).&lt;/p&gt;
&lt;p&gt;Existing non-service token behaviour will continue to be supported.&lt;/p&gt;
&lt;p&gt;Service token generation will not be tied to a particular project. There
is no reliance on a particular project. If the project is deleted a new
project with the same role can be created and used to generate the service
token.&lt;/p&gt;
&lt;p&gt;A rolling password change of the service project can be performed by
using either two separate projects or two users in the same project.&lt;/p&gt;
&lt;p&gt;If an operator modifies their configuration to take advantage of the new
behaviour pre-existing images — images stored under the old reseller prefix
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;AUTH_&lt;/span&gt;&lt;/code&gt; — will continue to be accessible. The service token will
still be supplied to Swift, but it will be ignored.&lt;/p&gt;
&lt;p&gt;Example: Image Download, backwards compatibility:&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;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="mf"&gt;1.&lt;/span&gt; &lt;span class="n"&gt;Get&lt;/span&gt; &lt;span class="n"&gt;Glance&lt;/span&gt; &lt;span class="n"&gt;Image&lt;/span&gt; &lt;span class="mi"&gt;123&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&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="n"&gt;glance&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;9292&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;v2&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;images&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;123&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;
        &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;AUTH&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;TOKEN&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;token&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="n"&gt;project&lt;/span&gt; &lt;span class="s1"&gt;'abc'&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;v&lt;/span&gt;&lt;span class="o"&gt;---------+&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;     &lt;span class="n"&gt;Glance&lt;/span&gt;      &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="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;Get&lt;/span&gt; &lt;span class="n"&gt;Swift&lt;/span&gt; &lt;span class="n"&gt;Object&lt;/span&gt; &lt;span class="n"&gt;Data&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&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="n"&gt;swift&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;8080&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;v1&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;AUTH_abc&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;glance_123&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;123&lt;/span&gt;
        &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;AUTH&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;TOKEN&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;token&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="n"&gt;project&lt;/span&gt; &lt;span class="s1"&gt;'abc'&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;X&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;-&lt;/span&gt;&lt;span class="n"&gt;TOKEN&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;token&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;Glance&lt;/span&gt; &lt;span class="n"&gt;service&lt;/span&gt; &lt;span class="n"&gt;project&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;v&lt;/span&gt;&lt;span class="o"&gt;---------+&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;      &lt;span class="n"&gt;Swift&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 id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Two Swift installations could be used to give similar behaviour by firewalling
user access to one Swift. That would incur a lot of hardware and operator overhead.&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 is no impact on the data model per se.&lt;/p&gt;
&lt;p&gt;(New image ‘location’ entries will be slightly different, as they will contain
a different Swift path.)&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 enhances security by preventing direct access to image
data via Swift. This removes the ability to bypass, for example, the image
download policy for public images, shared images, and user owned images.&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;New image objects will not be listed in users’ Swift accounts.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;A service token will need to be requested by the Glance API process when
Swift data is accessed.  This should have minimal impact.  The token
can be cached so will only impact a minority of requests which access
Swift. Requests which do not access Swift (eg listing images) will not
require a service token.&lt;/p&gt;
&lt;p&gt;There may be more cases of tokens expiring (and hitting uploads/downloads)
as both the user token and the service token can potentially expire.
There are some current efforts around mitigating token expiration. It
may be possible to re-use some of those efforts for the service token.&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 need to create a service project and modify their Swift
and Glance configurations if they wish to take advantage of the new
behaviour. (Unmodified configurations will work as before.)&lt;/p&gt;
&lt;p&gt;Pre-existing images will continue to be accessible.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;We may propose some changes to python-swiftclient.&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: Stuart McLaren&lt;/p&gt;
&lt;/section&gt;
&lt;section id="reviewers"&gt;
&lt;h3&gt;Reviewers&lt;/h3&gt;
&lt;p&gt;Core reviewer(s): Flavio Percoco, Nikhil Komawar&lt;/p&gt;
&lt;p&gt;Other reviewer(s): TBD&lt;/p&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Handle new configuration (Service credentials, Swift reseller prefix)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Token generation/caching&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Any swift client changes&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Test rolling password change&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;Keystone changes to introduce the concept of Service Tokens have been implemented &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;&lt;/p&gt;
&lt;p&gt;Swift changes to introduce support for Service Tokens/multiple reseller prefixes have been implemented &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;&lt;/p&gt;
&lt;p&gt;Required Swift client changes have been implemented &lt;a class="footnote-reference brackets" href="#id9" 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&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Ideally this would become the default configuration for Glance tests in
Tempest, and also the default configuration for devstack.&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;Example policy files will need to be created that show how to use the new
data provided from &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;X-SERVICE-TOKEN&lt;/span&gt;&lt;/code&gt; when making policy enforcement
decisions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update the Glance configuration docs&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="#id4"&gt;2&lt;/a&gt;)&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="http://git.openstack.org/cgit/openstack/keystone-specs/tree/specs/keystonemiddleware/implemented/service-tokens.rst"&gt;http://git.openstack.org/cgit/openstack/keystone-specs/tree/specs/keystonemiddleware/implemented/service-tokens.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;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="#id5"&gt;3&lt;/a&gt;)&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="http://git.openstack.org/cgit/openstack/swift-specs/tree/specs/done/service_token.rst"&gt;http://git.openstack.org/cgit/openstack/swift-specs/tree/specs/done/service_token.rst&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;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/182640"&gt;https://review.openstack.org/#/c/182640&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;/aside&gt;
&lt;/section&gt;
</description><pubDate>Thu, 24 Mar 2016 00:00:00 </pubDate></item><item><title>Buffered Reader for Swift Driver</title><link>http://specs.openstack.org/openstack/glance-specs/specs/newton/approved/glance_store/buffered-reader-for-swift-driver.html</link><description>

&lt;p&gt;Include the URL of your launchpad blueprint:
&lt;a class="reference external" href="https://blueprints.launchpad.net/glance/+spec/buffered-reader-for-swift-driver"&gt;https://blueprints.launchpad.net/glance/+spec/buffered-reader-for-swift-driver&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This change proposal introduces a buffering wrapper around image data for use
during image uploads. This wrapper helps improve the reliability of
image uploads by providing the ability to recover from errors occurring during
the upload process. The recovering ability comes from buffering the image
segments before uploading to swift. When an error occurs, Swift client resumes
the upload process from the last successful position determined using ‘seek’
and ‘tell’ operations on the buffered image segment.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;What is the problem?
Nova uploads image data to glance via a gzip stream. Glance’s swift backend
driver reads segments of data from the gzip stream and uploads it to Swift
cluster using the swift client. During this process, if an error occurs while
uploading data to Swift cluster, swift client aborts the upload as it is
incapable of recovering from errors. This eventually triggers the Swift driver
to delete all the data uploaded thus far.&lt;/p&gt;
&lt;p&gt;Why is the problem a problem?
Being unable to recover from errors
- Has a direct and negative impact on the reliability of snapshots.
- Leads to wastage of network bandwidth utilized to upload data leading up to
the error&lt;/p&gt;
&lt;p&gt;Why is swift client incapable of recovering from errors? Why not improve it
instead?
Swift client is actually equipped to recover from socket errors, 401s, 408s,
rate-limit errors, 5XXs and others. It handles a decent range of errors and
indeed tries to recover from each of the errors in an appropriate way.  When
an error occurs, swift client tries to resume the upload by repositioning the
input source to last successful position by using the reset function [0]. The
reset function itself utilizes the ‘seek’ and ‘tell’ operations [1] on the
input source to determine the appropriate position from which the upload shall
be resumed. This approach works really well when swiftclient is working with
a file on disk or any other input source that supports ‘seek’ and ‘tell’
operations. However, in the case of image uploads from nova to glance, the
input source is a data stream, which unfortunately doesn’t support the ‘seek’
and ‘tell’ operations. This leads to swift client aborting the upload. So,
providing ‘seek’ and ‘tell’ operations on the image data source would help
solve this issue automatically by virtue of swift client’s retry mechanism.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Introduce a wrapper around image data, in the shape of a reader class called
BufferedReader, that supports ‘seek’ and ‘tell’ operations.&lt;/p&gt;
&lt;p&gt;Currently, glance uploads image data to Swift as Dynamic Large Object (DLO),
which holds the data in several smaller objects called segments.
Glance’s swift driver uses the swift client to upload each segment
individually to the backend storage. However, before passing on the image
segments to swift client, the swift driver wraps [2] the segments with
ChunkReader class [3], which enables the swift client to upload the image
segment in smaller chunks, usally 64KB in size.&lt;/p&gt;
&lt;p&gt;In the proposed approach, instead of wrapping every segment with ChunkReader,
we wrap it with BufferedReader, which buffers the image segment by tee-ing
image data to a temporary file as it’s being uploaded to Swift. As the image
segment is available on disk, BufferedReader proxies the ‘read’, ‘seek’ and
‘tell’ operations to the underlying temporary file. The temporary file is
deleted if the image segment is uploaded successfully or when the upload is
aborted after exhausting retries. If the segment fails to upload successfully,
swift client’s retry mechanism resumes the upload by repositioning the input
using ‘seek’ and ‘tell’ operations that are now available.&lt;/p&gt;
&lt;p&gt;We propose to introduce the BufferedReader as a configurable option, while
leaving the default behavior as is. Using this configuration option, the
amount of disk space used for buffering can be regulated as well. If the
allotted space for buffering is full, BufferedReader reverts to default
behavior, i.e. data is uploaded to Swift without being buffered.&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;An alternative is to use memory buffering instead of disk buffering. With
memory buffering, there’ll be a substantial increase in the memory footprint,
which may degrade the API performance. Also, disk is a cheaper resource than
memory but not necessarily faster.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A solution is proposed in [4] to solve this problem for 401s specifically.
This proposal basically works by ensuring the token is not nearing
expiration. If it is expiring soon, it renews the token. Though this works
well for 401 in particular, a similar approach may not be possible for other
errors.&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;Notifications won’t be added, modified or deleted.&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;With buffering to disk, there is an additional cost involved with writing to
and reading from disk. This may potentially add a performance penalty to image
uploads. However, the bulk of time elapsed for image upload is spent in
transferring data over the network. In comparison, read and write operations
to disk are relatively much quicker. With some thorough testing, the
performance impact of this approach can be studied in further detail.&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 the image data is buffered to disk, there will be more disk utilization on
the API than before. The disk utilization will be equivalent to:
(image segment size * number of simultaneous snapshots)&lt;/p&gt;
&lt;p&gt;Deployers need to take the extra disk utilization into account while using
this feature. Additional care should be taken so that this disk utilization
doesn’t impact the disk space available for glance cache in any way.&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;hemanth-makkapati&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;belliott
jesse-j-cook&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="reviewers"&gt;
&lt;h3&gt;Reviewers&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Core reviewer(s):&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;nikhil-komawar
stuart-mclaren&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other reviewer(s):&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;brian-rosmaita
mfedosin&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 BufferedReader class&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Make the reader class configurable and leave the default behavior as-is&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Test on devstack&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 dependencies as such but [4] is a related effort.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;The new configuration option would require documentation.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;[0] &lt;a class="reference external" href="https://github.com/openstack/python-swiftclient/blob/stable/kilo/swiftclient/client.py#L1296-L1297"&gt;https://github.com/openstack/python-swiftclient/blob/stable/kilo/swiftclient/client.py#L1296-L1297&lt;/a&gt;
[1] &lt;a class="reference external" href="https://github.com/openstack/python-swiftclient/blob/stable/kilo/swiftclient/client.py#L1376-L1381"&gt;https://github.com/openstack/python-swiftclient/blob/stable/kilo/swiftclient/client.py#L1376-L1381&lt;/a&gt;
[2] &lt;a class="reference external" href="https://github.com/openstack/glance_store/blob/master/glance_store/_drivers/swift/store.py#L546-L550"&gt;https://github.com/openstack/glance_store/blob/master/glance_store/_drivers/swift/store.py#L546-L550&lt;/a&gt;
[3] &lt;a class="reference external" href="https://github.com/openstack/glance_store/blob/master/glance_store/_drivers/swift/store.py#L928-L942"&gt;https://github.com/openstack/glance_store/blob/master/glance_store/_drivers/swift/store.py#L928-L942&lt;/a&gt;
[4] &lt;a class="reference external" href="https://review.openstack.org/#/c/199049/"&gt;https://review.openstack.org/#/c/199049/&lt;/a&gt;&lt;/p&gt;
&lt;/section&gt;
</description><pubDate>Thu, 24 Mar 2016 00:00:00 </pubDate></item><item><title>Swift Multi-tenant Store Service Token Support</title><link>http://specs.openstack.org/openstack/glance-specs/specs/newton/approved/glance_store/swift-multi-tenant-store-service-token-support.html</link><description>

&lt;p&gt;This is a proposal for how Composite Tokens (aka Service Tokens) can be
used by Glance to improve the Swift Multi-Tenant store.&lt;/p&gt;
&lt;p&gt;Specifically, to:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Guarantee consistency between the Glance database and the Swift store.
(For example remove the ability for users to delete image objects
without Glance knowing.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Store images separately from users’ regular Swift data, preventing
noise in their account, and more clearly abstracting the Glance API.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Ensure policy enforcement&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Remove the potential for namespace collisions&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Blueprint:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/glance/+spec/swift-multi-tenant-store-service-token-support"&gt;https://blueprints.launchpad.net/glance/+spec/swift-multi-tenant-store-service-token-support&lt;/a&gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Glance uses Swift to store data on behalf of users.&lt;/p&gt;
&lt;p&gt;There are two approaches to how the data is stored:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;Single-tenant&lt;/em&gt;. Objects are stored in a single dedicated Swift account
(i.e., all data belonging to all users is stored in the same account).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;Multi-tenant&lt;/em&gt;. Objects are stored in the end-user’s Swift account (project).
Typically, dedicated container(s) are created to hold the objects.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There are advantages and limitations with both approaches as described in the
following table:&lt;/p&gt;
&lt;table class="docutils align-default"&gt;
&lt;tbody&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Item&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Feature/Topic&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Single-
Tenant&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Multi-
Tenant&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;1&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Fragile to password leak (CVE-2013-1840)&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Yes&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;2&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Fragile to token leak (*)&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Yes&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;3&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Fragile to container deletion&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Yes&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;4&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Fragile to service user deletion&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Yes&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;5&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;“Noise” in Swift account&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;Yes&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;6&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Namespace collisions (user and service
picking same name)&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;Yes&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;7&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Guarantee of consistency (Glance
database vs swift account) ($), (+)&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Yes&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;8&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Policy enforcement (e.g., Image Download)&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Yes&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;9&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Fair Swift rate limiting (users unaffected
by others’ Swift use)&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;Yes&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;(*) “Fragile” here means that a single leaked token could be used to&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;access all users’ image data.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;($) Users can delete objects which underpin images in the multi-tenant&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;case.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;(+) If delayed delete is enabled it’s not clear that the multi-tenant&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;case will ‘scrub’ properly. This is not being considered as part
of this spec.&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Optionally require a Service Token when accessing image data stored in a
multi-tenant Swift store.&lt;/p&gt;
&lt;p&gt;This proposal uses the “Service Token Composite Authorization” support in
the Keystone middleware &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;p&gt;This proposal also uses the Swift support for multiple reseller prefixes
which allow storing objects in project-specific accounts while retaining
control over how those objects are accessed via Composite Tokens &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;.&lt;/p&gt;
&lt;p&gt;The changes will apply to all accesses to the Swift backend (upload,
download etc).&lt;/p&gt;
&lt;p&gt;Example: Existing Image Download:&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;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="mf"&gt;1.&lt;/span&gt; &lt;span class="n"&gt;Get&lt;/span&gt; &lt;span class="n"&gt;Glance&lt;/span&gt; &lt;span class="n"&gt;Image&lt;/span&gt; &lt;span class="mi"&gt;123&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&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="n"&gt;glance&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;9292&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;v2&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;images&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;123&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;
        &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;AUTH&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;TOKEN&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;token&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="n"&gt;project&lt;/span&gt; &lt;span class="s1"&gt;'abc'&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;v&lt;/span&gt;&lt;span class="o"&gt;---------+&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;     &lt;span class="n"&gt;Glance&lt;/span&gt;      &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="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;Get&lt;/span&gt; &lt;span class="n"&gt;Swift&lt;/span&gt; &lt;span class="n"&gt;Object&lt;/span&gt; &lt;span class="n"&gt;Data&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&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="n"&gt;swift&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;8080&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;v1&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;AUTH_abc&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;glance_123&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;123&lt;/span&gt;
        &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;AUTH&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;TOKEN&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;token&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="n"&gt;project&lt;/span&gt; &lt;span class="s1"&gt;'abc'&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;v&lt;/span&gt;&lt;span class="o"&gt;---------+&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;      &lt;span class="n"&gt;Swift&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 proposed access model has two changes:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Rather than using the standard &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;AUTH_&lt;/span&gt;&lt;/code&gt; Swift reseller prefix a specialized
prefix, eg &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;IMAGE_&lt;/span&gt;&lt;/code&gt; will be used.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A service token will be generated and supplied with the Swift request&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Example: Proposed Image Download:&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;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="mf"&gt;1.&lt;/span&gt; &lt;span class="n"&gt;Get&lt;/span&gt; &lt;span class="n"&gt;Glance&lt;/span&gt; &lt;span class="n"&gt;Image&lt;/span&gt; &lt;span class="mi"&gt;456&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&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="n"&gt;glance&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;9292&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;v2&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;images&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;456&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;
        &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;AUTH&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;TOKEN&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;token&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="n"&gt;project&lt;/span&gt; &lt;span class="s1"&gt;'abc'&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;v&lt;/span&gt;&lt;span class="o"&gt;---------+&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;     &lt;span class="n"&gt;Glance&lt;/span&gt;      &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="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;Get&lt;/span&gt; &lt;span class="n"&gt;Swift&lt;/span&gt; &lt;span class="n"&gt;Object&lt;/span&gt; &lt;span class="n"&gt;Data&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&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="n"&gt;swift&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;8080&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;v1&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;IMAGE_abc&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;glance_456&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;456&lt;/span&gt;
        &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;AUTH&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;TOKEN&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;token&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="n"&gt;project&lt;/span&gt; &lt;span class="s1"&gt;'abc'&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;X&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;-&lt;/span&gt;&lt;span class="n"&gt;TOKEN&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;token&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;Glance&lt;/span&gt; &lt;span class="n"&gt;service&lt;/span&gt; &lt;span class="n"&gt;project&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;v&lt;/span&gt;&lt;span class="o"&gt;---------+&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;      &lt;span class="n"&gt;Swift&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 service token will be generated much as a token for the single-tenant
Swift store is today, ie credentials will be stored as part of Glance’s
configuration. Unlike the single-tenant store credentials, if the
multi-tenant service account credentials leak they will not give direct
access to all images.&lt;/p&gt;
&lt;p&gt;The combination of the user and service token will allow access for for
project &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;abc&lt;/span&gt;&lt;/code&gt; under the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;IMAGE_&lt;/span&gt;&lt;/code&gt; reseller prefix. Specifically, Swift
will verify that the service token contains the particular role required
to access the relevant reseller prefix. (For more detailed information
see the relevant Swift spec &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;).&lt;/p&gt;
&lt;p&gt;The Swift reseller prefix can be operator defined, and will be part of
both the Swift and Glance configuration.&lt;/p&gt;
&lt;p&gt;Requests to Swift for the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;IMAGE_&lt;/span&gt;&lt;/code&gt; prefix which do not contain a suitably
scoped service token will return HTTP Forbidden (403).&lt;/p&gt;
&lt;p&gt;Existing non-service token behaviour will continue to be supported.&lt;/p&gt;
&lt;p&gt;Service token generation will not be tied to a particular project. There
is no reliance on a particular project. If the project is deleted a new
project with the same role can be created and used to generate the service
token.&lt;/p&gt;
&lt;p&gt;A rolling password change of the service project can be performed by
using either two separate projects or two users in the same project.&lt;/p&gt;
&lt;p&gt;If an operator modifies their configuration to take advantage of the new
behaviour pre-existing images — images stored under the old reseller prefix
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;AUTH_&lt;/span&gt;&lt;/code&gt; — will continue to be accessible. The service token will
still be supplied to Swift, but it will be ignored.&lt;/p&gt;
&lt;p&gt;Example: Image Download, backwards compatibility:&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;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="mf"&gt;1.&lt;/span&gt; &lt;span class="n"&gt;Get&lt;/span&gt; &lt;span class="n"&gt;Glance&lt;/span&gt; &lt;span class="n"&gt;Image&lt;/span&gt; &lt;span class="mi"&gt;123&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&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="n"&gt;glance&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;9292&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;v2&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;images&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;123&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;
        &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;AUTH&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;TOKEN&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;token&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="n"&gt;project&lt;/span&gt; &lt;span class="s1"&gt;'abc'&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;v&lt;/span&gt;&lt;span class="o"&gt;---------+&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;     &lt;span class="n"&gt;Glance&lt;/span&gt;      &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="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;Get&lt;/span&gt; &lt;span class="n"&gt;Swift&lt;/span&gt; &lt;span class="n"&gt;Object&lt;/span&gt; &lt;span class="n"&gt;Data&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&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="n"&gt;swift&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;8080&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;v1&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;AUTH_abc&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;glance_123&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;123&lt;/span&gt;
        &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;AUTH&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;TOKEN&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;token&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="n"&gt;project&lt;/span&gt; &lt;span class="s1"&gt;'abc'&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;X&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;-&lt;/span&gt;&lt;span class="n"&gt;TOKEN&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;token&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;Glance&lt;/span&gt; &lt;span class="n"&gt;service&lt;/span&gt; &lt;span class="n"&gt;project&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;v&lt;/span&gt;&lt;span class="o"&gt;---------+&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;      &lt;span class="n"&gt;Swift&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 id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Two Swift installations could be used to give similar behaviour by firewalling
user access to one Swift. That would incur a lot of hardware and operator overhead.&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 is no impact on the data model per se.&lt;/p&gt;
&lt;p&gt;(New image ‘location’ entries will be slightly different, as they will contain
a different Swift path.)&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 enhances security by preventing direct access to image
data via Swift. This removes the ability to bypass, for example, the image
download policy for public images, shared images, and user owned images.&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;New image objects will not be listed in users’ Swift accounts.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;A service token will need to be requested by the Glance API process when
Swift data is accessed.  This should have minimal impact.  The token
can be cached so will only impact a minority of requests which access
Swift. Requests which do not access Swift (eg listing images) will not
require a service token.&lt;/p&gt;
&lt;p&gt;There may be more cases of tokens expiring (and hitting uploads/downloads)
as both the user token and the service token can potentially expire.
There are some current efforts around mitigating token expiration. It
may be possible to re-use some of those efforts for the service token.&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 need to create a service project and modify their Swift
and Glance configurations if they wish to take advantage of the new
behaviour. (Unmodified configurations will work as before.)&lt;/p&gt;
&lt;p&gt;Pre-existing images will continue to be accessible.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;We may propose some changes to python-swiftclient.&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: Stuart McLaren&lt;/p&gt;
&lt;/section&gt;
&lt;section id="reviewers"&gt;
&lt;h3&gt;Reviewers&lt;/h3&gt;
&lt;p&gt;Core reviewer(s): Flavio Percoco, Nikhil Komawar&lt;/p&gt;
&lt;p&gt;Other reviewer(s): TBD&lt;/p&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Handle new configuration (Service credentials, Swift reseller prefix)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Token generation/caching&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Any swift client changes&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Test rolling password change&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;Keystone changes to introduce the concept of Service Tokens have been implemented &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;&lt;/p&gt;
&lt;p&gt;Swift changes to introduce support for Service Tokens/multiple reseller prefixes have been implemented &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;&lt;/p&gt;
&lt;p&gt;Required Swift client changes have been implemented &lt;a class="footnote-reference brackets" href="#id9" 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&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Ideally this would become the default configuration for Glance tests in
Tempest, and also the default configuration for devstack.&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;Example policy files will need to be created that show how to use the new
data provided from &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;X-SERVICE-TOKEN&lt;/span&gt;&lt;/code&gt; when making policy enforcement
decisions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update the Glance configuration docs&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="#id4"&gt;2&lt;/a&gt;)&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="http://git.openstack.org/cgit/openstack/keystone-specs/tree/specs/keystonemiddleware/implemented/service-tokens.rst"&gt;http://git.openstack.org/cgit/openstack/keystone-specs/tree/specs/keystonemiddleware/implemented/service-tokens.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;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="#id5"&gt;3&lt;/a&gt;)&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="http://git.openstack.org/cgit/openstack/swift-specs/tree/specs/done/service_token.rst"&gt;http://git.openstack.org/cgit/openstack/swift-specs/tree/specs/done/service_token.rst&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;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/182640"&gt;https://review.openstack.org/#/c/182640&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;/aside&gt;
&lt;/section&gt;
</description><pubDate>Thu, 24 Mar 2016 00:00:00 </pubDate></item><item><title>Support download from and upload to Cinder volumes</title><link>http://specs.openstack.org/openstack/glance-specs/specs/mitaka/implemented/cinder-store-upload-download.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/glance/+spec/cinder-store-upload-download"&gt;https://blueprints.launchpad.net/glance/+spec/cinder-store-upload-download&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Current Glance’s Cinder backend driver only can get the volume size but
doesn’t support read, write and deletion of volumes.&lt;/p&gt;
&lt;p&gt;As missing parts in Cinder side (listed in &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;: os-brick library,
readonly-volumes, multi-attach) are now supported, now we can implement
read (download), write (upload), and deletion for it.&lt;/p&gt;
&lt;p&gt;When an raw image is backed on the cinder store, a new volume with the image
can be created by cloning the image volume. This will be useful to launch
boot-from-volume instances rapidly as some Cinder drivers can clone a volume
efficiently using copy-on-write. It will also improves storage capacity with
the drivers which support thin-provisioning. &lt;a class="footnote-reference brackets" href="#id7" 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;&lt;/p&gt;
&lt;p&gt;Note that the image volume itself is not intended to be used as a boot-volume
for an instance. Image volumes are marked read-only, so they cannot be attached
to instances in read-write mode. Instead, cloned volumes should be used for
booting instances.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Without upload, download and deletion support of Glance’s Cinder backend
driver, it can’t be used as a default store.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;This spec proposes implementing image uploading to and downloading from Cinder
volumes, and deletion of the volume on the image deletion.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Uploading steps:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Create a new volume with the size that can store the image. It will be
placed in the tenant specified in glance-api.conf.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Attach the new volume to the glance-api host using the os-brick library.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;The os-brick library collects the connector (host) information, such as
the initiator IQN for iSCSI or WWN for FibreChannel.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Call &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;initialize_connection&lt;/span&gt;&lt;/code&gt; API of Cinder with the connector
information and the volume as arguments to get the volume connection
information, such as target portal IP address and IQN for iSCSI.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Pass the connection information to the os-brick’s &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;connect_volume&lt;/span&gt;&lt;/code&gt;
method to attach the volume to the host. The volume device information
such as the device path (e.g. &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/dev/sdX&lt;/span&gt;&lt;/code&gt;) is returned.
This step requires root privilege to execute the command for iSCSI, FC
and so on, so the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance-rootwrap&lt;/span&gt;&lt;/code&gt; must be installed and it should
allow the commands for os-brick. &lt;a class="footnote-reference brackets" href="#id6" 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;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Write the image data to the volume from the given device path.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Detach the volume from the host.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Call the os-brick’s &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;disconnect_volume&lt;/span&gt;&lt;/code&gt; method and Cinder’s
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;terminate_connection&lt;/span&gt;&lt;/code&gt; API to remove the volume connection.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Mark the volume as read-only.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add volume metadata that indicate the image size, image ID, image owner
(to track the owner even when it is placed in the service tenant). 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="s1"&gt;'image_id'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'e38f5596-4bd3-4b63-b4ef-88bcc814ed8e'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s1"&gt;'image_owner'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;     &lt;span class="s1"&gt;'b58fffa08b4242988c42950b5f24fcd5'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s1"&gt;'image_size'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;      &lt;span class="s1"&gt;'228599296'&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;/li&gt;
&lt;li&gt;&lt;p&gt;Downloading steps:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Attach the image volume to glance-api host as read-only.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Read the image data from the volume.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Detach the volume.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Deletion steps:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Call the Cinder’s &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;delete&lt;/span&gt;&lt;/code&gt; API to delete the volume when the image is
deleted.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As cinder currently doesn’t support ACL or public volumes among tenants,
in order to support public or sharable images, the image volume should be
placed in the service tenant which is only accessible from the Glance and
Cinder services to control the accessibility.&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;To attach and detach volumes to the host, root privilege is required to
operate block devices on the host. Glance needs to import oslo-rootwrap
to allow only required commands for these operations to be executed as root.&lt;/p&gt;
&lt;p&gt;The Glance node must be a part of storage network (iSCSI, FC etc.). In theory
that might open new attack vectors each way.&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;When creating a new Cinder volume from an image stored in the Glance Cinder
store, or creating a new image from a volume, Cinder is able to offload
the image copy using storage array features such as background copy or
copy-on-write, if some conditions (e.g. image stored in Cinder backend is in
raw format) are satisfied. This will improve the performance of image copy
significantly.&lt;/p&gt;
&lt;p&gt;Nova-compute will be able to bypass the image copy by attaching the image
volumes to the host, if Cinder is deployed.&lt;/p&gt;
&lt;p&gt;Note that the image upload/download requires sufficient bandwidth to/from
cinder storage.&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 cinder backends, the Glance node must be able to access the backend
storage and it may require additional hardware connectivity (iSCSI, FC, etc.).
Operators have to configure cinder and glance-api.conf appropriately.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;To enable cinder store, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cinder&lt;/span&gt;&lt;/code&gt; must be added to the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;stores&lt;/span&gt;&lt;/code&gt; option in
the glance-api.conf.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;To place the image volume into the specific tenant, authentication information
for the tenant must also be provided.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The glance-rootwrap must be installed. The rootwrap config path should also be
configured in glance-api.conf.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;To offload the image copy on volume creation to the storage array, the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;allowed_direct_url_schemes&lt;/span&gt;&lt;/code&gt; option should contain &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cinder&lt;/span&gt;&lt;/code&gt; in
cinder.conf. &lt;a class="footnote-reference brackets" href="#id7" 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; Also, the glance-api host must be able to attach the
Cinder volumes onto itself.&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&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;tsekiyam&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="reviewers"&gt;
&lt;h3&gt;Reviewers&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Core reviewer(s):&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;flaper87&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;Import os-brick and oslo-rootwrap into glance_store.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Extend current cinder backend driver to support upload, download and deletion.&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;Enable cinder backend in the devstack.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Test uploading of an image to the cinder backend.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Then test downloading of the image again.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Delete the image and check if the volume is deleted.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Test the other normal glance store operations such as owner changes and
sharing.&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 documentation should be expanded to describe how to enable and use
cinder store. Especially, it should explain new options to configure cinder
authentication (tenant id, username, password) to store the volume into the
specific tenant.&lt;/p&gt;
&lt;p&gt;It also needs to cover the requirement to Glance node being the part of storage
network (iSCSI, FC etc.) and having sufficient bandwidth towards the storage.&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;Blueprint: Adding a store driver to allow Cinder as a block storage
backend for Glance:
&lt;a class="reference external" href="https://blueprints.launchpad.net/glance/+spec/glance-cinder-driver"&gt;https://blueprints.launchpad.net/glance/+spec/glance-cinder-driver&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;2&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;Rootwrap filter for os-brick:
&lt;a class="reference external" href="https://github.com/openstack/os-brick/blob/master/etc/os-brick/rootwrap.d/os-brick.filters"&gt;https://github.com/openstack/os-brick/blob/master/etc/os-brick/rootwrap.d/os-brick.filters&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;3&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;Cloud Administrator Guide: Volume-backed image:
&lt;a class="reference external" href="http://docs.openstack.org/admin-guide-cloud/blockstorage_volume_backed_image.html"&gt;http://docs.openstack.org/admin-guide-cloud/blockstorage_volume_backed_image.html&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;/aside&gt;
&lt;/section&gt;
</description><pubDate>Tue, 01 Mar 2016 00:00:00 </pubDate></item><item><title>Supporting OVF Single Disk Image Upload</title><link>http://specs.openstack.org/openstack/glance-specs/specs/mitaka/implemented/ovf-lite.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/glance/+spec/ovf-lite"&gt;https://blueprints.launchpad.net/glance/+spec/ovf-lite&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The Open Virtualization Format (OVF) is an open standard for packaging and
distributing virtual appliances that is hypervisor and processor architecture
agnostic. Both enterprise and Telco Network Virtual Function (NVF) providers
desire OpenStack OVF support, to distribute in a standard format appliance
images and deployment requirements to ensure optimal performance. An OVF
package, also called an OVA (file extension ova), is essentially a tar ball
that contains disk images, a manifest and the ovf xml file. A common use case
is a single disk image package with the ovf file containing deployment metadata.
NFV workloads in particular tend to require enhanced platform features and
fine-grained resource provisioning to meet their performance criteria.
For example, special instructions, hardware accelerators, high speed IO, NUMA
awareness, and more. We propose to extract the single root disk image and its
metadata and  save the same in Glance with the goal of easing provisioning,
in particular eliminating the need for error prone manual editing of image
metadata.  The glance image metadata can be used by a custom filter (in the
Mitaka release no nova image properties filter changes can be upstreamed),
or by defining host aggregates using tags from the CIM namespace[H],
that which is used in the OVF to identify appropriate compute hosts.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;The OVF image format is a format backed by industry (VMware, Ericsson, IBM, and
Red Hat to name a few) and the European Telecommunications Standards Institute.
A common use case is a single disk image OVF package. To handle the same,
VMware even developed a special purpose Nova driver that launches a virtual
machine using an uploaded OVF package with a single image. However, each time
the OVF image is used, it needs to be parsed and the image and its metadata
extracted because it is not a first class glance image, incurring a
performance overhead.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;We propose supporting OVF package by adding a new task capable of extracting
the package data and metadata. Support will be limited to extracting the root
disk image and saving it to the Glance image store, followed by parsing the
.ovf file to extract desired metadata specified via a configuration file. Note
that OVF files, which are in XML format, can be complex, and XML allows users
the freedom of representing particularly leaf values as either an element or as
an attribute, making parsing non-trivial. We shall restrict ourselves in this
release to the items in CIM_ProcessorAllocationSettingData given they are of
primary interest to us for VM orchestration purposes. The extracted metadata
will be recorded as image properties on the Glance image record. Typically, the
image provider will specify metadata pertaining to hardware requirements and
deployment parameters that ensure optimal performance. This import
functionality, for the present, will be restricted to admin users, and the
feature itself can be disabled or enabled through configuration using
functionality as proposed in [L]. The metadata may serve, among other things,
to aid Nova in optimal placement/orchestration to ensure meeting vendor
performance, compliance, and/or other requirements.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;The alternative is to manually enter image metadata as it is done today, which
is both tedious and error prone, even as we try to automate service delivery in
the cloud.&lt;/p&gt;
&lt;p&gt;A full fledged solution where an OVF package has multiple disk images is out of
scope for this effort but is a logical evolution of the feature. We anticipate
in the future the creation of OVF artifacts and transforming their contents
into Heat artifacts. The richness of OVF would need to be captured in Heat,
including its networking aspects.&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;Unpacking an unknown OVA tar file can have security risks, namely gzip
expansion and tar escalation of privilege attacks[J]. In this initial
implementation we shall restrict access to OVA import to admin users.
In a future extension we could address some of these vulnerabilities such as,
examining the tar manifest first (tar tvf foo.ova) to confirm no system paths
or high value files like /etc/passwd are mentioned. To protect from gzip bomb
style attacks an anti-virus program would come in handy and should be threaded
into the process flow. A signature verification functionality would enable
opening up the import functionality to non-admin users, particularly to trusted
image suppliers.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;While notifications for OVA processing start and finish can be
helpful there shall be none at this point.&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;Ease of use.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;On image upload, additional processing takes place for the extracting and
parsing of the image data and metadata, but this only affects OVA files. Other
formats are unaffected.&lt;/p&gt;
&lt;p&gt;With regards to Nova, launching an OVF package will be faster because it is
processed on import (once) rather than on each use.&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;Existing OVF packages in Glance can be deployed as before using the VMware
driver. Once this functionality is delivered, disk images may be directly
deployed, like qcow and other images. The Nova OVF driver cannot be
deprecated until all OVF packages are processed using this new strategy.
Please note that this feature requires disk space to support untarring
of archives and that operations might fail due to inadequate disk resources.
Further, the deployer should check the value of image_property_quota in
glance-api.conf to ensure that the quota is set high enough to allow for all
the desired OVF metadata to be stored as 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&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;&lt;p&gt;A global configuration parameter specifying the metadata of interest to
extract. Per feedback, this shall be maintained in a separate file
ovf-metadata.conf with a sample file provided.
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="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;ovf_metadata_properties&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="n"&gt;ProcessorArchitecture&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="n"&gt;InstructionSet&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="n"&gt;InstructionSetExtensionName&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;Possible values:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;ProcessorArchitecture: x86, x86-64, ARM, MIPS
InstructionSet: ARM A32, ARM A64, MIPS32 (32-bit), MIPS64 (64-bit), POWER
InstructionSetExtensionName:
    Advanced Vector Extensions (AVX),
    RDRAND (aka SecureKey),
    Advanced Encryption Standard New Instruction (Intel® AES-NI).
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;See [H] for an exhaustive list.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Download OVA&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Process the embedded .ovf descriptor file to extract metadata
and the root disk. Parsing will use the schema in [G]&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Save the root disk image in Glance&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Attach the extracted metadata as image properties of the saved disk image&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;In this initial implementation we will not handle encryption keys or
OVF certificates. Doing so however would add to the security of the feature
and possibly reduce threats as mentioned in [J]. The defcore compliant
refactored image TaskFlow also provides for increased security by way of
limiting size of import and time taken.&lt;/p&gt;
&lt;p&gt;An initial implementation using the TaskFlow task executor from Liberty is
ready. When the refactored image import API becomes available, by restricting
the OVF lite import feature to admins only, migrating to the same should be
smooth. Tests to establish the same required. Thus progress on both efforts
can occur in parallel.&lt;/p&gt;
&lt;p&gt;Should we drop the desire to support upload of compressed ova, we eliminate
the threat of compression attacks. In conjunction with first examining the
embedded ovf file, it is possible to determine the anticipated size of the
disk image and ensure it is within quota before proceeding with the upload.
Thanks to Mike Gerdt for this compression constraint relaxation suggestion
to make the feature more generally available, that is not restricted to admin
users. However, for Mitaka, we shall restrict this feature to admin users
only, thus allowing compressed files, and in so doing better network
bandwidth use, and more importantly conforming to the image upload refactor
work [M] underway.&lt;/p&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;p&gt;Primary assignee:
*  Deepti Ramakrishna (dramakri)
*  Lin Yang (ling-a-yang)&lt;/p&gt;
&lt;p&gt;Other contributors:
*  Jakub Jasek
*  Kent Wang&lt;/p&gt;
&lt;/section&gt;
&lt;section id="reviewers"&gt;
&lt;h3&gt;Reviewers&lt;/h3&gt;
&lt;p&gt;Core reviewer(s):
*  nikhil-komawar
*  Erno Kuvaja
*  Ian Cordasco
*  Flavio Percoco
*  Sabari Murugesan&lt;/p&gt;
&lt;p&gt;Other reviewer(s):
*  Brian Rosmaita&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 workflows for tasks, to parse .ovf file, to create glance image
with metadata. Our Liberty solution missed the deadline.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update configuration file to indicate metadata of interest.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update configuration and usage 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;Image save task, shall confirm else enhance that it checks user quota.&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;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Tests for upload covering valid and invalid input such as invalid tar bundle,
directory with no .ovf file, zero size and excessively large input file sizes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;With OVF Lite we would upload both an OVF file in Glance and a regular image.
We could configure OpenStack to skip saving the OVF file.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Integration tests would involve being able to launch an image so loaded using Nova
boot commands without using the VMware OVF driver.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;OVF API for CRUD operations need to be documented to indicate the additional image
creation. Delete and update operations would require delete and update of the
additional image in Glance. Will help to document.&lt;/p&gt;
&lt;p&gt;Backward functionality is preserved in an upgraded system by maintaining the Nova
OVF driver.&lt;/p&gt;
&lt;p&gt;In the future it would be good to introduce a script/task to be invoked in
an upgraded environment that provides OVF Lite support for existing
OVF files in Glance.  Further, should we want to enable/disable this feature
it would be good to work on [L] which currently is abandoned.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ol class="upperalpha simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://en.wikipedia.org/wiki/Open_Virtualization_Format"&gt;https://en.wikipedia.org/wiki/Open_Virtualization_Format&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/?title=ETSI"&gt;https://en.wikipedia.org/?title=ETSI&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/juno/approved/vmware-driver-ova-support.html"&gt;http://specs.openstack.org/openstack/nova-specs/specs/juno/approved/vmware-driver-ova-support.html&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="http://docs.openstack.org/developer/glance/formats.html"&gt;http://docs.openstack.org/developer/glance/formats.html&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Original blueprint: &lt;a class="reference external" href="https://wiki.openstack.org/wiki/Enhanced-Platform-Awareness-OVF-Meta-Data-Import"&gt;https://wiki.openstack.org/wiki/Enhanced-Platform-Awareness-OVF-Meta-Data-Import&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/glance/+spec/introspection-of-images"&gt;https://blueprints.launchpad.net/glance/+spec/introspection-of-images&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;OVF Envelope XML Schema Document (XSD). &lt;a class="reference external" href="http://schemas.dmtf.org/ovf/envelope/2/dsp8023_2.0.1.xsd"&gt;http://schemas.dmtf.org/ovf/envelope/2/dsp8023_2.0.1.xsd&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="http://schemas.dmtf.org/wbem/cim-html/2/CIM_ProcessorAllocationSettingData.html"&gt;http://schemas.dmtf.org/wbem/cim-html/2/CIM_ProcessorAllocationSettingData.html&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;CIM V2.38.0 schema. &lt;a class="reference external" href="http://dmtf.org/standards/cim/cim_schema_v2380"&gt;http://dmtf.org/standards/cim/cim_schema_v2380&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://bugs.python.org/issue21109#msg215656"&gt;https://bugs.python.org/issue21109#msg215656&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/Zip_bomb"&gt;https://en.wikipedia.org/wiki/Zip_bomb&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Config option for importing subflows: &lt;a class="reference external" href="https://review.openstack.org/#/c/194898/"&gt;https://review.openstack.org/#/c/194898/&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Image Import Refactor: &lt;a class="reference external" href="https://review.openstack.org/#/c/232371"&gt;https://review.openstack.org/#/c/232371&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/glance/+spec/image-signing-and-verification-support"&gt;https://blueprints.launchpad.net/glance/+spec/image-signing-and-verification-support&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/214810/"&gt;https://review.openstack.org/#/c/214810/&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;DMTF Common Information Model (CIM). &lt;a class="reference external" href="http://dmtf.org/standards/cim"&gt;http://dmtf.org/standards/cim&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</description><pubDate>Tue, 01 Mar 2016 00:00:00 </pubDate></item><item><title>Prevention of Unauthorized errors during upload/download in Swift driver</title><link>http://specs.openstack.org/openstack/glance-specs/specs/mitaka/implemented/prevention-of-401-in-swift-driver.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/glance/+spec/prevention-of-401-in-swift-driver"&gt;https://blueprints.launchpad.net/glance/+spec/prevention-of-401-in-swift-driver&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This change proposal introduces a new mechanism for uploading/downloading
chunked files to Swift store, that prevents possible 401 errors if user
token expires during the image upload/download. It helps to improve the
reliability of image uploads and downloads by providing the ability to
re-authenticate the user during the process, thereby enhancing the stability of
the entire system.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;There are several shortcomings in the current Swift driver implementation:&lt;/p&gt;
&lt;p&gt;1. In case of upload. If an uploading into Swift file exceeds user-set size
limit, then the file is split into chunks and each chunk is uploaded with
single PUT request as an independent object. These requests require authorization
and, unfortunately, it may happen that user token expires in interim chunk,
which will lead to an Unauthorized error and fail of upload.&lt;/p&gt;
&lt;p&gt;2. In case of download. Because Swift driver supports “retrying” mechanism,
it may happen, that in case of unsuccessful operation there will be another
attempt to download the file. However, if the token has expired after the
previous attempt, the new one will fail, too, with Unauthorized error.&lt;/p&gt;
&lt;p&gt;These issues are typical for both, SingleTenant and MultiTenant implementations,
although the decisions in both cases will be different.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;It’s proposed to change workflows of uploading and downloading files into Swift
in the following manner:&lt;/p&gt;
&lt;ol class="arabic simple" start="0"&gt;
&lt;li&gt;&lt;p&gt;Prerequisites:&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;New optional dependency from python_keystoneclient has been added for Swift
backend in glance_store. The additional layer (later ‘ConnectionManager’)
between swift store and swiftclient connections will be added.
ConnectionManager will be responsible for initializing keystone client and
requesting swift client connections (if needed). ConnectionManager executes
re-authentication if connection token is going to expire soon and
re-authentication has been enabled. If re-authentication is not enabled
ConnectionManager always returns the same connection (no connection refresh).
If re-authentication is enabled, ConnectionManager requests all pre-requisites
that allow to request the new token:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;for single-tenant store: glance service user credentials (auth_url,
domain, username, password, project). All required credentials stored in
StoreLocation object that passed to the Store so there is no need for the
new parameters or config options.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;for multi-tenant store: trust id, glance service user credentials (
username, project, password). Service user credentials will be extracted
from swift_store_config_file or (swift_store_user, swift_store_key) config
options. So there is no need for new configuration options. trust_id will be
created as a result of the following steps:&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;initialize keystone client scoped to user token&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;request user roles using keystone client from 1)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;initialize keystone client scoped to glance service user project (use
username and password to create Password auth plugin) and request user_id
of the service user.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;create trust using the client from 1), user roles from 2) and user_id
from 3). Store trust_id in ConnectionManager.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;After that ConnectionManager initializes and stores keystone client.
Keystone client provides a method to request new valid token from Identity
service. ConnectionManager can use that token to build a new Swift Connection.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Note&lt;/em&gt; If client cannot be created because of some reason then glance_store
raises an exception (for single-tenant) or uses token from user context(for
multi-tenant).&lt;/p&gt;
&lt;p&gt;Additionally the method called ‘init_client’ need to be added to store and it
will be responsible for initializing of keystone client.&lt;/p&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;&lt;p&gt;Upload case.&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;&lt;em&gt;Note&lt;/em&gt; All these changes will apply only to the chunked upload. If the
upload is performed as a single request, it will use the old workflow.&lt;/p&gt;
&lt;p&gt;In general, the following scenario is proposed:&lt;/p&gt;
&lt;p&gt;1. Before the upload glance_store identifies if image need to be chunked.
In case of chunked image glance_store initializes ConnectionManager that
support re-authentication.&lt;/p&gt;
&lt;p&gt;2. Before uploading each chunk, ConnectionManager checks if
re-authentication is enabled and the token will expire soon (it uses
‘will_expire_soon’ method of authentication plugin and
swift_store_expire_soon_interval value to define when the token needs to
be requested).
If the previous condition is true then ConnectionManager requests new token
and creates new swiftclient connection. That connection will be used for
uploading the chunk.
&lt;em&gt;Note&lt;/em&gt; ‘will_expire_soon’ used because glance_store might lose the data if
request to swiftclient fail with Unauthorized error. Unfortunately,
requests library starts reading the data before checking the token so we
cannot retry the requests after failure. More specifically, the requests
library doesn’t support 100-continue.&lt;/p&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Download case.&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;In general, the following scenario is proposed:&lt;/p&gt;
&lt;p&gt;1. Before the download, glance_store identifies if swift_retry_get_count is
positive. It the option value is positive glance_store initializes
ConnectionManager that allows to re-authenticate and initialize a new
connection. Otherwise, ConnectionManager always returns the same swift
connection.&lt;/p&gt;
&lt;p&gt;2. In the case of unsuccessful download of the file, before the retry,
ConnectionManager checks if re-authentication is enabled and connection
token is going to expire soon. If the previous condition is true
ConnectionManager requests new token and returns new connection.&lt;/p&gt;
&lt;ol class="arabic simple" start="3"&gt;
&lt;li&gt;&lt;p&gt;Glance executes download retry normally.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;At least one workaround for the whole functionality is available: extend token
expiration time to allow Glance upload the image. This solution affects all
services and it does not look like long term solution.&lt;/p&gt;
&lt;p&gt;Also there are several workarounds of this issue, but they work for SingleTenant
implementation only, because for MultiTenant case valid user token is required:&lt;/p&gt;
&lt;p&gt;1. Introduce a wrapper around image data, in the shape of a reader class
called  BufferedReader, that supports ‘seek’ and ‘tell’ operations, which
buffers the image segment by tee-ing image data to a temporary file as it’s
being uploaded to Swift. It’s stated as optional resource-consuming solution
that is used when connection between Glance and Swift is unstable, because it
helps not only Unauthorized errors.&lt;/p&gt;
&lt;p&gt;2. An alternative is to use memory buffering instead of disk buffering.
With memory buffering, there’ll be a substantial increase in the memory
footprint, which may degrade the API performance. Also, disk is a cheaper
resource than memory but not necessarily faster.&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;Keystone V3 should be supported to properly use trusts mechanism.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;If image file is too big then glance_store need to create trust and initialize
client for every upload to multi-tenant store. The same needs to be done if
swift_retry_get_count is positive and user is downloading an image from
swift store in multi-tenant mode.&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 following blueprint defines buffered reader for swift driver:
&lt;a class="reference external" href="https://blueprints.launchpad.net/glance/+spec/buffered-reader-for-swift-driver"&gt;https://blueprints.launchpad.net/glance/+spec/buffered-reader-for-swift-driver&lt;/a&gt;.
It describes buffered reader that allows to retry image upload in case of
failure. It may seem that this blueprint overlaps with Upload case in this
specification but it is different. The goal of this specification is to
provide a swiftclient connection with valid token to the user. Buffered reader
is responsible for retrying the upload with the original user token.&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;mfedosin
kkushaev
dshakhray&lt;/p&gt;
&lt;/section&gt;
&lt;section id="reviewers"&gt;
&lt;h3&gt;Reviewers&lt;/h3&gt;
&lt;p&gt;flaper87
stuart-mclaren&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 ConnectionManager class&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use ConnectionManager to request connections in ‘add’ and ‘get’ method
of Swift store&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;One configuration option: will_expire_soon interval needs to be described in
documentation. It defines period of time before token expiration when
ConnectionManager must request new token and initialize new connection.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;Trusts blueprint:
&lt;a class="reference external" href="https://blueprints.launchpad.net/glance/+spec/trust-authentication"&gt;https://blueprints.launchpad.net/glance/+spec/trust-authentication&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Buffered reader blueprint:
&lt;a class="reference external" href="https://blueprints.launchpad.net/glance/+spec/buffered-reader-for-swift-driver"&gt;https://blueprints.launchpad.net/glance/+spec/buffered-reader-for-swift-driver&lt;/a&gt;&lt;/p&gt;
&lt;/section&gt;
</description><pubDate>Tue, 01 Mar 2016 00:00:00 </pubDate></item><item><title>Add filters using an ‘in’ operator</title><link>http://specs.openstack.org/openstack/glance-specs/specs/mitaka/implemented/v2-add-filters-with-in-operator.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/glance/+spec/in-filtering-operator"&gt;https://blueprints.launchpad.net/glance/+spec/in-filtering-operator&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This specification introduces a feature to the Glance v2 API for filtering
images based on lists of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;id&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;name&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;status&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;container_format&lt;/span&gt;&lt;/code&gt; or
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;disk_format&lt;/span&gt;&lt;/code&gt; using the ‘in’ operator.
This feature is important because it allows Horizon to make only one request
to Glance instead of multiple single requests, which improves the system
performance and reduces the load.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Horizon sends separate requests to get the names of the images presented in
the ID forms of the instances.
It would be better to send one request instead of a lot of separate requests.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;I propose adding the ability to filter images by the properties &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;id&lt;/span&gt;&lt;/code&gt;,
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;name&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;status&lt;/span&gt;&lt;/code&gt;,``container_format``, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;disk_format&lt;/span&gt;&lt;/code&gt; using the ‘in’
operator between the values.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Alternative is implement this type of query to the Searchlight service. But
Searchlight is an optional service, and Horizon is always required the listing
of running instances.&lt;/p&gt;
&lt;p&gt;Also this particular functionality, the “in” operator, should still be added
for the following reasons:
* consistency with Glare, which has implemented the “in” operator;
* there’s a minimum set of filters that should be allowed for effective
service-to-service communication.&lt;/p&gt;
&lt;p&gt;Thus while try searching for UIs should be offloaded to Searchlight, this
particular functionality is basic and useful enough that it’s worth including
in the API.&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;Following the pattern of existing filters, new filters may be specified as
query parameters using the field to filter as the key and the filter criteria
as the value in the parameter.&lt;/p&gt;
&lt;p&gt;Filtering based on the principle of full compliance with the template,
for example ‘name = in:deb’ does not match ‘debian’.&lt;/p&gt;
&lt;p&gt;Changes apply exclusively to the API v2 Image entity listings:&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&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;v2&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;images&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;image&lt;/span&gt;\&lt;span class="n"&gt;_id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Filter by adding optional query parameters:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;disk_format&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;container_format&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;An example of an acceptance criteria using the ‘in’ operator for name:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;?name=in:name1,name2,name3
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;These filters will be added using syntax that conforms to the latest
guidelines from the OpenStack API Working Group and any applicable draft
guidelines &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;Example:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;GET /v2/images?name=in:name1,name2
{
    "first": "/v2/images?name=in:name1,name2",
    "images": [
        {
            "checksum": null,
            "container_format": "bare",
            "created_at": "2015-12-18T12:02:09Z",
            "disk_format": "raw",
            "file": "/v2/images/381b6dfb-48c2-4fcd-860d-9c7b10876730/file",
            "id": "381b6dfb-48c2-4fcd-860d-9c7b10876730",
            "min_disk": 0,
            "min_ram": 0,
            "name": "name1",
            "owner": "a03febe481094927a96fe367c15c347b",
            "protected": false,
            "schema": "/v2/schemas/image",
            "self": "/v2/images/381b6dfb-48c2-4fcd-860d-9c7b10876730",
            "size": null,
            "status": "queued",
            "tags": [],
            "updated_at": "2015-12-18T12:02:09Z",
            "virtual_size": null,
            "visibility": "private"
        },
        {
            "checksum": null,
            "container_format": "bare",
            "created_at": "2015-12-18T12:02:15Z",
            "disk_format": "raw",
            "file": "/v2/images/a3b9db48-5b6f-40e5-9cc1-d586f01281cc/file",
            "id": "a3b9db48-5b6f-40e5-9cc1-d586f01281cc",
            "min_disk": 0,
            "min_ram": 0,
            "name": "name2",
            "owner": "a03febe481094927a96fe367c15c347b",
            "protected": false,
            "schema": "/v2/schemas/image",
            "self": "/v2/images/a3b9db48-5b6f-40e5-9cc1-d586f01281cc",
            "size": null,
            "status": "queued",
            "tags": [],
            "updated_at": "2015-12-18T12:02:15Z",
            "virtual_size": null,
            "visibility": "private"
        }
    ],
    "schema": "/v2/schemas/images"
}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Max page size will still be enforced. For example if the max page size is 3
and I do request ‘id=in:1,2,3,4’ - I only get 3 images and a link to get
the fourth.&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 tests were conducted.
We determined the time spent in obtaining the list of images, filtering and
repeating the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;image-get&lt;/span&gt;&lt;/code&gt; query. The results are presented in &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;:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Blue line - used repeating the request.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Red line - used a filter.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Test code is presented in &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;/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;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;dshakhray&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="reviewers"&gt;
&lt;h3&gt;Reviewers&lt;/h3&gt;
&lt;p&gt;mfedosin
jokke&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;Unit and functional tests will be added as appropriate.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Docs should be updated with a description of new API filters and usage, as
well as of the additional policy options.&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="http://specs.openstack.org/openstack/api-wg/guidelines/pagination_filter_sort.html"&gt;API Working Group filtering guidelines&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="http://pixs.ru/showimage/yotxru1png_2430090_19659184.png"&gt;Result of perfomance test&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="http://paste.openstack.org/show/480210/"&gt;Script for performance tests&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;/aside&gt;
&lt;/section&gt;
</description><pubDate>Tue, 01 Mar 2016 00:00:00 </pubDate></item><item><title>Glance db purge utility</title><link>http://specs.openstack.org/openstack/glance-specs/specs/mitaka/implemented/database-purge.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/glance/+spec/database-purge"&gt;https://blueprints.launchpad.net/glance/+spec/database-purge&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This spec adds the ability to sanely and safely purge deleted rows from
the glance database for all relevant tables. Presently, we keep all deleted
rows. I believe this is unmaintainable as we move towards more upgradable
releases. Today, most operators depend on manual DB queries to delete this
data, but this exposes the DB to human errors.&lt;/p&gt;
&lt;p&gt;The goal is to have this be an extension to the &lt;cite&gt;glance-manage db&lt;/cite&gt; command.
Similar specs are being submitted to all the various projects that touch
a database.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Very long lived OpenStack installations will carry around database rows
for years and years. This brings following problems:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;If deleted data is kept in the DB, the number of rows can grow very large
taking up the disk space of nodes. Larger disk space means more worry
for disaster recovery, long running non-differential backups, etc.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Large number of deleted rows also means, an admin or authorized owner
querying for the corresponding rows will get 5xx responses timing out
on the DB, eventually slowing down other queries and API performance.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;DB upgradeability is a big challenge if the older data style are less
or inconsistent with the latest formats. An example would be the image
locations string where older location string styles are different
from the latest.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To date, there is no “mechanism” to programmatically
purge the deleted data. The archive rows feature doesn’t solve this.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;The proposal is to add a “purge” method to DbCommands in
glance/glance/cmd/manage.py. This will take a maximum count of rows to delete
and number of days argument and use that for a data_sub match.
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;DELETE&lt;/span&gt; &lt;span class="n"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;images&lt;/span&gt;
  &lt;span class="n"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;deleted&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;AND&lt;/span&gt; &lt;span class="n"&gt;deleted_at&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;data_sub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;NOW&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;LIMIT&lt;/span&gt; &lt;span class="n"&gt;count&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;Today, this can be accomplished manually with SQL commands, or via script.
There is also the archive_deleted_rows method. However, this won’t satisfy
certain data destruction policies that may exist at some companies.&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, all tables presently include a “deleted_at” 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;None, this would be run from glance-manage&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None, This only touches already deleted rows.&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 affects the operator’s ability to identify and delete all those rows from
the DB that have location stored for backend data entities, that are not
deleted (or partially deleted) due to some error at the time of the DELETE api
call or during scrubber’s data purge run.&lt;/p&gt;
&lt;p&gt;This has another operator/user impact for the calls that require changes-since
filter. It is required by the Nova proxy API and exists in v1 (and potentially
in v2). Purging the deleted data results into information evaporation that
the changes-since filter use case is designed for. One example, if it is needed
to check an old snapshot that has been deleted but has some vital info
for cross checking. Some operators give/want to give that functionality
to users. Purging breaks that contract and operators need to be aware about it.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;This has the potential to improve performance for very large databases.
Very long-lived installations can suffer from inefficient operations on
large tables.&lt;/p&gt;
&lt;p&gt;Another performance impact is on the negative side unless the operators
are being careful about the count. A long running purging operation will
potentially cause delay in the upgrade process. It is also likely to result
into a different differential backup of the DB and that may delay the process.&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 developers who want to optimize calls like re-adding a deleted
image-member to image while re-sharing that image, will have to consider
the rows can be deleted from now on.&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;p&gt;Primary assignee:
* mmagr&lt;/p&gt;
&lt;/section&gt;
&lt;section id="reviewers"&gt;
&lt;h3&gt;Reviewers&lt;/h3&gt;
&lt;p&gt;Core reviewer(s):
* flaper87
* nikhil-komawar&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Other reviewer(s):&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;Add purge functionality to manage.py db/api.py db/sqlalchemy/api.py
Add tests to confirm functionality
Add documentation of feature&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;The test will be written as such. Three rows will be inserted into a test db.
Two will be “deleted=1”, one will be “deleted=0”
One of the deleted rows will have “deleted_at” be NOW(), the other will be
“deleted_at” a few days ago, lets say 10. The test will call the new
function with the argument of “7”, to verify that only the row that was
deleted at 10 days ago will be purged. The two other rows should remain.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;The documentation needs to emphasize that the image_locations table will be
trimmed, which will destroy all information about where the image was
stored in various backends. The operator should keep this in mind when
selecting the number-of-days value for the purge function.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;This was discussed on both the openstack-operators mailing list and the
openstack-developers mailing lists with positive feedback from the group.&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="http://lists.openstack.org/pipermail/openstack-dev/2014-October/049616.html"&gt;http://lists.openstack.org/pipermail/openstack-dev/2014-October/049616.html&lt;/a&gt;&lt;/p&gt;
&lt;/section&gt;
</description><pubDate>Thu, 25 Feb 2016 00:00:00 </pubDate></item><item><title>Deprecate Glance v3 API</title><link>http://specs.openstack.org/openstack/glance-specs/specs/mitaka/implemented/deprecate-v3-api.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/glance/+spec/move-v3-to-glare"&gt;https://blueprints.launchpad.net/glance/+spec/move-v3-to-glare&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;On Mitaka summit it was decided [1] to make v3 (artifact) API a standalone
service with its own endpoint. To do that we have to deprecate Glance v3 API
and related things, and create new service with all required utilities.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Initially it was planned to make artifacts a new API with incremented version,
i.e. “v3”. But since Glance is a core project, it falls under the DefCore
specifications, which require (among other things) uniqueness of public APIs.
Unfortunately v3 api is pluggable and it can’t be unique by design.&lt;/p&gt;
&lt;p&gt;Also there are issues with understanding what Glance API is, because v1 and v2
are Image APIs, and they work with images only. But v3 was considered to be
unified (Artifact) API, which may work with objects of any nature.
The general feeling in the broader OpenStack community is that rather than
being a new version of the Images API, the Artifacts API should be considered
an entirely different thing.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Because v3 API has experimental status, it’s proposed to deprecate v3 API and move
all its code to the whole new standalone service with new endpoint. It will
release the Artifacts project from being subject to DefCore requirements and
will allow the project to move forward faster.&lt;/p&gt;
&lt;p&gt;Having the independent service also removes misunderstanding, because there will be
stable, DefCore-approved Glance Image API and pluggable independent Artifact API,
which may include Glance API in the future.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;It’s possible to leave everything as-is, but it doesn’t remove all of the above
issues.&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. All created for artifacts tables with prefix ‘artifacts-’ will stay in DB, but
will be used by another service.&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 of experimental APIs, that start with ‘/v3’, are deprecated and will be removed.&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;Experimental ‘feature/artifacts’ branch will be removed from ‘python-glanceclient’
repo.&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;‘apiv3app’ application has to be removed from ‘glance-api-paste.ini’&lt;/p&gt;
&lt;p&gt;‘enable_v3_api’ parameter has to be removed from glance-api config&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;p&gt;Primary assignee:&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;dshakray&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;Other contributors:&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;mfedosin&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;/section&gt;
&lt;section id="reviewers"&gt;
&lt;h3&gt;Reviewers&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;flaper87&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;nikhil-komawar&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;ativelkov&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;glance-api-paste.ini: remove ‘apiv3app’ application;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;glance/common/config.py: remove ‘enable_v3_api’ parameter;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;glance/api/middleware/version_negotiation.py: remove major version discoverability,
if version is 3, raise ValueError instead;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;move glance/api/v3/* code into glance/artifacts/api;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;make related changes in the 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;None.&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;[1] Mitaka glance artifacts review: &lt;a class="reference external" href="https://etherpad.openstack.org/p/mitaka-glance-artifacts-review"&gt;https://etherpad.openstack.org/p/mitaka-glance-artifacts-review&lt;/a&gt;&lt;/p&gt;
&lt;/section&gt;
</description><pubDate>Thu, 25 Feb 2016 00:00:00 </pubDate></item><item><title>Implement trusts for Glance</title><link>http://specs.openstack.org/openstack/glance-specs/specs/mitaka/implemented/glance-trusts.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/glance/+spec/trust-authentication"&gt;https://blueprints.launchpad.net/glance/+spec/trust-authentication&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This change proposal introduces a way for Glance to use Keystone trust
authorization.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Keystone tokens have some restricted lifetime. After the user token has
expired, any request initiated by Glance which needs a valid user token will
fail. This causes the original user’s request to also fail, even though the
token was originally valid when passed to Glance.&lt;/p&gt;
&lt;p&gt;This this spec intends to address the specific case where a token expires
during image upload causing the call to the registry to set the image
state ‘active’ to fail:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;User requests image-upload.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Keystone Middleware accepts the request and passes the request to Glance.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Glance passes all required data to glance_store.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;glance_store uploads an image but it takes a lot of time (more than token expiration time)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Glance sends a request to registry to change image status.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Keystone Middleware rejects the request because user token has expired.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;As a result the image never transitions to ‘active’ status and so isn’t usable.&lt;/p&gt;
&lt;p&gt;Increasing the token expiration time doesn’t seem to be a good long-term solution.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This implementation of trusts in glance_store is out of scope for this
specification. The current spec is related to Glance and it defines trusts
implementation for communication with Glance Registry.&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 snapshots also suffer from a token expiration issue. Nova first creates
a queued image before saving the instance state to local disk. Then the
image bytes are uploaded. Potentially the token can expire while the instance
state is being saved to disk. This spec will not address this case.&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;The proposal changes the Glance behavior when uploading images in Glance v2 api with enabled
Registry server, i.e. when data_api = glance.db.registry.api.&lt;/p&gt;
&lt;p&gt;Step 1. Glance received request for image-upload.&lt;/p&gt;
&lt;p&gt;Step 2. Before upload begins Glance tries to create a trust with the following parameters:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;token: user token&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;project: user project&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;roles: all user roles&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;trustee_user: system user that specified in CONF.keystone_authtoken configuration group&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;trustor_user: user who initiated the request.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Glance keeps trust_id until request processing is finished. If trust cannot be
created because of some reason then Glance uses user token for further steps.&lt;/p&gt;
&lt;p&gt;Step 3. Glance initiates and completes the image upload (this part is executed
by glance_store).&lt;/p&gt;
&lt;p&gt;Before starting step 4 Glance has an image uploaded to store and it needs
to update the image record in database. That requires the user token to be valid for V2
API if data_api is Glance Registry.&lt;/p&gt;
&lt;p&gt;Step 4. If authentication is required (see the text above) then Glance requests
the new token using the trust_id (see Step 2). Glance updates the request
context with the new token.&lt;/p&gt;
&lt;p&gt;Step 5. Glance updates image record in database. If Registry is used then
it receives the new token.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;At least one workaround for the whole functionality is available: extend token
expiration time to allow Glance upload the image. This solution affects all
services and it does not look like long term solution.&lt;/p&gt;
&lt;p&gt;There has been some discussion around updating how the keystone middleware
interprets a combination of a valid service token and expired user token – but
this is in the discussion/pre-design stage and is not guaranteed to be
implemented. Therefore we cannot currently base our solution on it, and it’s
recommended to use trusts. In the future this may be superseded by the use
of service tokens but it’ll have to be discussed when that time comes.&lt;/p&gt;
&lt;p&gt;Earlier there was a config option, called ‘use_user_token’. If it’s disabled glance
extracted user token from the context and changed it to admin’s. Unfortunately,
this option was considered as harmful and not acceptable for real deployments,
because it allowed to perform any operation in registry with admin rights. That’s
why this behaviour was deprecated in Mitaka.&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;Keystone V3 should be supported to properly use trusts 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;To deploy Glance with trusts the following config should be defined:
* trustee user grants should be specified in CONF.keystone_authtoken group:
username, password, auth_uri, ssl options.&lt;/p&gt;
&lt;p&gt;In devstack all parameters are defined by default.&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;mfedosin&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;kkushaev&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="reviewers"&gt;
&lt;h3&gt;Reviewers&lt;/h3&gt;
&lt;p&gt;flaper87
stuart-mclaren&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 trust authorization module to Glance.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Implement trust authorization between Glance and Glance registry for V2 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;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;To use trusts Glance needs to support Keystone V3. If V3 is not supported, Glance
will use old user token to finish upload operation.&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 unit test and functional tests should be implemented.&lt;/p&gt;
&lt;p&gt;Manual testing on devstack:&lt;/p&gt;
&lt;ol class="arabic simple" start="0"&gt;
&lt;li&gt;&lt;p&gt;Preparation: Use ‘file’ as ‘default_store’ for glance-api, set ‘expiration’
option in keystone.conf to ‘40’ (seconds), set ‘token_cache_time’
in glance-registry.conf to ‘-1’ to disable it, set ‘data_api’ in
glance-api.conf to ‘registry’.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Try to upload big image with v2 API (when upload takes at least 1 minute).
Make sure that upload fails with Unauthorized error.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Apply trusts patches.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Try to upload image again. Make sure that upload was finished successfully.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&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://wiki.openstack.org/wiki/Keystone/Trusts"&gt;Trusts wiki&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/keystone-specs/blob/master/specs/keystonemiddleware/implemented/service-tokens.rst"&gt;Service tokens&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
</description><pubDate>Wed, 27 Jan 2016 00:00:00 </pubDate></item><item><title>Mitaka Project Priorities</title><link>http://specs.openstack.org/openstack/glance-specs/priorities/mitaka-priorities.html</link><description>
&lt;span id="mitaka-priorities"/&gt;
&lt;p&gt;List of priorities (in the form of use cases) the glance development team is
prioritizing in Liberty (in no particular order).&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;Priority&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Owner(s)&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Specs&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;a class="reference internal" href="#defcore-updates"&gt;DefCore Updates&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;a class="reference external" href="https://launchpad.net/~flaper87"&gt;Flavio Percoco&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td/&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;&lt;a class="reference internal" href="#image-import-refactor"&gt;Image Import Refactor&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;a class="reference external" href="https://launchpad.net/~rosmaita"&gt;Brian Rosmaita&lt;/a&gt;,
&lt;a class="reference external" href="https://launchpad.net/~stuart-mclaren"&gt;Stuart Mclaren&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;a class="reference external" href="https://review.openstack.org/#/c/232371/"&gt;image refactor&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;&lt;a class="reference internal" href="#nova-v1-v2-support"&gt;Nova V1 -&amp;gt; V2 Support&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;a class="reference external" href="https://launchpad.net/~flaper87"&gt;Flavio Percoco&lt;/a&gt;,
&lt;a class="reference external" href="https://launchpad.net/~mfedosin"&gt;Mike Fedosin&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;a class="reference external" href="https://review.openstack.org/#/c/229891/"&gt;nova.image refactor&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;section id="priorities-without-a-clear-plan"&gt;
&lt;h2&gt;Priorities without a clear plan&lt;/h2&gt;
&lt;p&gt;Here are some things we would like to be a priority, but we are currently
lacking either a clear plan or someone to lead that effort:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;dl class="simple"&gt;
&lt;dt&gt;Revisit tempests tests&lt;/dt&gt;&lt;dd&gt;&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Verify all the required tests for the API v2 exist&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Tempest’s tests are used as a reference by DefCore&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;These tests will prove the interoperability of the API&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Glance trusts&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Pull V3 out of glance-api’s process into its own process/endpoint&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="defcore-updates"&gt;
&lt;h2&gt;DefCore Updates&lt;/h2&gt;
&lt;p&gt;Establish a communication channel with DefCore so that constant syncs can be had. Interactions with the DefCore team are important, especially when it comes down to our API evolution. We must make sure this becomes a standard practice.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="image-import-refactor"&gt;
&lt;h2&gt;Image Import Refactor&lt;/h2&gt;
&lt;p&gt;Define and implement a consistent, reliable, user-friendly and public capable image import workflow.&lt;/p&gt;
&lt;p&gt;The work here is focused on evolving the existing workflows into something that could be standardized and used as a reference by other groups like DefCore.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="nova-v1-v2-support"&gt;
&lt;h2&gt;Nova V1 -&amp;gt; V2 Support&lt;/h2&gt;
&lt;p&gt;Start and complete the support for Glance’s v2 in Nova. This will be a joint effort between both communities and it’ll be split into several parts. Our tasks for this consist in contributing to Nova and helping them move forward.&lt;/p&gt;
&lt;/section&gt;
</description><pubDate>Fri, 02 Oct 2015 00:00:00 </pubDate></item><item><title>Basic conversion of Images</title><link>http://specs.openstack.org/openstack/glance-specs/specs/kilo/conversion-of-images.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/glance/+spec/basic-import-conversion"&gt;https://blueprints.launchpad.net/glance/+spec/basic-import-conversion&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Some store engines work better when working with specific image
formats. For example, in the case of ceph, having a raw image improves
performance and allows ceph to do smarter things with the image
data. Therefore, this spec proposes adding a basic support to image
conversion that will give operators full control on the destination
format. The proposed change is the starting point for more complex
conversion operations.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;With the support of asynchronous operations and the new import
workflow in Glance (see the dependency tree), it will be possible to
have an image format conversion on the fly while importing an image.&lt;/p&gt;
&lt;p&gt;The conversion will be provided by a plugin of the import
workflow. This plugin can be activated or not based on the deployer
configuration. This means that the deployer will need to specify the
preferred format of images for the deployment.&lt;/p&gt;
&lt;p&gt;This blueprint will handle the conversion of formats supported by
qemu-img convert: raw, qcow2, vdi, vmdk and vpc.&lt;/p&gt;
&lt;p&gt;Internally, Glance will receive the bits of the image in a XX
format. These bits will be stored in a temporary location. The plugin
will be triggered to convert the image to its target format YY and
moved to its final destination. When the task is finished, the
temporary location is deleted.  This means that the format uploaded
initially is not kept by Glance.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Using &lt;a class="reference external" href="https://blueprints.launchpad.net/glance/+spec/async-glance-workers"&gt;Glance’s Asynchronous Workers&lt;/a&gt;, we can execute a background
task that converts images from the source format to a pre-configured
format.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Let the user convert images themselves and upload the final, converted, file.&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;Based on the maximum number of workers and the size that the administrator has
configured for the conversion workspace, performance could be negatively
affected if the operator misconfigures their maximum number of workers and
allocated workspace.&lt;/p&gt;
&lt;p&gt;In addition to the above, it’s also important to consider the time
required to download the image locally, convert it and then upload it
to the final store. The implementation proposes using &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;qemu-image&lt;/span&gt;&lt;/code&gt;,
which executes random accesses to the image data.&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;When configuring this feature, operators will need to know the average size of
the images that they are managing and appropriately configure the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;max_workers&lt;/span&gt;&lt;/code&gt; setting and an appropriate amount of space for the workers to
use.&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;flaper87&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="reviewers"&gt;
&lt;h3&gt;Reviewers&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Core reviewer(s):&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;jokke_
nikhil-komawar
kragniz
icordasc&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 specific workers for different conversion tasks&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create workflows for tasks&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update configuration files with additions&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update configuration 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;This depends on &lt;a class="reference external" href="https://blueprints.launchpad.net/glance/+spec/async-glance-workers"&gt;Glance’s Asynchronous Workers&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 testing will be needed for the conversion tasks and for the new task
flows.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;This may have an impact on the upgrade and installation parts of the
documentation. For operators upgrading, they’ll need to understand how to
properly configure a system for image conversion. For new users, they’ll
need to be warned about appropriately allocating space for the workers to use
and possibly choosing a more conservative maximum worker number than is
default until they can determine the appropriate number.&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, 11 Mar 2015 00:00:00 </pubDate></item><item><title>Introspection of Images</title><link>http://specs.openstack.org/openstack/glance-specs/specs/kilo/introspection-of-images.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/glance/+spec/introspection-of-images"&gt;https://blueprints.launchpad.net/glance/+spec/introspection-of-images&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Several image formats include metadata inside the image data. This spec
proposes that Glance expose that metadata through introspection of the image.
For example, we can read the metadata from a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;vmdk&lt;/span&gt;&lt;/code&gt; formatted image to know
that the disk type of the image is “streamOptimized”. Allowing Glance to
perform the introspection removes the burden from the administrator. Exposing
this metadata also helps the consumer of the image; Nova’s workflow is very
different based on the disk type of the image.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Several image formats include metadata inside the image data. A stream
optimized &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;vmdk&lt;/span&gt;&lt;/code&gt; image could be introspected like so:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;$ head -20 so-disk.vmdk

# Disk DescriptorFile
version=1
CID=d5a0bce5
parentCID=ffffffff
createType="streamOptimized"

# Extent description
RDONLY 209714 SPARSE "generated-stream.vmdk"

# The Disk Data Base
#DDB

ddb.adapterType = "buslogic"
ddb.geometry.cylinders = "102"
ddb.geometry.heads = "64"
ddb.geometry.sectors = "32"
ddb.virtualHWVersion = "4"
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;When a user of the image looks at the metadata they will see important
information like the required disk type, “streamOptimized”. Extracting the
metadata in Glance and exposing it through Glance’s API, means that
administrators and image users alike do not need to perform the introspection
themselves. Consumers like Nova will have very different workflows based on
disk type alone and could also optimize the rest of its workflow based on
other image metadata.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Using &lt;a class="reference external" href="https://blueprints.launchpad.net/glance/+spec/async-glance-workers"&gt;Glance’s Asynchronous Workers&lt;/a&gt;, we can extract the image metadata
without requiring a separate node and without suffering significant
performance degradation.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;A separate worker node could ostensibly be controlled to prevent degradation
on the Glance API nodes but is an unnecessary addition to the architecture.&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;Based on the maximum number of workers and the size that the administrator has
configured for the introspection workspace, performance could be negatively
affected if the operator misconfigures their maximum number of workers and
allocated workspace.&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;When configuring this feature, operators will need to know the average size of
the images that they are managing and appropriately configure the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;max_workers&lt;/span&gt;&lt;/code&gt; setting and an appropriate amount of space for the workers to
use.&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;flaper87&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;jokke_&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="reviewers"&gt;
&lt;h3&gt;Reviewers&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Core reviewer(s):&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;nikhil-komawar
kragniz
icordasc&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 specific workers for different introspection tasks&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create workflows for tasks&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update configuration files with additions&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update configuration 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;This depends on &lt;a class="reference external" href="https://blueprints.launchpad.net/glance/+spec/async-glance-workers"&gt;Glance’s Asynchronous Workers&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 testing will be needed for the introspection tasks and for the new task
flows.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;This may have an impact on the upgrade and installation parts of the
documentation. For operators upgrading, they’ll need to understand how to
properly configure a system for image introspection. For new users, they’ll
need to be warned about appropriately allocating space for the workers to use
and possibly choosing a more conservative maximum worker number than is
default until they can determine the appropriate number.&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, 10 Mar 2015 00:00:00 </pubDate></item><item><title>Support for multivalue operators in metadata catalog</title><link>http://specs.openstack.org/openstack/glance-specs/specs/kilo/metadata-multivalue-operators-support.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/glance/+spec/metadata-multivalue-operators-support"&gt;https://blueprints.launchpad.net/glance/+spec/metadata-multivalue-operators-support&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The metadata catalog provides data that user can pin to resources,
e.g., flavors extra specs. These are used by scheduler to choose a host that
satisfies the requirements provided in extra specs. Nova scheduler implements
operators to combine multiple values under one key in extra specs: &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;&amp;lt;or&amp;gt;&lt;/span&gt;&lt;/code&gt;
and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;&amp;lt;all-in&amp;gt;&lt;/span&gt;&lt;/code&gt;. Unfortunately, the catalog does not provide which operator
is suitable for a given property.&lt;/p&gt;
&lt;p&gt;This blueprint aims at this problem by extending current jsons with suitable
operators for each property.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;There is work being done in Horizon to provide support for multiple values
for a single key in extra specs, however, Glance currently does not provide
information about which operators are suitable for a given property.
In &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;compute-host-capabilities.json&lt;/span&gt;&lt;/code&gt; there is a property called
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cpu_info:features&lt;/span&gt;&lt;/code&gt;. Both operators - &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;&amp;lt;all-in&amp;gt;&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;&amp;lt;or&amp;gt;&lt;/span&gt;&lt;/code&gt; can be used
for this property. There are also properties like &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cpu_info:model&lt;/span&gt;&lt;/code&gt;
where &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;&amp;lt;or&amp;gt;&lt;/span&gt;&lt;/code&gt; is the only operator that should work.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;To make end-user (e.g. Horizon) aware which operator can be used for a given
property, this blueprint extends existing properties (and also properties
inside objects) with a new section under key - “operators”:&lt;/p&gt;
&lt;p&gt;Currently an example property would be structured 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;"cpu_info:features"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"Features"&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;"Specifies CPU flags/features."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"array"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"items"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s2"&gt;"enum"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="s2"&gt;"aes"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"vme"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"de"&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;And after extension:&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;"cpu_info:features"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"Features"&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;"Specifies CPU flags/features."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"operators"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="s2"&gt;"&amp;lt;or&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s2"&gt;"&amp;lt;all-in&amp;gt;"&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"array"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"items"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s2"&gt;"enum"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="s2"&gt;"aes"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"vme"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"de"&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;The added section 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;"operators"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="s2"&gt;"&amp;lt;or&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"&amp;lt;all-in&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;This section will be optional, e.g., property that is integer does
not need operator.&lt;/p&gt;
&lt;p&gt;Also glance will not do any check on “operators” field. API consumer
needs to take care to provide valid operators for nova scheduler. Currently
there are three operators that are valid for nova scheduler and are usable
with metadata definitions: &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;&amp;lt;or&amp;gt;&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;&amp;lt;in&amp;gt;&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;&amp;lt;all-in&amp;gt;&lt;/span&gt;&lt;/code&gt;&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;This will not impact data model, because “operators” will be part
of the blob stored in the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;json_schema&lt;/span&gt;&lt;/code&gt; column in the database 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;Example extended GET object body:&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;"objects"&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;"object1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"namespace"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"my-namespace"&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;"my-description"&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;"prop1"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="s2"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"My Property"&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;"More info here"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="s2"&gt;"operators"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;all-in&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
                    &lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="s2"&gt;"readonly"&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="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;"first"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"/v2/metadefs/objects?limit=1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"next"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"/v2/metadefs/objects?marker=object1&amp;amp;limit=1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"schema"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"/v2/schema/metadefs/objects"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Example POST/PUT body on objects:&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;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"StorageQOS"&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;"Our available storage QOS."&lt;/span&gt;&lt;span class="p"&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="s2"&gt;"MyProperty"&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;"MyProperty"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"readonly"&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;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"The My Property"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s2"&gt;"operators"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;or&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="s2"&gt;"enum"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"type1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"type2"&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;Because “operators” field is optional API consumer needs to handle default
value as it may be missing.&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;Upgrade of jsons or database in existing OpenStack installation will not
be needed. “operators” section will not be mandatory so the installation
can keep running without upgrade.&lt;/p&gt;
&lt;p&gt;Also there is possibility that property/object will be missing operators even
when the value has been added in the latest built-in metadata definition json
templates, the upgrade process does not update existing database. Deployer
needs to manually upgrade metadata definitions to the newest set.&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;pawel-koniszewski&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="reviewers"&gt;
&lt;h3&gt;Reviewers&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Core reviewer(s):&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;lzy-dev&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 existing metadata jsons with operators section.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Extend API json schema with new option&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;Horizon blueprint that depends on this blueprint:
&lt;a class="reference external" href="https://blueprints.launchpad.net/horizon/+spec/metadata-widget-multivalue-selection"&gt;https://blueprints.launchpad.net/horizon/+spec/metadata-widget-multivalue-selection&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Nova blueprint that this blueprint depends on:
&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/add-all-in-list-operator-to-extra-spec-ops"&gt;https://blueprints.launchpad.net/nova/+spec/add-all-in-list-operator-to-extra-spec-ops&lt;/a&gt;&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Current unit tests and functional tests will be extended to make sure
that the new section is returned and that it is correct. Tests will also
ensure that the operators part is optional.&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 attribute needs to be documented.&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, 26 Feb 2015 00:00:00 </pubDate></item><item><title>Image API v2 listing</title><link>http://specs.openstack.org/openstack/glance-specs/specs/api/v2/lists-image-api-v2.html</link><description>

&lt;p&gt;&lt;strong&gt;Pagination&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;This call is designed to return a subset of the larger collection of
images while providing a link that can be used to retrieve the next. You
should always check for the presence of a ‘next’ link and use it as the
URI in a subsequent HTTP GET request. You should follow this pattern
until there a ‘next’ link is no longer provided. The next link will
preserve any query parameters you send in your initial request. The
‘first’ link can be used to jump back to the first page of the
collection.&lt;/p&gt;
&lt;p&gt;If you prefer to paginate through images manually, the API provides two
query parameters: ‘limit’ and ‘marker’. The limit parameter is used to
request a specific page size. Expect a response to a limited request to
return between zero and &lt;em&gt;limit&lt;/em&gt; items. The marker parameter is used to
indicate the id of the last-seen image. The typical pattern of limit and
marker is to make an initial limited request then to use the id of the
last image from the response as the marker parameter in a subsequent
limited request.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Filtering&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The list operation accepts several types of query parameters intended to
filter the results of the returned collection.&lt;/p&gt;
&lt;p&gt;A client can provide direct comparison filters using &lt;em&gt;most&lt;/em&gt; image
attributes (i.e. name=Ubuntu, visibility=public, etc). A client cannot
filter on tags or anything defined as a ‘link’ in the json-schema (i.e.
self, file, schema).&lt;/p&gt;
&lt;p&gt;The ‘size_min’ and ‘size_max’ query parameters can be used to do
greater-than and less-than filtering of images based on their ‘size’
attribute (‘size’ is measured in bytes and refers to the size of an
image when stored on disk). For example, sending a size_min filter of
1048576 and size_max of 4194304 would filter the container to include
only images that are between one and four megabytes in size.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Sorting&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The results of this operation can be ordered by using classic and new
sorting syntaxes. Classic syntax uses multiple ‘sort_key’ and
‘sort_dir’ parameters, and new one accepts a single ‘sort’ string with
comma separated sort keys with optional sort direction after ‘:’.
Both syntaxes provide an ability to sort output with multiple keys and
directions but with some differences.&lt;/p&gt;
&lt;p&gt;The classic syntax takes a list of keys and either exactly the same
number of directions for each key, or only one that specifies the
default value for all keys.
The new syntax applies a default direction to all keys where it’s
missing.&lt;/p&gt;
&lt;p&gt;The API uses the natural sorting of whatever image attribute is
provided as the sort key. List of image attributes can be used as the
sort key: ‘name’, ‘status’, ‘container_format’, ‘disk_format’,
‘size’, ‘id’, ‘created_at’, ‘updated_at’. The sort dir parameter
indicates in which direction to sort. Acceptable values are ‘asc’
(ascending) and ‘desc’ (descending). Default values for sort key and
sort direction are ‘created_at’ and ‘desc’.&lt;/p&gt;
&lt;p&gt;Examples of sorting:&lt;/p&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;&lt;p&gt;New syntax with specified direction for keys:&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;sort&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="n"&gt;asc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;asc&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Sort: by name with asc order, then by status with asc order.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;New syntax with missing direction:&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;sort&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="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;asc&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Sort: by name with desc order, then by status with asc order.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;New syntax without directions:&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;sort&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="n"&gt;status&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Sort: by name with desc order, then by status with desc order.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Classic syntax with specified default direction:&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;sort_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;sort_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;sort_dir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;asc&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Sort: by name with asc order, then by status with asc order.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Classic syntax with missing direction:&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;sort_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;sort_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Sort: by name with desc order, then by status with desc order.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Classic syntax with missing key and specified default direction:&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;sort_dir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;asc&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Sort: by created_at with asc order.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Classic syntax with specified direction for keys:&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;sort_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;sort_dir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;desc&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;sort_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;sort_dir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;asc&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Sort: by name with desc order, then by status with asc order.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Classic syntax with different number of keys and directions:&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;sort_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;sort_dir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;asc&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;sort_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;sort_dir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;asc&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;sort_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Will be an error.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
</description><pubDate>Fri, 13 Feb 2015 00:00:00 </pubDate></item><item><title>Glance sorting enhancements</title><link>http://specs.openstack.org/openstack/glance-specs/specs/kilo/sorting-enhancements.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/glance/+spec/glance-sorting-enhancements"&gt;https://blueprints.launchpad.net/glance/+spec/glance-sorting-enhancements&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Currently, the sorting support for Glance allows the caller to specify
multiple sort keys and one sort direction. This blueprint enhances the
sorting support for the /images and /images/detail APIs so that
multiple sort keys and sort directions can be supplied on the request.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;There is no support for retrieving image data based on multiple sort
directions; multiple sort keys and one direction are currently
supported, and they’re defaulted to descending sort order by the
“created_at” key.&lt;/p&gt;
&lt;p&gt;In order to retrieve data in any sort order and direction, the REST
APIs need to accept multiple sort keys and directions.&lt;/p&gt;
&lt;p&gt;Use Case: A UI that displays a table with only the page of data that it
has retrieved from the server. The items in this table need to be sorted
by status first and by display name second. In order to retrieve data in
this order, the APIs must accept multiple sort keys/directions.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;The /images and /images/detail APIs will align with the API working group
guidelines &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; for sorting and support the following parameter on the
request:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;sort: Comma-separated list of sort keys, each key is optionally appended
with &amp;lt;:dir&amp;gt;, where ‘dir’ is the direction for the corresponding sort key
(supported values are ‘asc’ for ascending and ‘desc’ for descending).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&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;/images?sort=status:asc,name:asc,created_at:desc
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Note: The “created_at” and “id” sort keys are always appended at the end of
the key list if they are not already specified in the request.&lt;/p&gt;
&lt;p&gt;The database layer already supports multiple sort keys and directions. This
blueprint will update the API layer to retrieve the sort information from
the API request and pass that information down to the database layer.&lt;/p&gt;
&lt;p&gt;All sorting is handled in the glance.db.sqlalchemy.api._paginate_query
function. This function accepts an ORM model class as an argument and the
only valid sort keys are attributes on the given model class. Therefore,
the valid sort keys are: ‘name’, ‘status’, ‘container_format’, ‘disk_format’,
‘size’, ‘id’, ‘created_at’, ‘updated_at’.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Multiple sort keys and directions could be passed using repeated ‘sort_key’
and ‘sort_dir’ query parameters. For example:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;/images?sort_key=status&amp;amp;sort_dir=asc&amp;amp;sort_key=name&amp;amp;sort_dir=asc&amp;amp;
sort_key=created_at&amp;amp;sort_dir=desc
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;To provide users with the ability to use the classic familiar syntax and to
ensure a smoother transition to the new one, classic syntax should be
implemented too.&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 following existing v2 GET APIs will support the new sorting parameters:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;/v2/images&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;/v2/images/detail&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Note that the design described in this blueprint could be applied to other GET
REST APIs, but this blueprint is scoped to only those listed above. Once this
design is finalized, then the same approach could be applied to other APIs.&lt;/p&gt;
&lt;p&gt;The existing API documentation needs to be updated to include the following
new Request Parameters:&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;Parameter&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Style&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;sort&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;query&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;Comma-separated list of sort keys and optional
sort directions in the form of key&amp;lt;:dir&amp;gt;,
where ‘dir’ is either ‘asc’ for ascending
order or ‘desc’ for descending order. Defaults
to the ‘created_at’ and ‘id’ keys in
descending order.&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Currently, the images query supports the ‘sort_key’ and ‘sort_dir’ parameters;
these will be deprecated. The API will raise a “BadRequest” error response
(code 400) if both the new ‘sort’ parameter and a deprecated ‘sort_key’ or
‘sort_dir’ parameter is specified.&lt;/p&gt;
&lt;p&gt;Neither the API response format nor the return codes will be modified, only
the order of the images that are returned.&lt;/p&gt;
&lt;p&gt;In the event that an invalid sort key or sort direction is specified, then a
“BadRequest” error response (code 400) will be returned with a message like
“Invalid input received: Invalid sort key” or “Invalid input received: Invalid
sort dir” respectively.&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-glanceclient should be updated to accept sort keys and
sort directions, using the ‘sort’ parameter being proposed in the
cross-project spec &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;.&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 choice of sort keys has no impact on data retrieval performance.
Therefore, the user should be allowed to retrieve data in whatever
order they need to for creating their views (see use case in the
Problem Description).&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;mfedosin&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="reviewers"&gt;
&lt;h3&gt;Reviewers&lt;/h3&gt;
&lt;p&gt;ativelkov&lt;/p&gt;
&lt;p&gt;icordasc&lt;/p&gt;
&lt;p&gt;nikhil-komawar&lt;/p&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;p&gt;Ideally the logic for processing the sort parameters would be common to all
components and would be done in oslo; a similar blueprint is also being
proposed in nova:
&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/nova-pagination"&gt;https://blueprints.launchpad.net/nova/+spec/nova-pagination&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Therefore, I see the following work items:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Update the existing API to retrieve the sort information and pass down to
the DB layer (&lt;a class="reference external" href="https://review.openstack.org/#/c/148326/"&gt;https://review.openstack.org/#/c/148326/&lt;/a&gt;);&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Extend API with new syntax to support multiple sorting keys and directions
(&lt;a class="reference external" href="https://review.openstack.org/#/c/148512/"&gt;https://review.openstack.org/#/c/148512/&lt;/a&gt;);&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update the python-glanceclient to accept and process multiple sort keys and
sort directions with classic and new sorting syntax
(&lt;a class="reference external" href="https://review.openstack.org/#/c/120777/"&gt;https://review.openstack.org/#/c/120777/&lt;/a&gt;,
&lt;a class="reference external" href="https://review.openstack.org/#/c/148688/"&gt;https://review.openstack.org/#/c/148688/&lt;/a&gt;,
&lt;a class="reference external" href="https://review.openstack.org/#/c/148981/"&gt;https://review.openstack.org/#/c/148981/&lt;/a&gt;);&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Implement the full test coverage for the new 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;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;CLI Sorting Argument Guidelines cross project spec &lt;a class="footnote-reference brackets" href="#id6" 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;;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Related (but independent) change being proposed in nova &lt;a class="footnote-reference brackets" href="#id7" 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;/ul&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Both unit and Tempest tests need to be created to ensure that the data is
retrieved in the specified sort order. Tests should also verify that the
default sort keys (“created_at” and “id”) are always appended to the user
supplied keys (if the user did not already specify them).&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;The /images and /images/detail API documentation will need to be updated
to:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;reflect the new sorting parameters and explain that these parameters will
affect the order in which the data is returned.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;explain how the default sort keys will always be added at the end of the
sort key list.&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="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;&lt;a class="reference external" href="https://github.com/openstack/api-wg/blob/master/guidelines/pagination_filter_sort.rst"&gt;API Working group sorting guidelines&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;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;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="http://specs.openstack.org/openstack/openstack-specs/specs/cli-sorting-args.html"&gt;CLI Sorting Argument Guidelines&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="#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://blueprints.launchpad.net/nova/+spec/nova-pagination"&gt;Related change being proposed in nova&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;/aside&gt;
&lt;/section&gt;
</description><pubDate>Fri, 13 Feb 2015 00:00:00 </pubDate></item><item><title>Notification Support for Metadata Definitions</title><link>http://specs.openstack.org/openstack/glance-specs/specs/kilo/metadefs-notifications.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/glance/+spec/metadefs-notifications"&gt;https://blueprints.launchpad.net/glance/+spec/metadefs-notifications&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This blueprint adds metadata definition notification support.&lt;/p&gt;
&lt;p&gt;The implemented juno spec for metadata notifications is here for reference:&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="http://specs.openstack.org/openstack/glance-specs/specs/juno/metadata-schema-catalog.html"&gt;http://specs.openstack.org/openstack/glance-specs/specs/juno/metadata-schema-catalog.html&lt;/a&gt;&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Metadata definition resources - namespaces, objects, properties,
tags, and resource types - don’t provide any notification events when
certain operations are performed on them. This doesn’t allow for any
intelligent caching of the data, meaning that the only opportunity for
catalog users to be aware of changes is to continually poll. Polling is not
performant for catalog users and puts extra load on the API and database.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;We are proposing to support notifications for events on the
Metadata Definitions Catalog.&lt;/p&gt;
&lt;p&gt;This implementation will include the following events that will be
triggered when necessary:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;metadef_namespace.create - namespace has been created&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;metadef_namespace.update - namespace has been updated&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;metadef_namespace.delete - namespace has been deleted&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;metadef_object.create - object has been created&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;metadef_object.update - object has been updated&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;metadef_object.delete - object has been deleted&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;metadef_property.create - property has been created&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;metadef_property.update - property has been updated&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;metadef_property.delete - property has been deleted&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;metadef_tag.create - tag has been created&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;metadef_tag.update - tag has been updated&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;metadef_tag.delete - tag has been deleted&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;metadef_resource_type.create - resource type has been added to namespace&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;metadef_resource_type.delete - resource type has been removed from namespace&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In addition we will add a new configuration option to allow for disabling
individual notifications.  It will be a comma separated list with the
following syntax:&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;disabled_notifications&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;type&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;.&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;action&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 example, the following would disable all tag notification and property
deletions:&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;disabled_notifications&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;metadef_tag&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;metadef_property&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;delete&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The notifier will read this configuration and ignore notifications that are
in the disabled list.&lt;/p&gt;
&lt;p&gt;The reason for this proposed addition is that we aren’t sure whether or not
tag notifications could get too chatty for some reason.  Therefore,
we’d like to give an option for deployers to disable it.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;No notification support could be added.  In this event,
constant polling for changes could be done.  The constant polling would lead
to both latency in getting updates and extra load on the API and database.&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 external API impacts will be visible.  The API itself will have a notifier
added as part of the call.&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;A notifier will be added to the REST API calls.  The notifications listed
above will be added. A new configuration option will be added to disable
specific 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;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;Additional notifications will be generated, but the amount of changes to
metadata definitions are not anticipated to be enough to impact performance.&lt;/p&gt;
&lt;p&gt;However we want to add the new disabled_notifications configuration option to
allow operators to disable the notifications if they determine that are too
chatty.&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 setup listeners to received notification on metadefs
if they desire them.&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;kamil-rykowski&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="reviewers"&gt;
&lt;h3&gt;Reviewers&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Core reviewer(s):&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;jokke&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other reviewer(s):&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;lakshmi-sampath
travis-tripp&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;Changes would be made to:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Glance v2 metadef APIs to add notifiers&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;notifer&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;gateway&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;Need to sync openstack/common from oslo-incubator for service module.&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://bugs.launchpad.net/glance/+bug/1413861"&gt;https://bugs.launchpad.net/glance/+bug/1413861&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 will be added for all possible code with a goal of being able to
isolate functionality as much as possible.&lt;/p&gt;
&lt;p&gt;Tempest tests will be added wherever possible.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Docs needed for new notification usage&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://docs.openstack.org/developer/glance/metadefs-concepts.html"&gt;Current glance metadata definition catalog documentation.&lt;/a&gt;&lt;/p&gt;
&lt;/section&gt;
</description><pubDate>Thu, 22 Jan 2015 00:00:00 </pubDate></item><item><title>Pass Targets to Glance’s Policy Enforcer</title><link>http://specs.openstack.org/openstack/glance-specs/specs/kilo/pass-targets-to-policy-enforcer.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/glance/+spec/pass-targets-to-policy-enforcer"&gt;https://blueprints.launchpad.net/glance/+spec/pass-targets-to-policy-enforcer&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Currently it’s possible to define custom rules in Glance’s &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;policy.json&lt;/span&gt;&lt;/code&gt;
that rely on attributes other than a user’s roles. Unfortunately, if you
attempt to apply one of those rules, it will always cause the user to be
prevented from performing the associated action. This specification proposes
that we pass the proper target objects to the enforcer so these rules can be
used and properly enforced.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Currently, Glance promises that permissions can be configured in the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;policy.json&lt;/span&gt;&lt;/code&gt; file but any rule other than a role check currently
results in 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; response. As this is a promised feature,
implementing this specification is merely fixing the already promised
behaviour.&lt;/p&gt;
&lt;p&gt;It is not possible to restrict access to actions in Glance’s &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;policy.json&lt;/span&gt;&lt;/code&gt;
based on anything other than a user’s roles. The policy enforcer that Glance
extends from oslo expects a dictionary-like object to be passed as a target of
the action. Every method that uses the policy enforcer and enforces the policy
defined for the corresponding action currently passes an empty dictionary
(&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;{}&lt;/span&gt;&lt;/code&gt;) which provides absolutely no data about the actual target.&lt;/p&gt;
&lt;p&gt;If we define a rule similar to 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="s2"&gt;"tenant_is_owner"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"tenant&lt;/span&gt;&lt;span class="si"&gt;%(owner)s&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;And we apply it to an action, 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="s2"&gt;"delete_image"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"rule:tenant_is_owner"&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Then every request to delete any image will be denied with a 403
(Unauthorized) response from Glance’s API. The reason stems from how the rule
is parsed and the target is passed in. The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;"rule:tenant_is_owner"&lt;/span&gt;&lt;/code&gt; rule
will be parsed as a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GenericCheck&lt;/span&gt;&lt;/code&gt;. These checks are split on the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;:&lt;/span&gt;&lt;/code&gt; into
a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;kind&lt;/span&gt;&lt;/code&gt; and a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;match&lt;/span&gt;&lt;/code&gt; (roughly, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;"&amp;lt;kind&amp;gt;:&amp;lt;match&amp;gt;"&lt;/span&gt;&lt;/code&gt;). The match portion
is then interpolated with the target, i.e.,&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;match&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;match&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;So using our example above, we would do&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;match&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;%(owner)s&lt;/span&gt;&lt;span class="s2"&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;Except that this raises a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;KeyError&lt;/span&gt;&lt;/code&gt; which means the check immediately
returns &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;False&lt;/span&gt;&lt;/code&gt; and fails. In this particular instance (deleting an image),
if we passed an instance of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance.api.policy.ImageTarget&lt;/span&gt;&lt;/code&gt;, then what would
instead happen is that the interpolation would succeed.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;The solution for image-based resources is simple. We have the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;image&lt;/span&gt;&lt;/code&gt; on the
policy proxies that relate to images. We simply pass that to
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance.api.policy.ImageTarget&lt;/span&gt;&lt;/code&gt; and pass the resulting instance to the
policy enforcer so it can be accessed like a dictionary when interpolated.
For members and tasks, there is no target class that we can use. These are
very thin classes that could easily be written.&lt;/p&gt;
&lt;p&gt;Once we have the appropriately defined target classes, we would then update
the places where the policy is enforced to use instances of those target
classes.&lt;/p&gt;
&lt;p&gt;With proper targets in place, we can also implement safer default policy rules
for operators who rely solely on the default &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;policy.json&lt;/span&gt;&lt;/code&gt; file.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Custom rule creation based on attributes of the target object could be
disabled. This would severely limit an operator’s ability to restrict actions
based on a user’s tenant and other properties of the target of the action.&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 will give operators a significant amount of control over the security of
their Glance installations. Currently they can only restrict actions based on
roles which may be sufficient in some cases. If the operator, however, wishes
to restrict access based on other factors (besides role) they cannot do this.
If they try to do it, there is no indication that it will not work but they
can essentially produce a Denial of Service to users who should be able to
perform actions based on the policy defined.&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;To leverage the fixes in this specification, operators need to update their
versions of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;policy.json&lt;/span&gt;&lt;/code&gt; used in their deployments. To write a rule,
operators need to know that there are three values provided by glance that can
be used in a rule on the left side of the colon (&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;:&lt;/span&gt;&lt;/code&gt;). Those values are the
current user’s credentials in the form of:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;role&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;tenant&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;owner&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The left side of the colon can also contain any value that Python can
understand, e.g.,:&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;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;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;"a&lt;/span&gt; &lt;span class="pre"&gt;string"&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&amp;amp;c.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Role checks are going to continue to work exactly as they already do. If the
role defined in the check is one that the user holds, then that will pass,
e.g., &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;role:admin&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Using &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tenant&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;owner&lt;/span&gt;&lt;/code&gt; will only work with Images or actions that
interact with an image. Consider the following rule:&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;tenant&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;owner&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;This will use the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tenant&lt;/span&gt;&lt;/code&gt; value of the currently authenticated user. It
will also use &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;owner&lt;/span&gt;&lt;/code&gt; from the image it is acting upon. If those two
values are equivalent the check will pass. All attributes on an image (as well
as extra image properties) are available for use on the right side of the
colon. The most useful are the following:&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;owner&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;protected&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;is_public&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;An operator, therefore, could construct a set of rules 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="p"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;"not_protected"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"False:&lt;/span&gt;&lt;span class="si"&gt;%(protected)s&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"is_owner"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"tenant:&lt;/span&gt;&lt;span class="si"&gt;%(owner)s&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"not_protected_and_is_owner"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"rule:not_protected and rule:is_owner"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"delete_image"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"rule:not_protected_and_is_owner"&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&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;icordasc&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="reviewers"&gt;
&lt;h3&gt;Reviewers&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Core reviewer(s):&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;nikhil-komawar
jokke&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other reviewer(s):&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;kragniz&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 appropriate target classes&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use target classes to proxy targets to the policy enforcer&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add tests demonstrating that generic checks now work&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add better documentation surrounding policy rules to the existing
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;Functional tests will be added where specific &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;policy.json&lt;/span&gt;&lt;/code&gt; files are loaded
to test access control of different targets.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;There is no direct impact, but the existing &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;policy.json&lt;/span&gt;&lt;/code&gt; documentation is
thin and only describes what each rule controls. It does not describe the
available target information or how to write rules.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;Related bugs:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://bugs.launchpad.net/glance/+bug/1253963"&gt;https://bugs.launchpad.net/glance/+bug/1253963&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/glance/+bug/1346648"&gt;https://bugs.launchpad.net/glance/+bug/1346648&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Initial work at an implementation:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://review.openstack.org/#/c/146651/"&gt;https://review.openstack.org/#/c/146651/&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Glance meeting discussion on 2015 January 15:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="http://eavesdrop.openstack.org/meetings/glance/2015/glance.2015-01-15-14.02.log.html"&gt;http://eavesdrop.openstack.org/meetings/glance/2015/glance.2015-01-15-14.02.log.html&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
</description><pubDate>Wed, 21 Jan 2015 00:00:00 </pubDate></item><item><title>Glance VMware store to support multiple datastores</title><link>http://specs.openstack.org/openstack/glance-specs/specs/kilo/vmware-store-multiple-datastores.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/glance/+spec/vmware-store-multiple-datastores"&gt;https://blueprints.launchpad.net/glance/+spec/vmware-store-multiple-datastores&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Glance, when configured to use VMware store, stores the images in a virtual
storage container called datastore, identified by the configuration option
vmware_datastore_name. The size of the datastore can only be increased to a
certain limit which also depends upon the underlying physical storage.&lt;/p&gt;
&lt;p&gt;The capacity of the store is thus bound by the size of a single datastore and
poses serious scalability issues.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Currently the number of images stored by glance, when configured to use VMware
store, is limited by the capacity of a single datastore. The size of a
datastore has an upper bound [1].&lt;/p&gt;
&lt;p&gt;e.g The maximum datastore size is 64TB when backed by VMFS-5 filesystem. While
the same for a datastore with NFS may depend on the storage array vendor. While
this is the theoretical maximum based on the supported filesystem, datastores
are also sized based on the underlying physical storage, including internal and
external devices and networked storage. With networked storage the choice of
storage protocol (iSCSI, FC, FCoE) also play a vital role in deciding the
optimal size. Thus, the capacity of a datastore used in a datacenter varies by
deployment.&lt;/p&gt;
&lt;p&gt;Apart from the capacity, there may be a performance bottleneck when many
compute nodes concurrently access a single datastore to download images.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;To allow adding more capacity and improving performance, we suggest the use of
multiple datastores for storing images.&lt;/p&gt;
&lt;p&gt;There is only one major aspect of the proposed change:
- Datastore Selection.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1) Datastore Selection:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;This change proposes to select a datastore based on the priority given to it by
the operator and the capacity to accommodate the image. A new configuration
option (say vmware_datastores) will be added that would enable the operator to
specify multiple datastores along with their relative weights. In case of equal
priority the selection will be based on the maximum freespace available on the
datastore. This approach is very similar to filesystem_store_datadirs used by
filesystem store.&lt;/p&gt;
&lt;p&gt;Example: say vmware_datastores is configured with nfs_datastore,
iscsi_datastore, ssd_datastore with weights 100, 100 and 200 respectively.
Here, ssd_datastore will be the preferred datastore if it
can accommodate the image data being added. Otherwise, nfs_datastore or
iscsi_datastore will be chosen based on maximum freespace available.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;1) The datastore selection can be done through round-robin/randomized strategy
instead of priority-based. This would be ideal if all datastores are of same
type and perform similarly. But since datastores are of different types, the
strategy is best driven by operator input. e.g SSD backed datastores may be
faster that networked datastores. While its possible to determine
the type of datastore, implicit assumptions cannot be made.&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;Does not have any impact on glance data model.&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 spec only adds a selection logic to the existing functionality and hence
does not have any security impact.&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 use of multiple datastores will reduce concurrent operations on a single
datastore.&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 proposal will allow administrators to configure multiple datastores to
save the image data in VMware storage backend. If enabled, it will override
the existing configuration option &lt;em&gt;vmware_datastore_name&lt;/em&gt; that allows to
specify a single datastore. If disabled, the store will fallback to
vmware_datastore_name option. Thus, the change is backwards compatible. We
will deprecate the vmware_datastore_name option going forward.&lt;/p&gt;
&lt;p&gt;New Multi Strings configuration option in &lt;em&gt;glance-api.conf&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;vmware_datastores&lt;/strong&gt;
Optional. Default: Not set.&lt;/p&gt;
&lt;p&gt;A datastore along with its datacenter path and a weight. If the
datastore is a member of a datastore cluster, then the name of the cluster
should also be included. Otherwise, the cluster name can be omitted. This
option can be specified multiple times to specify multiple datastores.
Thus, the required format becomes:&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;vmware_datastores =&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;&amp;lt;datacenter_path&amp;gt;:&amp;lt;datastore1&amp;gt;:&amp;lt;weight&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;vmware_datastores =&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;&amp;lt;datacenter_path&amp;gt;:&amp;lt;datastore_cluster_name&amp;gt;:&amp;lt;datastore2&amp;gt;:&amp;lt;weight&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;The weights are used to establish the relative priorities of the specified
datastores. Thus, they can be any arbitrary integer values.&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Examples:&lt;/dt&gt;&lt;dd&gt;&lt;dl class="simple"&gt;
&lt;dt&gt;vmware_datastores =&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;datacenter1:nfs_datastore:2&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;vmware_datastores =&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;datacenter1:ssd_datastore:3&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;vmware_datastores =&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;datacenter1:backup_datastore:1&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;In the above example, ssd_datastore will be given highest priority, followed
by nfs_datastore and backup_datastore.&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;dl class="simple"&gt;
&lt;dt&gt;vmware_datastores =&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;datacenter1:nfs1_datastore:100&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;vmware_datastores =&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;datacenter1:nfs2_datastore:100&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;vmware_datastores =&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;datacenter1:backup_datastore:50&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;In this example, the nfs datastores will be given equal priority, followed by
the backup_datastore. With equal priority, the contention between nfs
datastores is resolved by the maximum freespace.&lt;/p&gt;
&lt;p&gt;Note:- If the datacenter path or datastore name contains a colon (:) symbol,
it must be escaped with a backslash.&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;smurugesan (sabari)&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="reviewers"&gt;
&lt;h3&gt;Reviewers&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Core reviewer(s):&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;nikhil-komawar
arnaudleg&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other reviewer(s):&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;rgerganov&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;Implement new config option in VMware store driver.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Implement datastore selection logic in the VMware store driver.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Implement unit tests.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Change glance-api sample conf in glance repository.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add a deprecation warning for vmware_datastore_name.&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;oslo.vmware has introduced a Datastore object which will be used in this
implementation.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;oslo.vmware has a vim_util module that has some low-level utility methods
to interact with the vmware api’s. This is required to parse api responses.&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;Tempest tests are not 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;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Document new configuration options.&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;[1] &lt;a class="reference external" href="http://www.vmware.com/pdf/vsphere5/r55/vsphere-55-configuration-maximums.pdf"&gt;http://www.vmware.com/pdf/vsphere5/r55/vsphere-55-configuration-maximums.pdf&lt;/a&gt;&lt;/p&gt;
&lt;/section&gt;
</description><pubDate>Mon, 12 Jan 2015 00:00:00 </pubDate></item><item><title>Create and Use &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance-manage&lt;/span&gt;&lt;/code&gt; config file</title><link>http://specs.openstack.org/openstack/glance-specs/specs/kilo/create-glance-manage-conf.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/glance/+spec/create-glance-manage-conf"&gt;https://blueprints.launchpad.net/glance/+spec/create-glance-manage-conf&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance-manage&lt;/span&gt;&lt;/code&gt; currently uses the configuration files meant for
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance-registry&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance-api&lt;/span&gt;&lt;/code&gt;. This was ostensibly done to reduce the
number of places that an operator may need to add, update, or remove settings.
I would like to create a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance-manage.conf&lt;/span&gt;&lt;/code&gt; file to allow
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance-manage&lt;/span&gt;&lt;/code&gt; to be independently configured.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;If &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance-api&lt;/span&gt;&lt;/code&gt; is started by a user (or service) but a different user tries
to use &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance-manage&lt;/span&gt;&lt;/code&gt; they can encounter permissions errors if
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/var/log/glance/api.log&lt;/span&gt;&lt;/code&gt; is not writable to by the user trying to use
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance-manage&lt;/span&gt;&lt;/code&gt;. While this is one symptom of the dependence on the registry
and api configuration files, more may soon appear. Further, having separate
configuration files will allow end users and deployers to configure the tools
separately as well as use &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance-manage&lt;/span&gt;&lt;/code&gt; on a node without requiring the
presence of both &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance-api.conf&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance-registry.conf&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;See also &lt;a class="reference external" href="https://bugs.launchpad.net/glance/+bug/1391211"&gt;bug 1391211&lt;/a&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;I am proposing that we add another configuration file, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance-manage.conf&lt;/span&gt;&lt;/code&gt;
to side-step this and any other issues we have with depending on the registry
and api’s configuration files.&lt;/p&gt;
&lt;p&gt;For Kilo, we will add the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance-manage.conf&lt;/span&gt;&lt;/code&gt; file and continue to load the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance-registry.conf&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance-api.conf&lt;/span&gt;&lt;/code&gt; files in the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance-manage&lt;/span&gt;&lt;/code&gt; command setup step. Currently the load order of
configuration files (which causes &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance-manage&lt;/span&gt;&lt;/code&gt; to use
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/var/log/glance/api.log&lt;/span&gt;&lt;/code&gt;) 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;glance-registry.conf&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance-api.conf&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We will preserve this order and then load &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance-manage.conf&lt;/span&gt;&lt;/code&gt;. We will only
default to setting &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;log_file&lt;/span&gt;&lt;/code&gt; in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance-manage.conf&lt;/span&gt;&lt;/code&gt; to prevent
overriding settings from the other two files. We will also issue a deprecation
warning pointing to this specification so that operators and end users know to
configure &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance-manage.conf&lt;/span&gt;&lt;/code&gt; for a later cycle. In that cycle, we
will stop depending on &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance-registry.conf&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance-api.conf&lt;/span&gt;&lt;/code&gt;. The
documentation should also immediately, starting in the K cycle, begin to
instruct users to configure settings for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance-manage&lt;/span&gt;&lt;/code&gt; in
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance-manage.conf&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 way we could address this would be to remove the default &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;log_file&lt;/span&gt;&lt;/code&gt;
values in Glance’s configuration files. If we did this, all log files would
then be named &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/var/log/{{service}}/{{&lt;/span&gt; &lt;span class="pre"&gt;command&lt;/span&gt; &lt;span class="pre"&gt;}}.log&lt;/span&gt;&lt;/code&gt;, e.g.,
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/var/log/glance/glance-api.log&lt;/span&gt;&lt;/code&gt; would be the file used by &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance-api&lt;/span&gt;&lt;/code&gt;.
Changing this would not only break current documentation but also end user
expectations. Due to the considerable difference in behaviour without prior
warning, we decided to take the approach outlined in this specification
instead of using the same conventions as other projects.&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 would introduce another file that would need to be edited by end users.
Some settings configured in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance-manage.conf&lt;/span&gt;&lt;/code&gt; may also be present in
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance-registry.conf&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance-api.conf&lt;/span&gt;&lt;/code&gt;. Any potential security
problems caused by needing to copy and synchronize settings between three
files are applicable here. Alternatively, since &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance-manage&lt;/span&gt;&lt;/code&gt; can be
configured separately now, there will be no need to have the full API and
registry configuration files on a node in order to run &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance-manage&lt;/span&gt;&lt;/code&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;This introduces another file with configuration options. Common configuration
options for will need to be copied and pasted from file-to-file and will need
attention to keep synchronized. This will likely increase the complexity of
maintaining an installation of Glance.&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 be able to run &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance-manage&lt;/span&gt;&lt;/code&gt; from nodes without needing
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance-registry.conf&lt;/span&gt;&lt;/code&gt; or &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance-api.conf&lt;/span&gt;&lt;/code&gt; to be present. This
specification does introduce another file that deployers need to be aware of
and know how to configure.&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;icordasc&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="reviewers"&gt;
&lt;h3&gt;Reviewers&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Core reviewer(s):&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;nikhil-komawar&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other reviewer(s):&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;kragniz
jokke_&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;Generate a default &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance-manage.conf&lt;/span&gt;&lt;/code&gt; as described above&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Begin loading it in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance-manage&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add deprecation messages regarding &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance-registry.conf&lt;/span&gt;&lt;/code&gt; and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance-api.conf&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update the documentation to describe how to configure &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance-manage&lt;/span&gt;&lt;/code&gt; with
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance-manage.conf&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;We can test this by ensuring that a separate log file is generated for
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance-manage&lt;/span&gt;&lt;/code&gt;, i.e., &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/var/log/glance/manage.log&lt;/span&gt;&lt;/code&gt; is present after
running the command.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;This will require the changes to describe how to configure &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance-manage&lt;/span&gt;&lt;/code&gt;
to continue working as it has in the past.&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/glance/+bug/1391211"&gt;https://bugs.launchpad.net/glance/+bug/1391211&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
</description><pubDate>Thu, 18 Dec 2014 00:00:00 </pubDate></item><item><title>Add capabilities to storage driver</title><link>http://specs.openstack.org/openstack/glance-specs/specs/kilo/store-capabilities.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/glance/+spec/store-capabilities"&gt;https://blueprints.launchpad.net/glance/+spec/store-capabilities&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This features will enable the static and dynamic ability of a storage driver
instance based on it’s implementation as well as the configuration. The runtime
status of the backend storage will influence the capacity too.&lt;/p&gt;
&lt;p&gt;Henceforth, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;glance_store&lt;/span&gt;&lt;/code&gt; library can perform proper operations on
storage as requested by upper layer, e.g. Glance. For example, to enable
or disable image adding function to glance based on current implementation.
The store also recognized whether a driver can be reused for all requests
it handles or if it has to be recreated for each request because it is not
stateless.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;The capabilities of store driver can be affected by the following factors:&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Status of a connected backend storage.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The deployment configuration.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;State of the driver code.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Technically one of capabilities is static whereas the other is dynamic.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;Currently glance_store and glance don’t use these capabilities. The driver
doesn’t have a way to expose its capabilities. On the other hand in the store’s
backend handler or client, e.g. glance-{api,registry} there is no common method
to check these generic operations of the store drivers.&lt;/p&gt;
&lt;p&gt;Currently we observe at least two kind of problems:&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Some necessary applicability check on the operation related with store
access are missing, which inhibits the usability of glance service and
glance_store lib.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Hard to implement such check logic neatly, including common check routine
on these generic operations of store driver, and the check for particular
feature.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;&lt;/blockquote&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;Existing drivers need to be updated to expose proper capabilities.&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;List of required store capabilities as needed currently.&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;Capability 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;READ_ACCESS&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Generic read access&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;WRITE_ACCESS&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Generic write access&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;RW_ACCESS&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;READ_ACCESS and WRITE_ACCESS&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;READ_OFFSET&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Read all bits from a offset
(Included READ_ACCESS)&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;WRITE_OFFSET&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Write all bits to a offset
(Included WRITE_ACCESS)&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;RW_OFFSET&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;READ_OFFSET and WRITE_OFFSET&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;READ_CHUNK&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Read required length of bits
(Included READ_ACCESS)&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;WRITE_CHUNK&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Write required length of bits
(Included WRITE_ACCESS)&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;RW_CHUNK&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;READ_CHUNK and WRITE_CHUNK&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;READ_RANDOM&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;READ_OFFSET and READ_CHUNK&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;WRITE_RANDOM&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;WRITE_OFFSET and WRITE_CHUNK&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;RW_RANDOM&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;RW_OFFSET and RW_CHUNK&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;DRIVER_REUSABLE&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;driver is stateless and its instance can be
reused safely&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add common check routine on these generic operations for the store drivers.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Refactoring existing drivers to leverage these capabilities.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add the logic to recreate driver instance if the storage or driver
isn’t stateless.&lt;/p&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;There is no expectation for any obvious degradation in the performance.&lt;/p&gt;
&lt;p&gt;The reason being that there is a simple addition of a checker function
being triggered in the form of a hook for each store operation, with
current inclusion of the (‘get’, ‘delete’, ‘add’) operations.&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;Developers implementing new drivers to the glance_store library would need to
be aware of this concept. The static and dynamic ability of the storage backend
could influence their and their implementation design.&lt;/p&gt;
&lt;p&gt;All changes maintain backward-compatibility.&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;zhiyan (lzy-dev)&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="reviewers"&gt;
&lt;h3&gt;Reviewers&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Core reviewer(s):&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Nikhil Komawar (nikhil-komawar)
Stuart McLaren (stuart-mcLaren)&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;&lt;a class="reference external" href="https://review.openstack.org/#/c/137416"&gt;glance_store change&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/141825"&gt;Glance change&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;Necessary unit and functional test cases, will be added into
glance_store as well as glance.&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;Corresponding changes:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://review.openstack.org/#/c/137416"&gt;glance_store change&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/141825"&gt;Glance change&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
</description><pubDate>Tue, 02 Dec 2014 00:00:00 </pubDate></item><item><title>Catalog Index Service</title><link>http://specs.openstack.org/openstack/glance-specs/specs/kilo/catalog-index-service.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/glance/+spec/catalog-index-service"&gt;https://blueprints.launchpad.net/glance/+spec/catalog-index-service&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This is intended to improve performance of Glance API services while
dramatically improving search capabilities.&lt;/p&gt;
&lt;p&gt;It will improve performance by offloading user search queries from existing
API servers. In addition, we are working on numerous improvements in Horizon
which will include improvements to image, snapshot, artifact details and
searching. The desired user experience is greatly dependent upon a rich,
dynamic, near real time faceted and aggregated search capability with a strong
query language.&lt;/p&gt;
&lt;p&gt;This will initially be considered “Experimental API”. The API is intended to
be as close to final as possible, but we reserve the right to completely
abandon this or change it making it backwards in-compatible.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Glance has metadata for all images and provides listing of them.  If you want
to search for images based on criteria, the API is limited and somewhat
inflexible. Search currently is limited to union (“AND” operations) searching
of certain hard coded attributes. There is no support for intersection ( “OR”
operations).&lt;/p&gt;
&lt;p&gt;Searching does not include searching descriptions and has limited support for
property based searches. Full text searching of descriptions is typically slow
with a traditional relational database. Adding full text indexing to the
database can degrade overall performance of the database (affects inserts).&lt;/p&gt;
&lt;p&gt;With the addition of metadata definitions in Juno release, the new search API
should allow the users to specify the search criteria using the tags and
property type definition in addition to adhoc string search. They should
ideally get auto-completion of possible properties and property values with
near real time response.&lt;/p&gt;
&lt;p&gt;Artifact definitions will support storing dynamic properties based on the
artifact type. However, proper indexing and search is not possible with a
traditional RDBMS. You end up with full table scans across tables that are not
applicable for a given query.  In addition, writing and understanding the
query engine is difficult to understand and maintain, especially after the
original authors move on.&lt;/p&gt;
&lt;p&gt;Adding new properties with constraints for highly performant searching is
difficult to achieve in a relational database.&lt;/p&gt;
&lt;p&gt;A search engine needs to be easily customizable so that the data being
collected can be changed dynamically and the way it is indexed and searched
can be easily modified without requiring source data migration. (e.g. a new
type of object to group namespaces together called “category”)&lt;/p&gt;
&lt;p&gt;Typical search interfaces should also provide facilities like auto-completion
and search suggestions with near real time performance.  This is not possible
with a traditional database.&lt;/p&gt;
&lt;p&gt;Adding more attributes to a search query over time should be easy to extend
and maintain without exponentially increasing the complexity of the search
logic.&lt;/p&gt;
&lt;p&gt;User should be able to combine the search query across resources (images,
metadata, artifacts) easily.&lt;/p&gt;
&lt;p&gt;A search engine should not put additional load on the normal functions of the
primary service and should easily accommodate more users by distributing the
load on separate server instances. For example, a search query from Horizon
should not impact Nova.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;We are proposing a new catalog search service for Glance that will improve
performance of Glance API services while dramatically improving search
capabilities. The following subsections detail the concepts.&lt;/p&gt;
&lt;p&gt;Block Diagram:&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://wiki.openstack.org/w/images/7/74/Index-service-block-diagram.png"&gt;https://wiki.openstack.org/w/images/7/74/Index-service-block-diagram.png&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The service will be based on Elasticsearch. Elasticsearch is a search server
based on Lucene. It provides a distributed, scalable, near real-time, faceted,
multitenant-capable full-text search engine with a RESTful web interface and
schema-free JSON documents. Elasticsearch is developed and released as open
source under the terms of the Apache License.  Notable users of Elasticsearch
include Wikimedia, StumbleUpon, Mozilla, Quora, Foursquare, Etsy, SoundCloud,
GitHub, FDA, CERN, and Stack Exchange.
(Source: &lt;a class="reference external" href="http://en.wikipedia.org/wiki/Elasticsearch"&gt;http://en.wikipedia.org/wiki/Elasticsearch&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;The elastic-recheck project also uses Elasticsearch (and kibana) to classify
and track OpenStack gate failures.
(Source: &lt;a class="reference external" href="http://status.openstack.org/elastic-recheck"&gt;http://status.openstack.org/elastic-recheck&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Indexing&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Index&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;This will serve as the cache for all search requests. It will be backed by
Elasticsearch.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Index Loaders&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Index loaders define the data mappings for indexing and load the data from the
source. They are called during initialization of service and on-demand later
when required to index everything. They ensure that all appropriate RBAC
information is included in the index to facilitate appropriate authorization
on search responses.&lt;/p&gt;
&lt;p&gt;The index loaders will attempt to maintain native API format as best as
possible with as much direct pass through as possible so that data manipulation
and maintenance is kept to a minimum.&lt;/p&gt;
&lt;p&gt;An example Glance Image data mapping 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="s1"&gt;'dynamic'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;True&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;'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="s1"&gt;'name'&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;'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;'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;'tags'&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;'disk_format'&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;'container_format'&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;'size'&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;'long'&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="s1"&gt;'virtual_size'&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;'long'&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="s1"&gt;'status'&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;'visibility'&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;'checksum'&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;'min_disk'&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;'long'&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="s1"&gt;'min_ram'&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;'long'&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="s1"&gt;'owner'&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;'protected'&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;'boolean'&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;&lt;em&gt;Index Updates&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Once the index is initialized it needs to be constantly updated to keep it in
sync with the data source. Update clients will listen for notifications from
data sources to re-index the data for specific resources (e.g. an image or
artifact).&lt;/p&gt;
&lt;p&gt;For glance, it would listen on message Topic for notifications like (image.create,
image.update, etc) and reindex for the effected image metadata.
(More info at &lt;a class="reference external" href="http://docs.openstack.org/developer/glance/notifications.html"&gt;http://docs.openstack.org/developer/glance/notifications.html&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Index Management API&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Allows for CRUD management of loading, updating and deleting data in the index.
Indexing is allowed only for admin users.&lt;/p&gt;
&lt;p&gt;Default policy.json 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="s2"&gt;"catalog_index"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"role:admin"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;"catalog_search"&lt;/span&gt;&lt;span class="p"&gt;:&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;&lt;strong&gt;Searching&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The search API allows users to execute a search query and get back search hits
that match the query. The query can either be provided using a simple query
string as a parameter, or using a request body.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;Search query is not parsed and passed “as-is” to elastic search engine except for adding filters. Response from search engine could be filtered based on the plugin implementation of document type.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;All search APIs can be applied across multiple types within an index, and
across multiple indices with support for the multi index syntax.&lt;/p&gt;
&lt;p&gt;This will allow for search phrase completion as well as search suggestions(
such as handling misspellings)&lt;/p&gt;
&lt;p&gt;The search will have two levels of RBAC.&lt;/p&gt;
&lt;p&gt;1. API level policy checks using policy.json files.  This will allow coarse
grained RBAC support for simple deny / allow on API usage.&lt;/p&gt;
&lt;p&gt;2. RBAC query filters.  These will be defined in conjunction with index loaders.
When a request comes in, the type(s) of resource(s) being requested will map
to an RBAC query filter.&lt;/p&gt;
&lt;p&gt;The RBAC query filter will add any appropriate filters to the request being
sent into the elastic search service, such that only specific results that
the user is allowed to view will be returned.&lt;/p&gt;
&lt;p&gt;For example, the image index loader will include indexing owner information
and visibility information. The RBAC filter will examine the incoming request
and adds filters to the request so that the results don’t include non-shared /
non-public images from a different project than the user making the request.&lt;/p&gt;
&lt;p&gt;Property protected fields will be read from the config file and will be added
as “source filtering” field(s) in elasticsearch query which will keep/remove the
protected fields from the search output based on the authorization of the user.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Searching data could also be achieved by writing SQL queries on the Glance
database but there are several factors which do not make it an ideal
solution:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Joins across multiple tables in real time will make the response time very
slow&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Full text searching of descriptions is typically slow with a traditional
relational database. Adding full text indexing to the database can degrade
overall performance of the database&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Property types can be added dynamically using metadefs and proper indexing
in relational databases is not possible&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Search queries will be running against the same database used by Glance core
functions and inadvertently effecting their response time.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Adding more attributes to search query over time should be easy to extend
and maintain without exponentially increasing the complexity of the search
logic&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;User should be able to combine the search query across resources (images,
artifacts) etc. and the search engine should not be tightly integrated with
any specific module.&lt;/p&gt;
&lt;p&gt;Another alternative would be for clients to load the entire data set and
search within the client.  This means every user gets all the data every
time the user loads the page and has to keep it in sync with server side data.
This is increases the load and burden on the core OpenStack service providing
the data and is slower since the client has to load the entire dataset across
the network. In addition, the client has to recreate the logic for things like
search suggestions and complex queries with AND / OR logic.&lt;/p&gt;
&lt;p&gt;It should be noted that NONE of these options also include an ability to do things
like get search request scoring of results returned with a configurable threshold
for results (something elastic search provides).&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 data being indexed will be stored outside the Glance SQL database and
therefore we don’t expect any data model changes in Glance.&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;Common Response Codes&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Create Success: 201 Created&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Modify Success: 200 OK&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Delete Success: 204 No Content&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Failure: 400 Bad Request with details.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Forbidden: 403 Forbidden&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Not found: 404 Not found e.g. if specific entity not found&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Method Not Allowed: 405 Not allowed e.g. if trying to delete on a list resource&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Not Implemented: 501 Not Implemented e.g. HEAD not implemented&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This is an experimental API&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;API Version&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Search images supports both GET and POST.
Elasticsearch supports GET with query params but its a limited subset of query DSL.
GET is implemented here with a request body to make use of all the available query options&lt;/p&gt;
&lt;p&gt;Please refer to the following URI for the Query DSL
&lt;a class="reference external" href="http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl.html"&gt;http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Search images(GET):&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&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;v2&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;search&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Example Request Body:&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;"index"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"glance"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"image"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="s2"&gt;"query"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="s2"&gt;"query_string"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="s2"&gt;"query"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"cirros"&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;Example Response Body:&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;"took"&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="s2"&gt;"timed_out"&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;"_shards"&lt;/span&gt;&lt;span class="p"&gt;:&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;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s2"&gt;"successful"&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="s2"&gt;"failed"&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;"hits"&lt;/span&gt;&lt;span class="p"&gt;:&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;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s2"&gt;"max_score"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.40409642&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s2"&gt;"hits"&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;"_index"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"search"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
              &lt;span class="s2"&gt;"_type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"image"&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;"75fbdd4c-3e5b-4552-8950-9bb5262babcd"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
              &lt;span class="s2"&gt;"_score"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.40409642&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
              &lt;span class="s2"&gt;"_source"&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;"active"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                  &lt;span class="s2"&gt;"virtual_size"&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;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"cirros-0.3.2-x86_64-uec-ramdisk"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                  &lt;span class="s2"&gt;"property"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
                  &lt;span class="s2"&gt;"container_format"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"ari"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                  &lt;span class="s2"&gt;"min_ram"&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;"disk_format"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"ari"&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;"owner"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"f72690e85b2a4ff095f50b7fad99429a"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                  &lt;span class="s2"&gt;"protected"&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;"checksum"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"68085af2609d03e51c7662395b5b6e4b"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                  &lt;span class="s2"&gt;"min_disk"&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;"is_public"&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;"size"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3723817&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;"75fbdd4c-3e5b-4552-8950-9bb5262babcd"&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;""&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;"_index"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"search"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
              &lt;span class="s2"&gt;"_type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"image"&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;"95467ea8-dd34-4bdd-8a6a-f52e47ee9bce"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
              &lt;span class="s2"&gt;"_score"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.23091224&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
              &lt;span class="s2"&gt;"_source"&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;"active"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                  &lt;span class="s2"&gt;"virtual_size"&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;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"cirros-0.3.2-x86_64-uec"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                  &lt;span class="s2"&gt;"property"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
                      &lt;span class="s2"&gt;"kernel_id_d00ea383-a1fa-48d3-b56c-880093730b53"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                      &lt;span class="s2"&gt;"ramdisk_id_75fbdd4c-3e5b-4552-8950-9bb5262babcd"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                      &lt;span class="s2"&gt;"hypervisor_type_uml"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                      &lt;span class="s2"&gt;"hw_watchdog_action_poweroff"&lt;/span&gt;
                  &lt;span class="p"&gt;],&lt;/span&gt;
                  &lt;span class="s2"&gt;"container_format"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"ami"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                  &lt;span class="s2"&gt;"min_ram"&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;"disk_format"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"ami"&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="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;"kernel_id"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                          &lt;span class="s2"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"d00ea383-a1fa-48d3-b56c-880093730b53"&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;"ramdisk_id"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                          &lt;span class="s2"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"75fbdd4c-3e5b-4552-8950-9bb5262babcd"&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;"hypervisor_type"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                          &lt;span class="s2"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"uml"&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;"hw_watchdog_action"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                          &lt;span class="s2"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"poweroff"&lt;/span&gt;
                      &lt;span class="p"&gt;}&lt;/span&gt;
                  &lt;span class="p"&gt;],&lt;/span&gt;
                  &lt;span class="s2"&gt;"owner"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"f72690e85b2a4ff095f50b7fad99429a"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                  &lt;span class="s2"&gt;"protected"&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;"checksum"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"4eada48c2843d2a262c814ddc92ecf2c"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                  &lt;span class="s2"&gt;"min_disk"&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;"is_public"&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;"size"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;25165824&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;"95467ea8-dd34-4bdd-8a6a-f52e47ee9bce"&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;""&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;"_index"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"search"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
              &lt;span class="s2"&gt;"_type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"image"&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;"d00ea383-a1fa-48d3-b56c-880093730b53"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
              &lt;span class="s2"&gt;"_score"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.067124054&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
              &lt;span class="s2"&gt;"_source"&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;"active"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                  &lt;span class="s2"&gt;"virtual_size"&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;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"cirros-0.3.2-x86_64-uec-kernel"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                  &lt;span class="s2"&gt;"property"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
                  &lt;span class="s2"&gt;"container_format"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"aki"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                  &lt;span class="s2"&gt;"min_ram"&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;"disk_format"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"aki"&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;"owner"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"f72690e85b2a4ff095f50b7fad99429a"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                  &lt;span class="s2"&gt;"protected"&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;"checksum"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"836c69cbcd1dc4f225daedbab6edc7c7"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                  &lt;span class="s2"&gt;"min_disk"&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;"is_public"&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;"size"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;4969360&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;"d00ea383-a1fa-48d3-b56c-880093730b53"&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;""&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;Search images(POST):&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;POST&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;v2&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;search&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Please refer to the following URI for the Query DSL
&lt;a class="reference external" href="http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl.html"&gt;http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Example Request Body:&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;"index"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"glance"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"image"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="s2"&gt;"query"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="s2"&gt;"query_string"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="s2"&gt;"query"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"cirros"&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;Example Response Body:&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;"took"&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="s2"&gt;"timed_out"&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;"_shards"&lt;/span&gt;&lt;span class="p"&gt;:&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;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s2"&gt;"successful"&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="s2"&gt;"failed"&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;"hits"&lt;/span&gt;&lt;span class="p"&gt;:&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;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s2"&gt;"max_score"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.40409642&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s2"&gt;"hits"&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;"_index"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"search"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
              &lt;span class="s2"&gt;"_type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"image"&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;"75fbdd4c-3e5b-4552-8950-9bb5262babcd"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
              &lt;span class="s2"&gt;"_score"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.40409642&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
              &lt;span class="s2"&gt;"_source"&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;"active"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                  &lt;span class="s2"&gt;"virtual_size"&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;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"cirros-0.3.2-x86_64-uec-ramdisk"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                  &lt;span class="s2"&gt;"property"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
                  &lt;span class="s2"&gt;"container_format"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"ari"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                  &lt;span class="s2"&gt;"min_ram"&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;"disk_format"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"ari"&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;"owner"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"f72690e85b2a4ff095f50b7fad99429a"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                  &lt;span class="s2"&gt;"protected"&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;"checksum"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"68085af2609d03e51c7662395b5b6e4b"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                  &lt;span class="s2"&gt;"min_disk"&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;"is_public"&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;"size"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3723817&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;"75fbdd4c-3e5b-4552-8950-9bb5262babcd"&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;""&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;"_index"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"search"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
              &lt;span class="s2"&gt;"_type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"image"&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;"95467ea8-dd34-4bdd-8a6a-f52e47ee9bce"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
              &lt;span class="s2"&gt;"_score"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.23091224&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
              &lt;span class="s2"&gt;"_source"&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;"active"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                  &lt;span class="s2"&gt;"virtual_size"&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;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"cirros-0.3.2-x86_64-uec"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                  &lt;span class="s2"&gt;"property"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
                      &lt;span class="s2"&gt;"kernel_id_d00ea383-a1fa-48d3-b56c-880093730b53"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                      &lt;span class="s2"&gt;"ramdisk_id_75fbdd4c-3e5b-4552-8950-9bb5262babcd"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                      &lt;span class="s2"&gt;"hypervisor_type_uml"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                      &lt;span class="s2"&gt;"hw_watchdog_action_poweroff"&lt;/span&gt;
                  &lt;span class="p"&gt;],&lt;/span&gt;
                  &lt;span class="s2"&gt;"container_format"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"ami"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                  &lt;span class="s2"&gt;"min_ram"&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;"disk_format"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"ami"&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="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;"kernel_id"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                          &lt;span class="s2"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"d00ea383-a1fa-48d3-b56c-880093730b53"&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;"ramdisk_id"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                          &lt;span class="s2"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"75fbdd4c-3e5b-4552-8950-9bb5262babcd"&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;"hypervisor_type"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                          &lt;span class="s2"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"uml"&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;"hw_watchdog_action"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                          &lt;span class="s2"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"poweroff"&lt;/span&gt;
                      &lt;span class="p"&gt;}&lt;/span&gt;
                  &lt;span class="p"&gt;],&lt;/span&gt;
                  &lt;span class="s2"&gt;"owner"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"f72690e85b2a4ff095f50b7fad99429a"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                  &lt;span class="s2"&gt;"protected"&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;"checksum"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"4eada48c2843d2a262c814ddc92ecf2c"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                  &lt;span class="s2"&gt;"min_disk"&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;"is_public"&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;"size"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;25165824&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;"95467ea8-dd34-4bdd-8a6a-f52e47ee9bce"&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;""&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;"_index"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"search"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
              &lt;span class="s2"&gt;"_type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"image"&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;"d00ea383-a1fa-48d3-b56c-880093730b53"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
              &lt;span class="s2"&gt;"_score"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.067124054&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
              &lt;span class="s2"&gt;"_source"&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;"active"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                  &lt;span class="s2"&gt;"virtual_size"&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;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"cirros-0.3.2-x86_64-uec-kernel"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                  &lt;span class="s2"&gt;"property"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
                  &lt;span class="s2"&gt;"container_format"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"aki"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                  &lt;span class="s2"&gt;"min_ram"&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;"disk_format"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"aki"&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;"owner"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"f72690e85b2a4ff095f50b7fad99429a"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                  &lt;span class="s2"&gt;"protected"&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;"checksum"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"836c69cbcd1dc4f225daedbab6edc7c7"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                  &lt;span class="s2"&gt;"min_disk"&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;"is_public"&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;"size"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;4969360&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;"d00ea383-a1fa-48d3-b56c-880093730b53"&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;""&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;Index images: index, create, update and delete data:&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;POST&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;v2&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Indexing is allowed only for admin users.
Supported actions are index, create, update and delete&lt;/p&gt;
&lt;p&gt;Example Request Body:&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;"default_index"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"search"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;"default_type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"image"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;"actions"&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;"action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"create"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="s2"&gt;"index"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"search"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"image"&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;"d00ea383-a1fa-48d3-b56c-880093730b54"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="s2"&gt;"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;"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="s2"&gt;"virtual_size"&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;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"cirros-0.3.3-x86_64-uec-kernel"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
              &lt;span class="s2"&gt;"property"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
              &lt;span class="s2"&gt;"container_format"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"aki"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
              &lt;span class="s2"&gt;"min_ram"&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;"disk_format"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"aki"&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;"owner"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"f72690e85b2a4ff095f50b7fad99429a"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
              &lt;span class="s2"&gt;"protected"&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;"checksum"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"836c69cbcd1dc4f225daedbab6edc7c7"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
              &lt;span class="s2"&gt;"min_disk"&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;"is_public"&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;"size"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;4969360&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;"d00ea383-a1fa-48d3-b56c-880093730b54"&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;""&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;"action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"update"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="s2"&gt;"index"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"search"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"image"&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;"75fbdd4c-3e5b-4552-8950-9bb5262babcd"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="s2"&gt;"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;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"cirros x86"&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;"inactive"&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;"action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"delete"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="s2"&gt;"index"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"search"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"image"&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;"95467ea8-dd34-4bdd-8a6a-f52e47ee9bce"&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 to existing Glance API.
Search queries will apply filters to return data that the user is authorized
to see. See description.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;None to existing notifications. Will only consume notifications
Need to add metadef notifications to Glance service.&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-glanceclient as needed&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;No changes to existing API or code
Data from Glance DB will read once during initialization to index it inside
search engine.&lt;/p&gt;
&lt;p&gt;This is intended to improve performance of Glance API services while
dramatically improving search capabilities. It will improve performance
by offloading user search queries from existing API servers.&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;Glance Catalog Index service will be installed as a separate service
with its own port and endpoint.&lt;/p&gt;
&lt;p&gt;This will initially be considered “Experimental API”. The API is intended to be
as close to final as possible, but we reserve the right to completely abandon
this or change it making it backwards in-compatible.&lt;/p&gt;
&lt;p&gt;glance-manage will have new commands for indexing image, metadef, and artifact
data&lt;/p&gt;
&lt;p&gt;The deployment will be targeted as a single region service. In future if required
an “Aggregate search” of all regions which can search across all the regions
could be provided.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;These are new API’s and will not impact any existing API’s.&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;lakshmi-sampath, kamil-rykowski,&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;wayne-okuma, travis-tripp&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="reviewers"&gt;
&lt;h3&gt;Reviewers&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Core reviewer(s):&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;nikhil-komawar zhiyan&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other reviewer(s):&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;icordasc&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;Installation of Elastic Search in Glance environment (single node)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;dl class="simple"&gt;
&lt;dt&gt;Index Dictionary data in ElasticSearch&lt;/dt&gt;&lt;dd&gt;&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Write a tool to index all metadata objects (namespaces objects,
properties) from database into elasticsearch&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Write a tool to index all images from database into elasticsearch&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Merge used properties from Glance(optional)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Listen to notifications/events form Glance on Image CRUD(optional) for
continuous indexing of new/old data&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;Create Glance Search API - Interface to backend ElasticSearch&lt;/dt&gt;&lt;dd&gt;&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Make Policy checks on requests&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Filter request based on RBAC with user token&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;Search Images&lt;/dt&gt;&lt;dd&gt;&lt;ul&gt;
&lt;li&gt;&lt;p&gt;List all the results by given search query string&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;Create Glance Index API&lt;/dt&gt;&lt;dd&gt;&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Policy checks&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;Discuss with Openstack/Infra&lt;/dt&gt;&lt;dd&gt;&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Test environment for elasticsearch&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Devstack integration of single node elastic search.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;dl class="simple"&gt;
&lt;dt&gt;Metadef notifications&lt;/dt&gt;&lt;dd&gt;&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Generate and Listen to metadef notifications&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Calls the tools (loaders)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Documentation update&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update glance client&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update glance manage&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;Depends on elasticsearch for search engine&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 all possible code with a goal of being able to
isolate functionality as much as possible.&lt;/p&gt;
&lt;p&gt;Tempest tests will be added wherever possible.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Docs needed for new service and usage.&lt;/p&gt;
&lt;p&gt;All document changes will indicate this as “Experimental API”&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;Elasticsearch Query DSL
&lt;a class="reference external" href="http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl.html"&gt;http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl.html&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
</description><pubDate>Mon, 01 Dec 2014 00:00:00 </pubDate></item><item><title>Delete an Image</title><link>http://specs.openstack.org/openstack/glance-specs/specs/api/v2/delete-image-api-v2.html</link><description>

&lt;p&gt;&lt;strong&gt;DELETE /v2/images/&amp;lt;IMAGE_ID&amp;gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Encode the ID of the image into the request URI. Request body is
ignored.&lt;/p&gt;
&lt;p&gt;Images with the ‘protected’ attribute set to true (boolean) cannot be
deleted and the response will have an HTTP 403 status code. You must
first set the ‘protected’ attribute to false (boolean) and then perform
the delete.&lt;/p&gt;
&lt;p&gt;The response will be empty with an HTTP 204 status code.&lt;/p&gt;
</description><pubDate>Fri, 17 Oct 2014 00:00:00 </pubDate></item><item><title>Image API v2 HTTP PATCH media types</title><link>http://specs.openstack.org/openstack/glance-specs/specs/api/v2/http-patch-image-api-v2.html</link><description>

&lt;section id="overview"&gt;
&lt;h2&gt;Overview&lt;/h2&gt;
&lt;p&gt;The HTTP PATCH request must provide a media type for the server to
determine how the patch should be applied to an image resource. An
unsupported media type will result in an HTTP error response with the
415 status code. For image resources, two media types are supported:&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;application/openstack-images-v2.1-json-patch&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;application/openstack-images-v2.0-json-patch&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;application/openstack-images-v2.1-json-patch&lt;/span&gt;&lt;/code&gt; media type is
intended to provide a useful and compatible subset of the functionality
defined in JavaScript Object Notation (JSON) Patch
&lt;a class="reference external" href="http://tools.ietf.org/html/rfc6902"&gt;RFC6902&lt;/a&gt;, which defines the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;application/json-patch+json&lt;/span&gt;&lt;/code&gt; media type.&lt;/p&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;application/openstack-images-v2.0-json-patch&lt;/span&gt;&lt;/code&gt; media type is based
on &lt;a class="reference external" href="http://tools.ietf.org/html/draft-ietf-appsawg-json-patch-04"&gt;draft
4&lt;/a&gt; of
the standard. Its use is deprecated.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="restricted-json-pointers"&gt;
&lt;h2&gt;Restricted JSON pointers&lt;/h2&gt;
&lt;p&gt;The ‘application/openstack-images-v2.1-json-patch’ media type defined in
this appendix adopts a restricted form of
&lt;a class="reference external" href="http://tools.ietf.org/html/draft-pbryan-zyp-json-pointer"&gt;JSON-Pointers&lt;/a&gt;.
A restricted JSON pointer is a
&lt;a class="reference external" href="http://tools.ietf.org/html/draft-ietf-appsawg-json-pointer-03#ref-Unicode"&gt;Unicode&lt;/a&gt;
string containing a sequence of exactly one reference token, prefixed by
a ‘/’ (%x2F) character.&lt;/p&gt;
&lt;p&gt;If a reference token contains ‘~’ (%x7E) or ‘/’ (%x2F) characters, they
must be encoded as ‘~0’ and ‘~1’ respectively.&lt;/p&gt;
&lt;p&gt;Its ABNF syntax 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;restricted&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;pointer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"/"&lt;/span&gt; &lt;span class="n"&gt;reference&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;
&lt;span class="n"&gt;reference&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;token&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;unescaped&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;escaped&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;unescaped&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="n"&gt;x00&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;E&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="n"&gt;x30&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="n"&gt;D&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="n"&gt;x7F&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="n"&gt;FFFF&lt;/span&gt;
&lt;span class="n"&gt;escaped&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"~"&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s2"&gt;"0"&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="s2"&gt;"1"&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Restricted JSON Pointers are evaluated as ordinary JSON pointers per
&lt;a class="reference external" href="http://tools.ietf.org/html/draft-pbryan-zyp-json-pointer"&gt;JSON-Pointer&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;For example, given the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;image&lt;/span&gt;&lt;/code&gt; entity:&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;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"da3b75d9-3f4a-40e7-8a2c-bfab23927dea"&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;"cirros-0.3.0-x86_64-uec-ramdisk"&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="s2"&gt;"visibility"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"public"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"size"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2254249&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"checksum"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"2cec138d7dae2aa59038ef8c9aec2390"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"~/.ssh/"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"present"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"tags"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"ping"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"pong"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="s2"&gt;"created_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"2012-08-10T19:23:50Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"updated_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"2012-08-10T19:23:50Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"self"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"/v2/images/da3b75d9-3f4a-40e7-8a2c-bfab23927dea"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"file"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"/v2/images/da3b75d9-3f4a-40e7-8a2c-bfab23927dea/file"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"schema"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"/v2/schemas/image"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The following restricted JSON pointers evaluate to the accompanying
values:&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;"/name"&lt;/span&gt;        &lt;span class="s2"&gt;"cirros-0.3.0-x86_64-uec-ramdisk"&lt;/span&gt;
&lt;span class="s2"&gt;"/size"&lt;/span&gt;        &lt;span class="mi"&gt;2254249&lt;/span&gt;
&lt;span class="s2"&gt;"/tags"&lt;/span&gt;        &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"ping"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"pong"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="s2"&gt;"/~0~1.ssh~1"&lt;/span&gt;  &lt;span class="s2"&gt;"present"&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="operations"&gt;
&lt;h2&gt;Operations&lt;/h2&gt;
&lt;p&gt;The application/openstack-images-v2.1-json-patch media type supports a
subset of the operations defined in the application/json-patch+json
media type. Specify the operation in the “op” member of the request
object.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;The supported operations are add, remove, and replace.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If an operation object contains no recognized operation member, an
error occurs.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Specify the location where the requested operation is to be performed in
the target image in the “path” member of the operation object.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;The member value is a string containing a restricted JSON-pointer
value that references the location where the operation is to be
performed within the target image.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Where appropriate (that is, for the “add” and “replace” operations), the
operation object must contain the “value” data member.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;The member value is the actual value to add (or to use in the replace
operation) expressed in JSON notation. (For example, strings must be
quoted, numeric values are unquoted.)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The payload for a PATCH request must be a &lt;em&gt;list&lt;/em&gt; of JSON objects. Each
object must adhere to one of the following formats.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;add&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The add operation adds a new value at a specified location in the target
image. The location must reference an image property to add to an
existing image.&lt;/p&gt;
&lt;p&gt;The operation object specifies a “value” member and associated value.&lt;/p&gt;
&lt;p&gt;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;PATCH&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;images&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;image_id&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;"op"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"add"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s2"&gt;"path"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"/login-name"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s2"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"kvothe"&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;You can also use the add operation to add a location to the set of
locations that are associated with a specified image ID, as follows:&lt;/p&gt;
&lt;p&gt;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;PATCH&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;images&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;image_id&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;"op"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"add"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s2"&gt;"path"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"/locations/1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s2"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"scheme4://path4"&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;remove&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The remove operation removes the specified image property in the target
image. If an image property does not exist at the specified location, an
error occurs.&lt;/p&gt;
&lt;p&gt;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;PATCH&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;images&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;image_id&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;"op"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"remove"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s2"&gt;"path"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"/login-name"&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;You can also use the remove operation to remove a location from a set of
locations that are associated with a specified image ID, as follows:&lt;/p&gt;
&lt;p&gt;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;PATCH&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;images&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;image_id&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;"op"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"remove"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="s2"&gt;"path"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"/locations/2"&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;replace&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The replace operation replaces the value of a specified image property
in the target image with a new value. The operation object contains a
“value” member that specifies the replacement value.&lt;/p&gt;
&lt;p&gt;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="p"&gt;{&lt;/span&gt;
      &lt;span class="s2"&gt;"op"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"replace"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s2"&gt;"path"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"/login-name"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s2"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"kote"&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 operation is functionally identical to expressing a “remove”
operation for an image property, followed immediately by an “add”
operation at the same location with the replacement value.&lt;/p&gt;
&lt;p&gt;If the specified image property does not exist for the target image, an
error occurs.&lt;/p&gt;
&lt;p&gt;You can also use the replace operation to replace a location in the set
of locations that are associated with a specified image ID, as follows:&lt;/p&gt;
&lt;p&gt;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;PATCH&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;images&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;image_id&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;"op"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"replace"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s2"&gt;"path"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"/locations"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s2"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:[&lt;/span&gt;
         &lt;span class="s2"&gt;"scheme5://path5"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s2"&gt;"scheme6://path6"&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;
</description><pubDate>Fri, 17 Oct 2014 00:00:00 </pubDate></item><item><title>General Image API v2.x information</title><link>http://specs.openstack.org/openstack/glance-specs/specs/api/v2/image-api-v2.html</link><description>

&lt;p&gt;The Image Service API v2 enables you to store and retrieve disk and
server images.&lt;/p&gt;
&lt;section id="versioning"&gt;
&lt;h2&gt;Versioning&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Two-part versioning scheme&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The Image Service API v2 mimics API v1 and uses a major version and a
minor version. For example, v2.3 is major version 2 and minor version 3.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Backwards-compatibility&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Minor version releases expand and do not reduce the interface. For
example, everything in v2.1 is available in v2.2.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Property protections&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The Images API v2.2 enables a cloud provider to employ &lt;em&gt;property
protections&lt;/em&gt;, an optional feature whereby CRUD protections are applied
to image properties.&lt;/p&gt;
&lt;p&gt;Thus, in particular deployments, non-admin users might not be able to
view, update, or delete some image properties.&lt;/p&gt;
&lt;p&gt;Additionally, non-admin users might be forced to follow a particular
naming convention when creating custom image properties.&lt;/p&gt;
&lt;p&gt;It is left to the cloud provider to communicate policies concerning
property protections to users.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="http-response-status-codes"&gt;
&lt;h2&gt;HTTP response status codes&lt;/h2&gt;
&lt;p&gt;The following HTTP status codes are all valid responses:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;200 - generic successful response, expect a body&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;201 - entity created, expect a body and a Location header&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;204 - successful response without body&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;301 - redirection&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;400 - invalid request (syntax, value, etc)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;401 - unauthenticated client&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;403 - authenticated client unable to perform action&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;409 - that action is impossible due to some (possibly permanent)
circumstance&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;415 - unsupported media type&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Responses that don’t have a 200-level response code are not guaranteed
to have a body. If a response does happen to return a body, it is not
part of this spec and cannot be depended upon.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="authentication-and-authorization"&gt;
&lt;h2&gt;Authentication and authorization&lt;/h2&gt;
&lt;p&gt;This spec does not govern how one might authenticate or authorize
clients of the v2 Images API. Implementors are free to decide how to
identify clients and what authorization rules to apply.&lt;/p&gt;
&lt;p&gt;Note that the HTTP 401 and 403 status codes are included in this
specification as valid response codes.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="request-and-response-content-format"&gt;
&lt;h2&gt;Request and response content format&lt;/h2&gt;
&lt;p&gt;The Images Service API v2 primarily accepts and serves JSON-encoded
data. In certain cases it also accepts and serves binary image data.
Most requests that send JSON-encoded data must have the proper media
type in their Content-Type header: ‘application/json’. HTTP PATCH
requests must use the patch media type defined for the entity they
intend to modify. Requests that upload image data should use the media
type ‘application/octet-stream’.&lt;/p&gt;
&lt;p&gt;Each call only responds in one format, so clients should not worry about
sending an Accept header. It is ignored. The response is formatted as
‘application/json’ unless otherwise stated in this spec.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="image-entities"&gt;
&lt;h2&gt;Image entities&lt;/h2&gt;
&lt;p&gt;An image entity is represented by a JSON-encoded data structure and its
raw binary data.&lt;/p&gt;
&lt;p&gt;An image entity has an identifier (ID) that is guaranteed to be unique
within the endpoint to which it belongs. The ID is used as a token in
request URIs to interact with that specific image.&lt;/p&gt;
&lt;p&gt;An image is always guaranteed to have the following attributes: id,
status, visibility, protected, tags, created_at, file and self. The
other attributes defined in the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;image&lt;/span&gt;&lt;/code&gt; schema below are guaranteed to
be defined, but is only returned with an image entity if they have been
explicitly set.&lt;/p&gt;
&lt;p&gt;A client may set arbitrarily-named attributes on their images if the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;image&lt;/span&gt;&lt;/code&gt; json-schema allows it. These user-defined attributes appear
like any other image attributes. See
&lt;a class="reference external" href="http://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.4"&gt;documentation&lt;/a&gt;
of the additionalProperties json-schema attribute.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="json-schemas"&gt;
&lt;h2&gt;JSON schemas&lt;/h2&gt;
&lt;p&gt;The necessary
&lt;a class="reference external" href="http://tools.ietf.org/html/draft-zyp-json-schema-03"&gt;json-schema&lt;/a&gt;
documents are provided at predictable URIs. A consumer should be able to
validate server responses and client requests based on the published
schemas. The schemas contained in this document are only examples and
should not be used to validate your requests. A client should &lt;strong&gt;always&lt;/strong&gt;
fetch schemas from the server.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Property Protections&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Version 2.2 of the Images API acknowledges the ability of a cloud
provider to employ &lt;em&gt;property protections&lt;/em&gt;. Thus, there may be image
properties that will not appear in the list images response for
non-admin users.&lt;/p&gt;
&lt;/section&gt;
</description><pubDate>Fri, 17 Oct 2014 00:00:00 </pubDate></item><item><title>Image API Binary Data API calls</title><link>http://specs.openstack.org/openstack/glance-specs/specs/api/v2/image-binary-data-api-v2.html</link><description>&lt;section id="image-api-binary-data-api-calls"&gt;

&lt;/section&gt;
&lt;section id="binary-data-api"&gt;

&lt;p&gt;The following API calls are used to upload and download raw image data.
For image metadata, see &lt;a class="reference external" href="#metadata-api"&gt;Metadata API&lt;/a&gt;.&lt;/p&gt;
&lt;section id="upload-image-file"&gt;
&lt;h2&gt;Upload Image File&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;PUT /v2/images/&amp;lt;IMAGE_ID&amp;gt;/file&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;NOTE: An image record must exist before a client can store binary image
data with it.&lt;/p&gt;
&lt;p&gt;Request Content-Type must be ‘application/octet-stream’. Complete
contents of request body will be stored and become accessible in its
entirety by issuing a GET request to the same URI.&lt;/p&gt;
&lt;p&gt;Response status will be 204.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="download-image-file"&gt;
&lt;h2&gt;Download Image File&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;GET /v2/images/&amp;lt;IMAGE_ID&amp;gt;/file&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Request body ignored.&lt;/p&gt;
&lt;p&gt;Response body will be the raw binary data that represents the actual
virtual disk. The Content-Type header will be
‘application/octet-stream’.&lt;/p&gt;
&lt;p&gt;The &lt;a class="reference external" href="http://www.ietf.org/rfc/rfc1864.txt"&gt;Content-MD5&lt;/a&gt; header will
contain an MD5 checksum of the image data. Clients are encouraged to
verify the integrity of the image data they receive using this checksum.&lt;/p&gt;
&lt;p&gt;If no image data has been stored, an HTTP status of 204 is returned.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
</description><pubDate>Fri, 17 Oct 2014 00:00:00 </pubDate></item><item><title>Get an Image</title><link>http://specs.openstack.org/openstack/glance-specs/specs/api/v2/retrieve-image-api-v2.html</link><description>

&lt;p&gt;&lt;strong&gt;GET /v2/images/&amp;lt;IMAGE_ID&amp;gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Request body ignored.&lt;/p&gt;
&lt;p&gt;Response body is a single image entity. Using &lt;strong&gt;GET
/v2/image/da3b75d9-3f4a-40e7-8a2c-bfab23927dea&lt;/strong&gt; as 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="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;"da3b75d9-3f4a-40e7-8a2c-bfab23927dea"&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;"cirros-0.3.0-x86_64-uec-ramdisk"&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="s2"&gt;"visibility"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"public"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"size"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2254249&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"checksum"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"2cec138d7dae2aa59038ef8c9aec2390"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"tags"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"ping"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"pong"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="s2"&gt;"created_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"2012-08-10T19:23:50Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"updated_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"2012-08-10T19:23:50Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"self"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"/v2/images/da3b75d9-3f4a-40e7-8a2c-bfab23927dea"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"file"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"/v2/images/da3b75d9-3f4a-40e7-8a2c-bfab23927dea/file"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"schema"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"/v2/schemas/image"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Property Protections&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Version 2.2 of the Images API acknowledges the ability of a cloud
provider to employ &lt;em&gt;property protections&lt;/em&gt;. Thus, there may be some image
properties that will not appear in the image detail response for
non-admin users.&lt;/p&gt;
</description><pubDate>Fri, 17 Oct 2014 00:00:00 </pubDate></item><item><title>Tag Catalog Support For Metadata Definitions</title><link>http://specs.openstack.org/openstack/glance-specs/specs/kilo/metadefs-tags.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/glance/+spec/metadefs-tags"&gt;https://blueprints.launchpad.net/glance/+spec/metadefs-tags&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This blueprint adds the basic tag catalog back after it was deferred from Juno
due to time constraints. The original, approved spec included supporting tag
libraries in the metadata definitions catalog. However, at the end of
Juno, the original spec was updated to remove tags since they weren’t
implemented.&lt;/p&gt;
&lt;p&gt;This spec is actually a reduction of the tag concepts in the original
approved Juno spec. In the original Juno spec, tags had a dynamic hierarchy
capability.  This spec does not include the tag hierarchy in order to
simplify this spec. That aspect of tags will be deferred to a later spec.&lt;/p&gt;
&lt;p&gt;The implemented juno spec is here for reference:&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://github.com/openstack/glance-specs/blob/master/specs/juno/metadata-schema-catalog.rst"&gt;https://github.com/openstack/glance-specs/blob/master/specs/juno/metadata-schema-catalog.rst&lt;/a&gt;&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;A challenge with using OpenStack is discovering, sharing, and correlating
tags across services and different types of resources. We believe this
affects both end users and administrators.&lt;/p&gt;
&lt;p&gt;For example, a cloud operator or vendor may have a predefined set of “tags”
they want to be used as a starting point for images and instances. Currently,
OpenStack does not have a facility for the cloud operator to include that base
set of tags. This means that every deployment and every project may end up
with its own disparate set of tags. This leads to inconsistencies, but also is
extra hassle for end users who end up reinventing all the “tags” in every
project.&lt;/p&gt;
&lt;p&gt;For example, is the tag “postgres” the same as “PostgreSQL”? If a
base library of tags is used, any user typing “pos” would be prompted with
the one that already exists in the tag library and would choose it.
Future searches based on tags would ensure consistent results.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Terminology&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The term metadata can become very overloaded and confusing.  This proposed
enhancement is about the additional metadata that is set as “tags” (name only)
across various artifacts and OpenStack services.&lt;/p&gt;
&lt;p&gt;Different APIs may use tags and key / value pairs differently. Tags typically
are not used to drive runtime behavior.  However, key / value pairs are
often used by the system to potentially drive runtime, such as scheduling,
quality of service, or driver behavior.&lt;/p&gt;
&lt;p&gt;A few examples of metadata today:&lt;/p&gt;
&lt;table class="docutils align-default"&gt;
&lt;tbody&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Nova&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Cinder&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Glance&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;dl class="simple"&gt;
&lt;dt&gt;Flavor&lt;/dt&gt;&lt;dd&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;extra specs&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/dd&gt;
&lt;dt&gt;Host Aggregate&lt;/dt&gt;&lt;dd&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;metadata&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/dd&gt;
&lt;dt&gt;Instances&lt;/dt&gt;&lt;dd&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;metadata&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;tags&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/td&gt;
&lt;td&gt;&lt;dl class="simple"&gt;
&lt;dt&gt;Volume &amp;amp; Snapshot&lt;/dt&gt;&lt;dd&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;image metadata&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;metadata&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/dd&gt;
&lt;dt&gt;VolumeType&lt;/dt&gt;&lt;dd&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;extra specs&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;qos specs&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/td&gt;
&lt;td&gt;&lt;dl class="simple"&gt;
&lt;dt&gt;Image &amp;amp; Snapshot&lt;/dt&gt;&lt;dd&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;properties&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;tags&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;We are proposing enhancements to the Metadata Definitions Catalog. The
following subsections detail the enhancements to the catalog.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Tags&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;A catalog of possible tags that can be used to help ensure tag name consistency
across users, resource types, and services. So, when a user goes to apply a tag
on a resource, they will be able to either create new tags or choose from tags
that have been used elsewhere in the system on different types of resources.
For example, the same tag could be used for Images, Volumes, and Instances.
Tags are not case sensitive (BigData is equivalent to bigdata but is different
from Big-Data).&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;A key use case is the collaboration on tags using a common catalog. This
is complementary to tags being added ad-hoc across all services. We think the
metadata API could also be backed by a search indexer across services to
include ad-hoc metadata as well as defined metadata. However, that is not the
focus of this blueprint.&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;This will use a relational database and exist in the same database as the
existing Glance Metadata Definitions Catalog. It will be additive to the
existing schema.&lt;/p&gt;
&lt;p&gt;The following DB schema is the initial suggested schema. We will improve and
take comments during code review. Constraints not shown for readability.&lt;/p&gt;
&lt;p&gt;Suggested Basic Schema:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;CREATE TABLE `metadef_tags` (
  `id`                     int(11) NOT NULL AUTO_INCREMENT,
  `namespace_id`           int(11) NOT NULL,
  `name`                   varchar(80) NOT NULL,
  `created_at`             timestamp NOT NULL,
  `updated_at`             timestamp
)
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;This will not include Tag descriptions in this revision.&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 the REST API everything is referred by namespace and name rather than
synthetic IDs. This helps to achieve portability (import / export using JSON).&lt;/p&gt;
&lt;p&gt;APIs should allow coarse grain and fine grain access to information in order
to control data transfer bandwidth requirements.&lt;/p&gt;
&lt;p&gt;Working with Namespaces
Basic interaction is:&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Get list of namespaces with overview info based on the desired filters.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Get tags&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;Common Response Codes&lt;/strong&gt;&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Create Success: &lt;cite&gt;201 Created&lt;/cite&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Modify Success: &lt;cite&gt;200 OK&lt;/cite&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Delete Success: &lt;cite&gt;204 No Content&lt;/cite&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Failure: &lt;cite&gt;400 Bad Request&lt;/cite&gt; with details.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Forbidden: &lt;cite&gt;403 Forbidden&lt;/cite&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Not found: &lt;cite&gt;404 Not found&lt;/cite&gt; if specific entity not found&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;API Version&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;All URLS will be under the v2 Glance API.  If it is not explicitly specified
assume /v2/&amp;lt;url&amp;gt;&lt;/p&gt;
&lt;p&gt;Namespace may optionally contain the following in addition to basic fields.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;resource_types&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;properties&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;objects&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;tags&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This spec adds Tags.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Tags&lt;/strong&gt;&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;List All Tags in a namespace:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;GET /metadefs/namespace/{namespace}/tags&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;Filters by adding query parameters:&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;limit&lt;/span&gt;          &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Use&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;specific&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="n"&gt;Expect&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;
                 &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;limited&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;between&lt;/span&gt; &lt;span class="n"&gt;zero&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;limit&lt;/span&gt; &lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
&lt;span class="n"&gt;marker&lt;/span&gt;         &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Specifies&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;name&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;last&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;seen&lt;/span&gt; &lt;span class="n"&gt;tag&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;typical&lt;/span&gt; &lt;span class="n"&gt;pattern&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="n"&gt;limit&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;marker&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;make&lt;/span&gt; &lt;span class="n"&gt;an&lt;/span&gt; &lt;span class="n"&gt;initial&lt;/span&gt;
                 &lt;span class="n"&gt;limited&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;then&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;use&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;last&lt;/span&gt; &lt;span class="n"&gt;tag&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;response&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;marker&lt;/span&gt; &lt;span class="n"&gt;parameter&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;subsequent&lt;/span&gt; &lt;span class="n"&gt;limited&lt;/span&gt;
                 &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Design note: We want a format that allows for additional information
such as description to be added without changing the base response. For this
reason, we used a dictionary for each tag rather than just a flat list of
tags.&lt;/p&gt;
&lt;p&gt;Example Body:&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;"tags"&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;"Databases"&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;"BigData"&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;"MySQL"&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;"PostgreSQL"&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;"MongoDB"&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;dl class="simple"&gt;
&lt;dt&gt;Create / Replace all tags in a specific namespace:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;POST /metadefs/namespaces/{namespace}/tags/&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Add tag in a specific namespace:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;POST /metadefs/namespaces/{namespace}/tags/{tag}&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Delete tag in specific namespace:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;DELETE /metadefs/namespaces/{namespace}/tags/{tag}&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Delete all tags in specific namespace:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;DELETE /metadefs/namespaces/{namespace}/tags&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&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;We intend to expose this via Horizon and are working on related blueprints.&lt;/p&gt;
&lt;p&gt;Update python-glanceclient as needed.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None anticipated.&lt;/p&gt;
&lt;p&gt;This is expected to be called from Horizon when an admin wants to annotate
tags onto things likes images and instances. This API would be hit for them to
get available tags or create new ones.&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;DB Schema Creation for new API&lt;/p&gt;
&lt;p&gt;Default / Sample tag libraries will be checked into Glance.&lt;/p&gt;
&lt;p&gt;Deployers can customize these and provide additional definition files suitable
to their cloud deployment.&lt;/p&gt;
&lt;p&gt;glance-manage will include loading tags.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;None (New API)&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;wayne-okuma&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="reviewers"&gt;
&lt;h3&gt;Reviewers&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Core reviewer(s):&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;zhiyan&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other reviewer(s):&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;lakshmi-sampath
travis-tripp&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;blockquote&gt;
&lt;div&gt;&lt;p&gt;Changes would be made to:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;The database API layer to add support for CRUD operations on tags&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The REST API for CRUD operations on the namespaces (add tags)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The REST API for CRUD operations on the tags&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The python-glanceClient to support operations&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;glance-manage to handle tags&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;Same dependencies as Glance.&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 for all possible code with a goal of being able to
isolate functionality as much as possible.&lt;/p&gt;
&lt;p&gt;Tempest tests will be added wherever possible.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Docs needed for new API extension and usage&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://www.youtube.com/watch?v=Dhrthnq1bnw"&gt;Youtube summit recap of Graffiti Juno POC demo that included tags.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="http://docs.openstack.org/developer/glance/metadefs-concepts.html"&gt;Current glance metadata definition catalog documentation.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Simple application category tags (no hierarchy)&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Images, volumes, software applications can be assigned to a category.
Similarly, a flavor or host aggregate could be “tagged” with supporting a
category of application, such as “BigData” or “Encryption”. Using the
matching of categories, flavors or host aggregates that support that category
of application can be easily paired up.&lt;/p&gt;
&lt;p&gt;Note: If a resource type doesn’t provide a “Tag” mechanism (only key value
pairs), a blueprint should be added to support tags on that type of resource.
In lieu of that, a key of “tags” with a comma separated list of tags as the
value be set on the resource&lt;/p&gt;
&lt;/section&gt;
</description><pubDate>Mon, 13 Oct 2014 00:00:00 </pubDate></item><item><title>Reload configuration files on SIGHUP signal</title><link>http://specs.openstack.org/openstack/glance-specs/specs/kilo/sighup-conf-reload.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/glance/+spec/sighup-conf-reload"&gt;https://blueprints.launchpad.net/glance/+spec/sighup-conf-reload&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;We propose to eliminate the need to restart the glance api service when
configuration files are modified. Operator can send SIGHUP signal to glance
service which will reload the configuration file.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;In a production environment, an administrator will modify the glance-api.conf
configuration parameters like filesystem_store_datadirs when the storage
is almost full to add more capacity by adding more disks, or to increase
the number of workers or log configuration etc. Then they need to restart the
glance services explicitly for these changes to be loaded. Restarting
service would break users connected to it which is not good from users point
of view.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Add the ability to dynamically change configuration settings of a running
glance server with no impact to service.&lt;/p&gt;
&lt;p&gt;A running glance server consists of a parent process and one or
more child processes.&lt;/p&gt;
&lt;p&gt;On receipt of a SIGHUP signal the parent process will:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;reload the configuration&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;send a SIGHUP to the original child processes&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;start new child processes with the new configuration&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;its listening socket will not be closed&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;On receipt of a SIGHUP signal each original child process will:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;close the listening socket so as not to accept new requests&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;complete any in-flight requests&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;exit&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This approach is based on nginx’s behaviour and avoids some of the
disadvantages of the current oslo’s Launcher reload:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Race conditions: Launcher does not shutdown eventlet cleanly, existing
requests can fail.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If all child processes are busy there can be a lengthy delay when new
requests are not processed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Long lived pre-SIGHUP idle client connections can stall request
processing indefinitely.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Not all parameters can be changed, eg number of workers.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The wsgi pipeline cannot be changed, for example to enable caching.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;An alternative may be to attempt to save and then restore long running tasks
using taskflow. The process restart would then only need to deal with
short lived requests (e.g. API DB lookups) and then no user visible downtime
is required for regular restarts&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;If the reload takes too long (e.g., &amp;gt;50ms) then the API requests will be
noticeably delayed.&lt;/p&gt;
&lt;p&gt;We are proposing current worker processes to stop accepting requests and
continue with what they are doing, while the parent process starts and
spawn new child processes with the new configuration. So there is a
possibility that the glance node will be running twice as many child processes
as it is configured to run for a while. It could impact performance,
especially if it is an underpowered node that is already configured to run
as many child processes as it can handle without degradation.&lt;/p&gt;
&lt;p&gt;In the author’s opinion, it is the responsibility of the operator to make sure
the node will not be over-provisioned with child processes (workers). If an
operator wants to run a node with no headroom for additional child processes,
the author suggests that such an operator not use dynamic configuration via
SIGHUP. Instead, such an operator should use the old fashioned technique of
restarting the api service.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;span id="other-deployer"/&gt;&lt;h3&gt;Other deployer impact&lt;/h3&gt;
&lt;p&gt;Need to document the impact of config changes for some params like workers,
host, port etc.&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;stuart-mclaren&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&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="reviewers"&gt;
&lt;h3&gt;Reviewers&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Core reviewer(s):&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;nikhil-komawar
flaper87&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other reviewer(s):&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;icordasc&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 handler for SIGHUP signal&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Reload configuration parameters&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Unit and functional tests for coverage&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;Please refer to &lt;a class="reference internal" href="#other-deployer"&gt;&lt;span class="std std-ref"&gt;Other deployer impact&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;p&gt;&lt;a class="reference external" href="https://etherpad.openstack.org/p/sighup-conf-reload"&gt;https://etherpad.openstack.org/p/sighup-conf-reload&lt;/a&gt;&lt;/p&gt;
&lt;/section&gt;
</description><pubDate>Thu, 09 Oct 2014 00:00:00 </pubDate></item><item><title>Glance Swift Store to use Multiple Containers for Storing Images</title><link>http://specs.openstack.org/openstack/glance-specs/specs/kilo/swift-store-multiple-containers.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/glance/+spec/swift-store-multiple-containers"&gt;https://blueprints.launchpad.net/glance/+spec/swift-store-multiple-containers&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Glance, when configured to use Swift store in Single Tenant Mode, stores
images in one container as indicated by the configuration option,
swift_store_container. This approach of storing images in ONE container
is subject to performance bottleneck.&lt;/p&gt;
&lt;p&gt;Storing images in one container is prone to Swift rate-limiting on
containers. Swift is equipped with container rate-limiting that can throttle
concurrent POST, PUT and DELETE operations in a single container.
This becomes a serious issue in a large scale deployments especially
when coupled with smaller segment sizes.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Swift is known to be capable of throttling incoming traffic[1]. The very fact
that swift can throttle write operations on containers presents a performance
bottleneck and hence large scale deployments need an alternative to get
around Swift throttling.&lt;/p&gt;
&lt;p&gt;When container rate-limiting is enabled for a Swift cluster, it throttles
concurrent POST, PUT and DELETE requests after a certain configurable rate.
This directly translates to a limit on concurrent image creation and deletion
operations for Glance before experiencing performance degradation.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;To reduce/overcome the performance bottleneck, we propose the use of multiple
containers for storing images in Single Tenant Mode (this change will not
affect Multi Tenant Mode because that setup stores each image in its own
container). This leads to increased concurrency of image creation and deletion
operations.&lt;/p&gt;
&lt;p&gt;There are four major aspects to this change:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Container Selection - determining what container an image should go into&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Container Creation - creating the new containers&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Re-distribution of Existing Images - moving images from old to new containers&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Database Migration - updating image locations as per new containers&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;1) Container Selection:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;This change proposes to select containers based on image uuid. Images will be
stored in multiple containers in order to avoid throttling during
multiple simultaneous uploads. The first N characters of the image UUID, where
N is a configurable integer between 1 and 32, the number of hex digits in a
UUID, with the default value of 2, will be used to determine which container
the image will be uploaded to. With the default value of the first two
characters used, this gives 16*16=256 unique containers. At N=1, the smallest
valid value for this configuration, 16 containers will be created and used for
storing images. The containers will be named after the value set for
swift_store_container with the first N chars of the image UUID as the suffix.&lt;/p&gt;
&lt;p&gt;Example: if this config option is set to 3 and
swift_store_container = ‘glance’, then an image with UUID
‘fdae39a1-bac5-4238-aba4-69bcc726e848’ would be placed in the container
‘glance_fda’. All dashes in the UUID are included when creating the container
name but do not count toward the character limit, so in this example with N=10
the container name would be ‘glance_fdae39a1-ba’.&lt;/p&gt;
&lt;p&gt;The number of containers can be easily increased or decreased by changing N in
the configuration. However, a new set of containers will be created with every
change to this configuration. Images created after a configuration change
will go into new containers while older images remain in their previous
containers. The older images do not need to necessarily be moved into new
containers as their locations would still point to the existing older container
they are stored in. This means that changing N in the configuration will
never result in existing containers being deleted. However, if one wishes to
move the older images to new containers, they may do so by re-distributing the
images, which is described later in this section.&lt;/p&gt;
&lt;p&gt;Note: ‘storing’ an image in a container implies storing the manifest and all
the image segments in the same container. Unless otherwise mentioned, this
continues to hold true all through this specification.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2) Container Creation:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Glance ships with a configuration option to dynamically create the container,
if it doesn’t exist already at the time of uploading image data to Swift. This
is indicated by configuration option, swift_store_create_container_on_put. If
dynamic container creation is enabled, Glance would automatically create each
container when the appropriate container for that image is not found.&lt;/p&gt;
&lt;p&gt;However, if the config option for dynamic container creation is disabled, image
uploads would fail if the appropriate containers are not created manually by
the deployer. This behavior is consistent with how Glance currently handles
missing containers if the config option to create them is not enabled.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;3) Re-distribution of Existing Images (out of scope):&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;This spec will not provide code or scripts to migrate existing images since
lazy loading is an existing effective method of distributing new images.
However, if one wants to migrate images here is the process: Once the use of
multiple containers is enabled or the number of containers is changed, all
previously created images would remain in the older container(s). If desired,
older images can be moved to new containers appropriately. This can be achieved
as a separate batch job that can be run as and when desired. Subject to the
number of older images, redistributing images may involve significant movement
of data in the Swift cluster. Hence, it would be helpful to achieve this in
phases and in a non-intrusive fashion. Once the images are re-distributed,
their image locations need to be updated as well.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;4) Database Migration (out of scope):&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;If images are re-distributed by operator choice, image location of each
re-distributed image must be updated to reflect the new container name. This
requires a db migration to replace the old container name in the location with
the new container name as per the image id. This migration can go
hand-in-hand with re-distribution.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Scope of this spec:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Of the four aspects discussed above, this specification only addresses
container creation and selection while leaving re-distribution and the
required db migrations out, which can be implemented as another concerted
effort.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;1) Instead of using image id as the basis for container selection, one can use
other basis like tenant id, which would keep all images belonging to a certain
tenant in the same container. While other container name basis are possible,
using image id provides an easier way to correlate an image to its container.&lt;/p&gt;
&lt;p&gt;2) An alternative to creating containers could be to allow the API to create
all the required containers while it boots up. This requires the API to know
all possible containers before hand, which may or may not be possible depending
upon the container selection basis chosen. This places a certain limitation on
the kind of bases one may opt for. Hence, going with dynamic container creation
will eliminate this limitation as both container selection and creation could
be dynamic. Also, dynamic container creation is in-line with current Glance
behavior.&lt;/p&gt;
&lt;p&gt;3) Instead of grouping multiple images together in a container, one alternative
would be to give each image its own container. However, that doesn’t solve any
problems, it just moves the cardinality issues from the container to the
account. Additionally, some deployers limit the maximum number of containers
allowed per account. White-listing certain accounts to bypass a container limit
would defeat the purpose of swift ratelimits which are chosen by deployers in
order to protect the entire cluster.&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 containers will be created and used for storing images. However, this
does not have any impact on the Glance image data model itself.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Database migrations&lt;/strong&gt;:&lt;/p&gt;
&lt;p&gt;No database migrations are required. The code supporting multiple containers
would only affect the uploading of new images, determining which container they
belong to based on uuid. For existing images (those uploaded before support
for multiple containers), the image already contains a valid location in its
metadata. Essentially, new containers will be populated by lazy loading: When
an image is uploading, it will first check through a HEAD request if the
appropriate container exists for that image based on its UUID, and if the
container does not exist then the container will be created immediately with a
PUT request.  This image will then be the first image stored in that particular
container.&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;Given the scope of this spec, where image data is not being re-distributed
among new containers and no migrations are being run, there is minimal
to no security impact introduced.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;This change only impacts the image location property among all the image
properties. And, since image location is not included in notifications, there
should be no impact to Glance 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;As image location is not accessible to either the end-user or from Glance
client, there should be no 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;The use of multiple containers will reduce throttling when multiple images are
uploaded simultaneously. This leads to increased concurrency of image creation
and deletion operations in large scale deployments.&lt;/p&gt;
&lt;p&gt;Container selection would take place for every image upload request and thus
adds an extra operation to the current set of operations to upload image data.
However, selecting a container would be a simple substring operation to fetch
the first few characters of an image id. The time incurred in determining the
container would be significantly smaller than the time incurred to upload image
data. Overall, the performance impact of container selection should be very
minimal.&lt;/p&gt;
&lt;p&gt;Container creation is a conditional operation that would take place only when
the container is not present already. This would occur once for each
combination of N characters as specified in the configuration.
For example, the default configuration option is that the first 2 characters of
the image UUID are used to select an appropriate container, leading to a total
of 256 containers which should be optimal for mid size deployments. We found
that in a large scale deployment, 4096 containers would be preferred over 256
containers if smaller segment sizes were chosen. The time incurred in creating
a new container is significantly smaller than the time incurred in upload image
data. Hence, the overall performance impact in image uploads should be minimal.&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 would begin taking effect upon enabling multiple containers in a
configuration. When enabled, new images would be uploaded to new containers,
while existing images would remain in their previously assigned container.
This change is forwards and backwards compatible, such that the deployer can
choose to enable or disable multiple containers at any time and images will
still upload and download correctly.&lt;/p&gt;
&lt;p&gt;Deployers should note that if their deployment limits the total number of
containers per account, the seed for the total number of containers should be
set such that this limit is not hit.&lt;/p&gt;
&lt;p&gt;New configuration option in &lt;em&gt;glance-api.conf&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;swift_store_multiple_containers_seed&lt;/strong&gt; - default = 0&lt;/p&gt;
&lt;p&gt;When set to 0, a single-tenant store will only use one container to store all
images. When set to an integer value between 1 and 32, a single-tenant store
will use multiple containers to store images, and this value will determine
how many containers are created. Used only when swift_store_multi_tenant is
disabled. The total number of containers that will be used is approximately
equal to 16^N, so if this config option is set to 2, then 16^2=256 containers
will be used to store images.&lt;/p&gt;
&lt;p&gt;Example: if this config option is set to 3 and
swift_store_container = ‘glance’, then an image with UUID
‘fdae39a1-bac5-4238-aba4-69bcc726e848’ would be placed in the container
‘glance_fda’. All dashes in the UUID are included when creating the container
name but do not count toward the character limit, so in this example with N=10
the container name would be ‘glance_fdae39a1-ba’.&lt;/p&gt;
&lt;p&gt;When choosing the value for swift_store_multiple_containers_seed, deployers
should discuss a suitable value with their swift operations team. The authors
of this spec recommend that large scale deployments use a value of ‘2’, which
will create a maxiumum of ~256 containers. Choosing a higher number than this,
even in extremely large scale deployments, may not have any positive impact
on performance and could lead to a large number of empty, unused containers.
If dynamic container creation is turned off, any value for this configuration
option higher than ‘1’ may be unreasonable as the deployer would have to
manually create each container.&lt;/p&gt;
&lt;p&gt;Any diagnostic/monitoring scripts assuming images to be stored in a single
container may need appropriate changes.&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;hemanth-makkapati&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;ben-roble&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="reviewers"&gt;
&lt;h3&gt;Reviewers&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Core reviewer(s):&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;nikhil-komawar brian-rosmaita&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other reviewer(s):&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;Implement new config options in Swift store driver&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Implement container selection in Swift store driver&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Implement unit, functional, and integration tests&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Change glance-api sample conf in glance repo&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Points to note:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;All code changes would be limited to glance_store module.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Image download code wouldn’t require any changes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Both manifest and segments would go into the same container.&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;No tempest tests needed&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;Document new configuration options&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;[1] &lt;a class="reference external" href="http://docs.openstack.org/developer/swift/ratelimit.html#configuration"&gt;http://docs.openstack.org/developer/swift/ratelimit.html#configuration&lt;/a&gt;&lt;/p&gt;
&lt;/section&gt;
</description><pubDate>Fri, 26 Sep 2014 00:00:00 </pubDate></item><item><title>Refactoring Glance logging</title><link>http://specs.openstack.org/openstack/glance-specs/specs/juno/refactoring-glance-logging.html</link><description>

&lt;p&gt;Glance is currently logging lots of operator relevant information as DEBUG.
Also the logged messages are translated in various ways. I would like to
refactor the whole Glance codebase reflecting the current logging
guidelines [1].&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;OPS are complaining that OpenStack as whole does not utilize the logging
levels appropriately and production implementations needs to run on DEBUG-
level to get needed information out of the logs.&lt;/p&gt;
&lt;p&gt;Glance is logging a lot of operator relevant information as DEBUG. [1]&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;I would like to see whole Glance codebase revisited and the logging changed to
use appropriate logging level and reflect the translation functions to those
levels as well. This would be also good opportunity to ensure that we have no
logging left that would write sensitive information like URIs and credentials
to logfiles.&lt;/p&gt;
&lt;p&gt;Unify the way how exceptions are logged. Exception message should be always
logged if anything to ensure that operators can find the event based on end
user problem description.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;We could implement error codes to differentiate the messages sent to user and
logged having still unique linkage between the two. This would cause more
documentation overhead but provide greater flexibility and granularity.&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 would reinforce the confidence that we do not log sensitive/confidential
information. [2]&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications impact&lt;/h3&gt;
&lt;p&gt;Some notification messages might have minor changes.&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 should not have performance hit outside of the corrected amount of
translation function calls made.&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;Users who have their own logging filtering in place would need to review
those rules after the logging level has been changed.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;The logging on correct levels should make developer life easier when trying
to debug the code.&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;Erno Kuvaja &amp;lt;jokke&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="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Review OpenStack logging guidelines [1][2]&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Review the current logging pattern and make decision where changing the
message content would be appropriate (sensitive data, etc.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Determine the correct logging level message by message and align the
translation functions used on that log level.&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 proposal in the Security Guideline draft [2] to implement some
sanitizing and tagging to oslo. This is not dependency nor should affect
this work other than possible adobtation if the proposed functionality gets
implemented.&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;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;New log level use cases should be documented so deployers would know what to
expect finding from their logs.&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://wiki.openstack.org/wiki/LoggingStandards"&gt;https://wiki.openstack.org/wiki/LoggingStandards&lt;/a&gt;
[2] &lt;a class="reference external" href="https://wiki.openstack.org/wiki/Security/Guidelines/logging_guidelines"&gt;https://wiki.openstack.org/wiki/Security/Guidelines/logging_guidelines&lt;/a&gt;&lt;/p&gt;
&lt;/section&gt;
</description><pubDate>Thu, 12 Jun 2014 00:00:00 </pubDate></item><item><title>Restrict users from downloading image based on custom properties</title><link>http://specs.openstack.org/openstack/glance-specs/specs/juno/restrict-downloading-images.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/glance/+spec/restrict-downloading-images-protected-properties"&gt;https://blueprints.launchpad.net/glance/+spec/restrict-downloading-images-protected-properties&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The goal of this blueprint is to restrict normal users from downloading
the images on the basis of core or custom properties by using
download_image policy.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Presently images shared publicly with the users can download these images
freely which could lead to piracy. Today, you can stop users from downloading
images by configuring download_image policy with role constraint, but it will
restrict all users having that particular role from downloading all of the
images, this is not good. So what I want is to restrict users from downloading
images on the basis of specific core or custom property is present in the
image and users having certain specific roles.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;We can achieve this by adding new rule in policy.json and apply that rule to
‘download_image’ policy.&lt;/p&gt;
&lt;p&gt;For example:
Add new rule in policy.json mentioned as below&lt;/p&gt;
&lt;p&gt;‘restricted’: ‘not (ntt_3251:%(x_billing_code_ntt)s and role:member)’
‘download_image’: ‘role:admin or rule:restricted’&lt;/p&gt;
&lt;p&gt;So if ‘download_image’ policy is enforced then in above case only admin or
user who satisfies rule ‘restricted’ will able to download image. Other users
will not be able to download the image and will get 403 Forbidden response.&lt;/p&gt;
&lt;p&gt;To avoid implementation of dict inspection via dot syntax and enforce the
policy on v1 and v2 api’s in the same way, we can create a dictionary-like
mashup of the image core and custom properties, in both v1
and v2 api and pass it directly as target to _enforce() method. In case if
core and custom property is same for the image, then the core property value
will be overwritten on the custom property.&lt;/p&gt;
&lt;p&gt;For example:
self._enforce(req, ‘download_image’, target=image_meta_mashup)&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Instead of passing dictionary-like mashup of the image core and custom
properties directly to target, we can pass image itself and can implement
dict inspection via dot syntax. In this case the new rule in policy.json
need to configured as follows,&lt;/p&gt;
&lt;p&gt;‘restricted’: ‘not (ntt_3251:%(target.x_billing_code_ntt)s and role:member)’
‘download_image’: ‘role:admin or rule:restricted’&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;ul&gt;
&lt;li&gt;&lt;p&gt;GET:/v2/images/{image_id}/file&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Description: Downloads binary image data.&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;Normal response code(s): 200, 204&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;dl class="simple"&gt;
&lt;dt&gt;Expected error http response code(s): 403&lt;/dt&gt;&lt;dd&gt;&lt;ul&gt;
&lt;li&gt;&lt;p&gt;When image having protected properties downloaded by user
who doesn’t satisfy ‘download_image’ policy&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;URL for the resource: /v2/images/{image_id}/file&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Parameters which can be passed via the url
{image_id}, String, The ID for the image.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GET:/v1/images/{image_id}&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;ul&gt;
&lt;li&gt;&lt;dl class="simple"&gt;
&lt;dt&gt;Description: Returns the image details as headers and the image binary&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;in the body of the response.&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Method: GET&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Normal response code(s): 200&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Expected error http response code(s): 403&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;When image having protected properties downloaded by user
who doesn’t satisfy ‘download_image’ policy&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;URL for the resource: /v1/images/{image_id}&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Parameters which can be passed via the url
{image_id}, String, The ID for the image.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;&lt;/blockquote&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;Need to add new rule in policy.json for restricting downloading of image.&lt;/p&gt;
&lt;p&gt;“restricted”: “not (ntt_3251:%(x_billing_code_ntt)s and role:member)”
“download_image”: “role:admin or rule:restricted”&lt;/p&gt;
&lt;p&gt;Where ntt_3251 will be the value of property ‘x_billing_code_ntt’.&lt;/p&gt;
&lt;p&gt;In our case it is necessary to ensure that normal users should not be able
to delete the property (‘x_billing_code_ntt’) added to the image.
If normal user is able to delete the property of the image then
he can easily download the image as the rule ‘restricted’ will not work
in this case.&lt;/p&gt;
&lt;p&gt;So we need to restrict normal users from deleting the property
using property protections.&lt;/p&gt;
&lt;p&gt;Need to modify following options in glance-api.conf file to enable
property-protections:&lt;/p&gt;
&lt;p&gt;property_protection_file = property-protections-roles.conf
property_protection_rule_format = roles&lt;/p&gt;
&lt;p&gt;Changes in property-protections-roles.conf&lt;/p&gt;
&lt;p&gt;[^x_billing_code_.*]
create = admin,member
read = admin,member,_member_
update = admin,member
delete = admin,member&lt;/p&gt;
&lt;p&gt;Need to ensure that to use this download restrictions feature,
show_image_direct_url and show_multiple_locations parameter is not set
to True in glance-api.conf file.
If these options are True then, using this download restriction is
potentially an inconsistent policy as user might be able to download the
image using image location(direct url).&lt;/p&gt;
&lt;p&gt;In order to deploy the above policy, service provider will need to deploy 2
sets of glance api services. One glance api service will be exposed to the
external nova services(nova-compute) and other to the users. The one which is
exposed to the users should enforce the download_image policy with the above
“restricted” rule and the glance-api which used by nova need to be
isolated/protected, e.g. separated by network, in order to avoid
glance-client/end user connect it by standard API.&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;abhishek-kekane&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 new rule in policy.json to restrict download of image.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add method to create dictionary-like mashup of image properties&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Modify v1 and v2 api to restrict download&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Modify logic of caching to restrict download for v1 and v2 api&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Sync openstack.common.policy of oslo-inc with Glance when the
change of oslo-inc get merged.&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 to add tempest test to cover download operation.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Please refer Other deployer impact.&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 Jun 2014 00:00:00 </pubDate></item></channel></rss>