<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0"><channel><title>oslo-specs</title><link>https://specs.openstack.org/openstack/oslo-specs</link><description /><language>en</language><copyright>2024, OpenStack Foundation</copyright><item><title>Remove Eventlet From oslo.service</title><link>https://specs.openstack.org/openstack/oslo-specs/specs/epoxy/remove-eventlet-from-oslo-service.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/oslo?searchtext=remove-eventlet-from-oslo-service"&gt;https://blueprints.launchpad.net/oslo?searchtext=remove-eventlet-from-oslo-service&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Oslo.service provides a framework for defining long-running services.
To achieve that goal, oslo.service rely on Eventlet and its coroutines.&lt;/p&gt;
&lt;p&gt;Eventlet is the heart of oslo.service.&lt;/p&gt;
&lt;p&gt;However, the removal of Eventlet from Openstack is now a &lt;a class="reference external" href="https://review.opendev.org/c/openstack/governance/+/902585"&gt;fact&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Removing Eventlet from oslo.service is now mandatory.&lt;/p&gt;
&lt;p&gt;This specification aims to design the removal of eventlet from oslo.service.&lt;/p&gt;
&lt;p&gt;The goal of this document is:
1. to identify alternatives to the Eventlet features currently used by oslo.service;
2. to define how to put in place those alternatives;
3. to define the various milestone needed to properly remove Eventlet;
4. to minimize the impact for oslo.service’s users.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;The removal of Eventlet is now a &lt;a class="reference external" href="https://review.opendev.org/c/openstack/governance/+/902585"&gt;fact&lt;/a&gt;.
The official Eventlet project will be retired in a near future and the
Openstack T.C officially accepted the community goal proposed to retire
Eventlet from the Openstack runtime.&lt;/p&gt;
&lt;p&gt;The main features provided by oslo.service are:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;loopingcall&lt;/span&gt;&lt;/code&gt;: a module to run a method in a loop;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;periodic&lt;/span&gt; &lt;span class="pre"&gt;task&lt;/span&gt;&lt;/code&gt;: periodic tasks that can be run in a separate process;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;service&lt;/span&gt;&lt;/code&gt;: a service manager that can handle workers;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;wsgi&lt;/span&gt;&lt;/code&gt;: an utility to create and launch wsgi server;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;systemd&lt;/span&gt;&lt;/code&gt;: an helper module for systemd service readiness notification;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;threadgroup&lt;/span&gt;&lt;/code&gt;: an helper to create a group of greenthreads and timers.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The problem is that oslo.service heavily rely on Eventlet.
All the oslo.service features listed below are based on Eventlet:&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;loopingcall&lt;/span&gt;&lt;/code&gt;;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;periodic&lt;/span&gt; &lt;span class="pre"&gt;task&lt;/span&gt;&lt;/code&gt;;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;service&lt;/span&gt;&lt;/code&gt;;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;wsgi&lt;/span&gt;&lt;/code&gt;;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;threadgroup&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In parallel of that, oslo.service also provide side features like:&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;eventlet_backdoor&lt;/span&gt;&lt;/code&gt;;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;fixture&lt;/span&gt;&lt;/code&gt;;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;sslutils&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These side feature are strongly linked to behavioral mechanisms of Eventlet
and are not strictly speaking features of oslo.service.&lt;/p&gt;
&lt;p&gt;So if we want to remove Eventlet from oslo.service we have to identify
what to do with the modules listed below:&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;loopingcall&lt;/span&gt;&lt;/code&gt;;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;periodic&lt;/span&gt; &lt;span class="pre"&gt;task&lt;/span&gt;&lt;/code&gt;;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;service&lt;/span&gt;&lt;/code&gt;;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;wsgi&lt;/span&gt;&lt;/code&gt;;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;threadgroup&lt;/span&gt;&lt;/code&gt;;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;eventlet_backdoor&lt;/span&gt;&lt;/code&gt;;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;fixture&lt;/span&gt;&lt;/code&gt;;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;sslutils&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We must identify if all these module could be rewritten by using alternatives
and if the usage of these alternatives would impact the existing API of
oslo.service (additional parameter, default value, etc).&lt;/p&gt;
&lt;p&gt;We must decide:
- how to transition from the current version of oslo.service
to the future version of oslo.service, a version free from Eventlet.
- if the future version of oslo.service will again provide all of
these features or if we should remove some of them in the process.&lt;/p&gt;
&lt;p&gt;If we decide to remove existing feature, then we must decide how transition
our consumers.&lt;/p&gt;
&lt;p&gt;In all the case, at some point will would have to release major version of
oslo.service where the backward compatibility will be definitely broken.&lt;/p&gt;
&lt;p&gt;That document aim to answer all these questions.&lt;/p&gt;
&lt;section id="constraints"&gt;
&lt;h3&gt;Constraints&lt;/h3&gt;
&lt;p&gt;For the sake of consistency we have to define a couple of constrains. The
goal of these constraints is to keep the migration as transparent as possible
for consumers.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;we cannot abruptly remove Eventlet, so, for all the previously described
oslo.service features, both implementations will have to cohabit, the
Eventlet version, and the new one;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;at the oslo.service’s consumers level, the transition must be as smooth as
possible. Meaning that consumers should not have to rewrite all their imports
to continue using the Eventlet based implementation, or the new version.
Some oslo.service modules may be abandoned, only those imports would have
to be removed if imported at the consumers level;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;consumers must decide when to switch from an implementation to an other;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;the removal of the Eventlet implementation should not impact the consumers
in a random way. If a feature is explicitly removed from oslo.service, then
an alternative must be documented in a migration guide specific to
oslo.service. Customers must be informed by deprecation warning of the
removal of the features;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;non-actively maintained deliverables must not be broken by the removal
of the Eventlet implementation;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;non-actively maintained deliverables must not block indefinitely the
removal of the Eventlet implementation. If such case is identified, then
the Pop Up team dedicated to the migration must be informed of this problem.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;section id="features-triagging"&gt;
&lt;h3&gt;Features triagging&lt;/h3&gt;
&lt;p&gt;Again, here are the main modules provided by oslo.service:&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;loopingcall&lt;/span&gt;&lt;/code&gt;;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;periodic&lt;/span&gt; &lt;span class="pre"&gt;task&lt;/span&gt;&lt;/code&gt;;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;service&lt;/span&gt;&lt;/code&gt;;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;wsgi&lt;/span&gt;&lt;/code&gt;;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;threadgroup&lt;/span&gt;&lt;/code&gt;;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;systemd&lt;/span&gt;&lt;/code&gt;;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;eventlet_backdoor&lt;/span&gt;&lt;/code&gt;;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;fixture&lt;/span&gt;&lt;/code&gt;;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;sslutils&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Each module is more or less a feature.&lt;/p&gt;
&lt;p&gt;As said previously, some modules are specific to Eventlet:&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;eventlet_backdoor&lt;/span&gt;&lt;/code&gt;: backdoor made to attach an Eventlet based process;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;fixture&lt;/span&gt;&lt;/code&gt;: a fixture for mocking the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;wait()&lt;/span&gt;&lt;/code&gt;;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;sslutils&lt;/span&gt;&lt;/code&gt;: specific Eventlet wrapper for ssl.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For this reason, the new implementation won’t re-implement these modules.
These modules will be simply removed from the new implementation.&lt;/p&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;wsgi&lt;/span&gt;&lt;/code&gt; module is based on a the &lt;a class="reference external" href="https://eventlet.readthedocs.io/en/latest/examples.html#wsgi-server"&gt;Eventlet wsgi server&lt;/a&gt; for
this reason, we also propose to remove that module from the new
implementation.&lt;/p&gt;
&lt;p&gt;We want to encourage consistency across projects. It is crucial to avoid
having multiple ways to start services across different projects. A unified
approach will simplify maintenance and enhance user experience.
We don’t want projects looking/running different.
For this reason we advocate for the adoption of one or two of the following
packages which could be credible alternatives to the Eventlet WSGI module
exposed by oslo.service:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;cite&gt;uWSGI &amp;lt;https://uwsgi-docs.readthedocs.io/en/latest/&amp;gt;&lt;/cite&gt;: synchronous WSGI
server well tested and OpenStack context. Threads based;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;cite&gt;uvicorn &amp;lt;https://pypi.org/project/uvicorn/&amp;gt;&lt;/cite&gt;: an ASGI web server
implementation for Python;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;cite&gt;asgiref &amp;lt;https://pypi.org/project/asgiref/&amp;gt;&lt;/cite&gt;: allow to wrap or decorate
async or sync functions to call them from the other style (so you can call
async functions from a synchronous thread, or vice-versa).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This way we will have an unified approach for all our deliverables. This
approach is compatible with both world (sync, and async).&lt;/p&gt;
&lt;p&gt;Both libraries are well and actively maintained by many developers.&lt;/p&gt;
&lt;p&gt;At the application layer, we advocate for the usage of
&lt;cite&gt;FastAPI &amp;lt;https://pypi.org/project/fastapi/&amp;gt;&lt;/cite&gt; which is
also compatible with both worlds (sync and async), and which is actively
maintained by hundred of people. FastAPI is coming a mainstream library
heavily used in the AI realm, so we think that it is a credible alternative
a long life ahead of him. The considerations about the application layer are
a bit out of the current topic though and or are given here with the sake of
giving tracks for discussions.&lt;/p&gt;
&lt;p&gt;The following modules will remains and would have to be transitioned:&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;loopingcall&lt;/span&gt;&lt;/code&gt;;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;periodic&lt;/span&gt; &lt;span class="pre"&gt;task&lt;/span&gt;&lt;/code&gt;;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;service&lt;/span&gt;&lt;/code&gt;;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;threadgroup&lt;/span&gt;&lt;/code&gt;;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;systemd&lt;/span&gt;&lt;/code&gt;;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The implementation of the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;systemd&lt;/span&gt;&lt;/code&gt; module seems to be a CPython vanilla
implementation, so it may remains untouched.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="how-to-proceed"&gt;
&lt;h3&gt;How to proceed?&lt;/h3&gt;
&lt;p&gt;Oslo.service cannot be transitioned in one time. We propose to introduce the
notion of backend into oslo.service to allow the usage of both implementation
in parallel.&lt;/p&gt;
&lt;p&gt;Backend will allow to implement the new version of oslo.service while keeping
the existing version handy.&lt;/p&gt;
&lt;p&gt;The backend will simplify the life of users during the transition.&lt;/p&gt;
&lt;p&gt;We propose the following milestones to juggle between implementations
and with the notion of backend:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;(SLURP) 2025.1: move the current implementation into an &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;eventlet&lt;/span&gt;&lt;/code&gt; backend
(the default backend in the config);&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;(SLURP) 2025.1: implement the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;threading&lt;/span&gt;&lt;/code&gt; backend;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;(NON-SLURP) 2025.2: deprecate the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;eventlet&lt;/span&gt;&lt;/code&gt; backend and make
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;threading&lt;/span&gt;&lt;/code&gt; the default;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;(NON-SLURP) 2026.2: remove the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;eventlet&lt;/span&gt;&lt;/code&gt; implementation and move the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;threading&lt;/span&gt;&lt;/code&gt; implementation at the root level, and remove the backend
notion.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Actually oslo.service is a flatten module. All its sub-modules are
at the root level. Meaning that users imports the features they needs from
the root level of the oslo.service module, 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="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;oslo_service&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;wsgi&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;oslo_service&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;service&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;oslo_service&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;loopingcall&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;If we do not introduce the backend notion, all the Openstack services using
oslo.service will have to rewrite all their imports at least twice. The first
time when they will be eager to use the new implementation:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;oslo_service.threading&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;service&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;and the second one when the old implementation will be removed, and, hence,
when the new implementation will be moved at the root level:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;oslo_service&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;service&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;This is not an acceptable scenario because it will lead to many useless back
and forth at the import level, without any additional added value for the
users.&lt;/p&gt;
&lt;p&gt;Usaging backends will hide the complexity of this swapping into oslo.service.
Users won’t suffer from changing their imports again and again.&lt;/p&gt;
&lt;p&gt;Actually, oslo.service looks like to:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;oslo_service
├── eventlet_backdoor.py
├── fixture.py
├── _i18n.py
├── __init__.py
├── locale
│   └── .. (ignored)
├── loopingcall.py
├── _options.py
├── periodic_task.py
├── service.py
├── sslutils.py
├── systemd.py
├── tests
│   └── .. (ignored)
├── threadgroup.py
├── version.py
└── wsgi.py
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Once the backend will be added the structure of oslo.service will looks like
to:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;oslo_service
├── backends
│   ├── eventlet
│   │   ├── eventlet_backdoor.py
│   │   ├── fixture.py
│   │   ├── __init__.py
│   │   ├── loopingcall.py
│   │   ├── periodic_task.py
│   │   ├── service.py
│   │   ├── sslutils.py
│   │   ├── threadgroup.py
│   │   └── wsgi.py
│   └── threading
│       ├── __init__.py
│       ├── loopingcall.py
│       ├── periodic_task.py
│       ├── service.py
│       └── threadgroup.py
├── eventlet_backdoor.py
├── fixture.py
├── _i18n.py
├── __init__.py
├── locale
│   └── .. (ignored)
├── loopingcall.py
├── _options.py
├── periodic_task.py
├── service.py
├── sslutils.py
├── systemd.py
├── tests
│   └── .. (ignored)
├── threadgroup.py
├── version.py
└── wsgi.py
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Each root sub-module will simply import the right backend conditionally,
example with the service sub-module:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;_options&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;backend&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;"threading"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;oslo_service.threading&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;service&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt;
    &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;oslo_service.eventlet&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;service&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;If a sub-module do not exists in the new implementation, then the root level
sub-module will use debtcollector &lt;a class="reference external" href="https://docs.openstack.org/debtcollector/latest/user/usage.html#deprecating-anything-else"&gt;to emit a deprecation warning&lt;/a&gt;
and give instruction to users, example with the wsgi sub-module:&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;debtcollector&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;deprecate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s2"&gt;"""&lt;/span&gt;
&lt;span class="s2"&gt;    The WSGI module is no longer supported&lt;/span&gt;
&lt;span class="s2"&gt;    You see this deprecation warning because you are importing&lt;/span&gt;
&lt;span class="s2"&gt;    the oslo.service wsgi module. This module is deprecated and will&lt;/span&gt;
&lt;span class="s2"&gt;    be soon removed. Please consider using uwsgi and consider following&lt;/span&gt;
&lt;span class="s2"&gt;    the migration path described here:&lt;/span&gt;
&lt;span class="s2"&gt;    https://docs.openstack.org/oslo.service/latest/migration/wsgi.html&lt;/span&gt;
&lt;span class="s2"&gt;    ",&lt;/span&gt;
&lt;span class="s2"&gt;    version="1.0"&lt;/span&gt;
&lt;span class="s2"&gt;)&lt;/span&gt;
&lt;span class="s2"&gt;if _options.backend == "eventlet":&lt;/span&gt;
&lt;span class="s2"&gt;    from oslo_service.eventlet import service&lt;/span&gt;
&lt;span class="s2"&gt;else&lt;/span&gt;
&lt;span class="s2"&gt;    raise ImportError("WSGI module not found in the threading backend...")&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Concerning the modules conserved in the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;threading&lt;/span&gt;&lt;/code&gt; implementation, they
will be rewritten by using new underlying libraries, like cotyledon, futurist,
and threading/concurrent from the stdlib. See the dependency and API section
for more details about the usage of these new libraries.&lt;/p&gt;
&lt;p&gt;If a sub-module is not impacted by the Eventlet removal and so not
re-implemented, then it could remains at the root level. That’s by example
the case of the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;systemd&lt;/span&gt;&lt;/code&gt; sub-module, which in our previous tree example
remains at the root level.&lt;/p&gt;
&lt;p&gt;If a consumers do not move its oslo.service backend to the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;threading&lt;/span&gt;&lt;/code&gt;
backend in the allotted time, then the T.C should be warned. Then the T.C will
surely inform the Pop Up team created to manage the whole Eventlet removal.
In this case, the Pop Up team may decide to migrate this deliverable or could
propose to retire it if nobody actively maintain it.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;It would be also possible to entirely deprecate oslo.service and to point
the available alternatives into the deprecation warnings, therefore,
leaving the charge of the refactor to the consumers.&lt;/p&gt;
&lt;p&gt;The problem of this approach is that it would surely spring various approaches
and so a diversity of solution.&lt;/p&gt;
&lt;p&gt;The motivation behind the creation of the Oslo projects was to uniformize the
solutions and to reduce the technical debt.&lt;/p&gt;
&lt;p&gt;If we delegate the refactor to oslo.service consumers it will lead to an
increase of this technical debt.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="impact-on-existing-apis"&gt;
&lt;h3&gt;Impact on Existing APIs&lt;/h3&gt;
&lt;section id="the-temporary-backends"&gt;
&lt;h4&gt;The temporary backends&lt;/h4&gt;
&lt;p&gt;The existing API will be modified to introduce the temporary backends.
Backends will remains private module not directly importable
by consumers. One or the other backend will be imported by the classic
import and by choosing one backend or the other in the config.&lt;/p&gt;
&lt;p&gt;The public API will remains almost the same until the Eventlet backend is not
removed.&lt;/p&gt;
&lt;p&gt;Once the Eventlet backend will be removed, then the public API related
to Eventlet will be also removed, see the next section.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="removed-sub-modules"&gt;
&lt;h4&gt;Removed sub-modules&lt;/h4&gt;
&lt;p&gt;Once the migration will be terminated, the backend notion will be removed
and the new implementation will be moved at the root level, meaning
that once the migration will be done, oslo.service will looks like to:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;oslo_service
├── _i18n.py
├── __init__.py
├── locale
│   └── .. (voluntary ignored)
├── loopingcall.py
├── _options.py
├── periodic_task.py
├── service.py
├── systemd.py
├── tests
│   └── .. (voluntary ignored)
├── threadgroup.py
└── version.py
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The following modules won’t exists anymore, and so won’t be anymore
importable:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;wsgi&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;eventlet_backdoor&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;fixture&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;sslutils&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;During the time the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;backends&lt;/span&gt;&lt;/code&gt; notion will be present, users will face
import errors until the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;wsgi&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;eventlet_backdoor&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;fixture&lt;/span&gt;&lt;/code&gt;,
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;sslutils&lt;/span&gt;&lt;/code&gt; modules are removed from the user codebase. Indeed, it is
useless to implement a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;NotImplemented&lt;/span&gt;&lt;/code&gt; interface as in all the case
users will have to remove them.&lt;/p&gt;
&lt;p&gt;And the transient &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;backends&lt;/span&gt;&lt;/code&gt; sub-module and its content, will be also
removed.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="periodic-task"&gt;
&lt;h4&gt;Periodic task&lt;/h4&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;periodic_task&lt;/span&gt;&lt;/code&gt; sub-module will become a proxy for
the futurist library.&lt;/p&gt;
&lt;p&gt;The oslo.service &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;periodic_task&lt;/span&gt;&lt;/code&gt; sub-module provide the following
abstractions to manage periodical tasks:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://docs.openstack.org/oslo.service/latest/reference/periodic_task.html#oslo_service.periodic_task.periodic_task"&gt;oslo_service.periodic_task.periodic_task&lt;/a&gt;
which represent a periodical task;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://docs.openstack.org/oslo.service/latest/reference/periodic_task.html#oslo_service.periodic_task.PeriodicTasks"&gt;oslo_service.periodic_task.PeriodicTasks&lt;/a&gt;
which is a manager for periodical tasks (one to many). Could be seen as a
worker where we attach callable to run periodically.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Futurist define the following methods and class to manage periodic tasks:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://docs.openstack.org/futurist/latest/reference/index.html#futurist.periodics.PeriodicWorker"&gt;futurist.periodics.PeriodicWorker&lt;/a&gt;
which allow to call a collection of callable periodically. This is a worker
where we attach callable to run periodically;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://docs.openstack.org/futurist/latest/reference/index.html#futurist.periodics.periodic"&gt;futurist.periodics.periodic&lt;/a&gt;
which allow to tag a method/function as wanting/able to execute periodically;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://docs.openstack.org/futurist/latest/reference/index.html#futurist.periodics.Watcher"&gt;futurist.periodics.Watcher&lt;/a&gt;
which is a read-only object representing a periodic callback’s activities.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So the following bindings are proposed to use oslo.service as a proxy of
futurist:&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;oslo_service.periodic_task.periodic_task&lt;/span&gt;&lt;/code&gt; will be bound with
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;futurist.periodics.periodic&lt;/span&gt;&lt;/code&gt;;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo_service.periodic_task.PeriodicTasks&lt;/span&gt;&lt;/code&gt; will be bound with
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;futurist.periodics.PeriodicWorker&lt;/span&gt;&lt;/code&gt;;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As our goal is to keep the existing oslo.service API as intact as possible,
we propose to ignore the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;futurist.periodics.Watcher&lt;/span&gt;&lt;/code&gt; class.&lt;/p&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;futurist.periodics.periodic&lt;/span&gt;&lt;/code&gt; implement the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;enabled&lt;/span&gt;&lt;/code&gt; notion. That
option do not exists in oslo.service. Indeed in oslo.service a periodic task
is disabled if the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;spacing&lt;/span&gt;&lt;/code&gt; parameter is set to a negative number. In this
case, if this number is negative on oslo.service, then, we will have to set
the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;enabled&lt;/span&gt;&lt;/code&gt; parameter of futurist to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;False&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Futurist periodic tasks &lt;a class="reference external" href="https://docs.openstack.org/futurist/latest/reference/index.html#periodics"&gt;accept an executor parameter&lt;/a&gt;.
Futurist &lt;a class="reference external" href="https://docs.openstack.org/futurist/latest/user/features.html#async"&gt;define different kind of executors&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;We should provide a way to choose the kind of executor that futurist will
use, for this reason, we will have to implement an abstraction to this notion
to offer to users a way to select one.&lt;/p&gt;
&lt;p&gt;Futurist provide an executor based on Eventlet. As our goal is to
remove Eventlet we won’t provide access to this executor at the oslo.service
level.&lt;/p&gt;
&lt;p&gt;Oslo.service will only allow to use/select the following futurist executors:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;futurist.ProcessPoolExecutor&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;futurist.SynchronousExecutor&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;futurist.ThreadPoolExecutor&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="service"&gt;
&lt;h4&gt;Service&lt;/h4&gt;
&lt;p&gt;To implement the new version of the oslo.service’ service sub-module we
propose to use Cotyledon.&lt;/p&gt;
&lt;p&gt;The Cotyledon module provide the following public API:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://cotyledon.readthedocs.io/en/latest/api.html#cotyledon.Service"&gt;cotyledon.Service&lt;/a&gt;:
base class for a service;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://cotyledon.readthedocs.io/en/latest/api.html#cotyledon.ServiceManager"&gt;cotyledon.ServiceManager&lt;/a&gt;:
manage lifetimes of services.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Where service sub-module of oslo.service provide the following public API:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://docs.openstack.org/oslo.service/latest/reference/service.html#oslo_service.service.Launcher"&gt;oslo_service.service.Launcher&lt;/a&gt;:
launch one or more services and wait for them to complete;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://docs.openstack.org/oslo.service/latest/reference/service.html#oslo_service.service.ProcessLauncher"&gt;oslo_service.service.ProcessLauncher&lt;/a&gt;:
launch a service with a given number of workers;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://docs.openstack.org/oslo.service/latest/reference/service.html#oslo_service.service.Service"&gt;oslo_service.service.Service&lt;/a&gt;:
service object for binaries running on hosts;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://docs.openstack.org/oslo.service/latest/reference/service.html#oslo_service.service.ServiceBase"&gt;oslo_service.service.ServiceBase&lt;/a&gt;:
base class for all services;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://docs.openstack.org/oslo.service/latest/reference/service.html#oslo_service.service.ServiceLauncher"&gt;oslo_service.service.ServiceLauncher&lt;/a&gt;:
runs one or more service in a parent process;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://docs.openstack.org/oslo.service/latest/reference/service.html#oslo_service.service.launch"&gt;oslo_service.service.launch&lt;/a&gt;:
launch a service with a given number of workers.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We propose the following bindings:&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;oslo_service.service.Launcher&lt;/span&gt;&lt;/code&gt; will delegate to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cotyledon.ServiceManager&lt;/span&gt;&lt;/code&gt;;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo_service.service.ServiceLauncher&lt;/span&gt;&lt;/code&gt; will delegate to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cotyledon.ServiceManager&lt;/span&gt;&lt;/code&gt;;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo_service.service.Service&lt;/span&gt;&lt;/code&gt; will delegate to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cotyledon.Service&lt;/span&gt;&lt;/code&gt;;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo_service.service.launch&lt;/span&gt;&lt;/code&gt; and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo_service.service.ProcessLauncher&lt;/span&gt;&lt;/code&gt; will remains more or less with
the same logic that is currently implemented, less the monkey patching of
Eventlet.&lt;/p&gt;
&lt;p&gt;Unlike oslo.service cotyledon allow only one service workers manager run at a
time. Oslo.service allow to run more than one Service launcher at a time.
This difference should be documented.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="loopingcall-threadgroup"&gt;
&lt;h4&gt;Loopingcall &amp;amp; threadgroup&lt;/h4&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;loopingcall&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;threadgroup&lt;/span&gt;&lt;/code&gt; modules are based on greenthreads,
so we have to re-implement them. We propose to use the CPython &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;threading&lt;/span&gt;&lt;/code&gt;
module to refactor them.&lt;/p&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;loopingcall&lt;/span&gt;&lt;/code&gt; seems to simply needs threads to run methods in loop.&lt;/p&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;threadgroup&lt;/span&gt;&lt;/code&gt; use eventlet green pool to manage group of threads. Again
the stdlib &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;threading&lt;/span&gt;&lt;/code&gt; module offer ways to attach threads to a defined
group. Possibly it would also require the usage of &lt;a class="reference external" href="https://docs.python.org/3/library/concurrent.futures.html#concurrent.futures.ThreadPoolExecutor"&gt;ThreadPoolExecutor&lt;/a&gt;
to allow asynchronous behavior.&lt;/p&gt;
&lt;p&gt;These 2 sub-modules should not be really impacted by API changes. Only the
internal mechanisms will change and the public API will surely remains the
same.&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;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;Removing Eventlet would mean moving, in some circumstances, to a native
threading model. Eventlet is based on cooperative coroutines provided by
greenlet, when cotyledon, or even futurist, uses threads, who are preemptive.&lt;/p&gt;
&lt;p&gt;Threads tend to be more expensive and slower than coroutines because they
involve context switching. OS will continue to share CPU operations with
all the threads even if they are not ready to works (network IO, etc).&lt;/p&gt;
&lt;p&gt;Indeed, depending on the number of workers allocated to services or periodic
tasks, in a context with a lot of threading concurrency, threads can degrade
the flow rate of the machine. This is linked to context-switching which is
resource-intensive.&lt;/p&gt;
&lt;p&gt;Threads are preemptive so compared to cooperative coroutines, they are more
prone to lead to race condition.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="configuration-impact"&gt;
&lt;h3&gt;Configuration Impact&lt;/h3&gt;
&lt;p&gt;This topic will impact the configuration in numerous ways.
The first impact will be related to the addition of a new config option
to allow switching the implementation. Switching the backend to use.&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;oslo_service_backend&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;eventlet&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;This new option will named &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo_service_backend&lt;/span&gt;&lt;/code&gt; and it will be a
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cfg.StrOpt&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;It will propose the following choices as valid settings:&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;choices&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'eventlet'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'threading'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;And it will defaulted to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;eventlet&lt;/span&gt;&lt;/code&gt;, and users
will move this value to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;threading&lt;/span&gt;&lt;/code&gt; when they will have cleaned-up the usage
of oslo.service deprecated sub-modules from their code base.&lt;/p&gt;
&lt;p&gt;This option will be removed once the deprecation period will be over.&lt;/p&gt;
&lt;p&gt;As said previously, using the backend notion, and so this option will allow
internal transients states within oslo.service, allowing us to swap the
internal implementations.&lt;/p&gt;
&lt;p&gt;The existing configuration related to the wsgi module and to the sslutils
of oslo.service will be removed once the swapping will be done, as these
sub-modules will be retired.&lt;/p&gt;
&lt;p&gt;In a first time these config sections (wsgi, sslutils) will be fully deprecated
to warn the user that they have to stop using it.&lt;/p&gt;
&lt;p&gt;We should also deprecate the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;backdoor_socket&lt;/span&gt;&lt;/code&gt; and the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;backdoor_port&lt;/span&gt;&lt;/code&gt;
from the default config section, as the eventlet_backdoor module will be
removed, as so, these options will be also removed once the swapping will
be done.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer Impact&lt;/h3&gt;
&lt;p&gt;Removing Eventlet from oslo.service would allow side works, like:
- removing the mutex tricks oslo.log;
- removing the greenlet/eventlet executor from futurist.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing-impact"&gt;
&lt;h3&gt;Testing Impact&lt;/h3&gt;
&lt;p&gt;As the current tests also relies on Eventlet and on monkey patching, all
the new implementation should also introduce its own tests.&lt;/p&gt;
&lt;p&gt;The existing tests should remains, and the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tests&lt;/span&gt;&lt;/code&gt; directory structure
should reflect the new module tree with both backends.&lt;/p&gt;
&lt;p&gt;The tests of the removal and the of the deprecation will be at the charge
of the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;eventlet&lt;/span&gt;&lt;/code&gt; backend. We do not want to pollute the new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;threading&lt;/span&gt;&lt;/code&gt;
implementation with obsolete artifacts.&lt;/p&gt;
&lt;p&gt;Oslo.service do not implement functional tests, so this refactor won’t add
ones.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Hervé Beraud (hberaud)&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="milestones"&gt;
&lt;h3&gt;Milestones&lt;/h3&gt;
&lt;p&gt;Target Milestone for completion:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;(SLURP) 2025.1: move the current implementation into an &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;eventlet&lt;/span&gt;&lt;/code&gt; backend
(the default backend in the config);&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;(SLURP) 2025.1: implement the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;threading&lt;/span&gt;&lt;/code&gt; backend;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;(NON-SLURP) 2025.2: deprecate the eventlet backend and make &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;threading&lt;/span&gt;&lt;/code&gt; the
default;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;(NON-SLURP) 2026.2: remove the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;eventlet&lt;/span&gt;&lt;/code&gt; implementation and move the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;threading&lt;/span&gt;&lt;/code&gt; implementation at the root level, and remove the backend
notion.&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;create an &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;eventlet&lt;/span&gt;&lt;/code&gt; sub-module to host the existing implementation
and plug the root level sub-modules to this new module&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;create a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;threading&lt;/span&gt;&lt;/code&gt; sub-module to host the new implementation
and add a new backend config defaulting to the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;eventlet&lt;/span&gt;&lt;/code&gt; sub-module&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;deprecate the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;eventlet&lt;/span&gt;&lt;/code&gt; sub-module&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;default the backend config to the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;threading&lt;/span&gt;&lt;/code&gt; implementation&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;remove the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;eventlet&lt;/span&gt;&lt;/code&gt; sub-module and remove the backend config option&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;move the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;threading&lt;/span&gt;&lt;/code&gt; implementation at the root level&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;As the notion of backend will be added, to different documentation
will cohabit for both implementations of the same sub-module.&lt;/p&gt;
&lt;p&gt;The documentation structure will reflect the oslo.service module:&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;doc&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;source&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;backends&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The new option allowing to swap the implementation will be documented.&lt;/p&gt;
&lt;p&gt;Each new implementation will have to specify its specificity at the
docstring level.&lt;/p&gt;
&lt;p&gt;The documentation should also provide a migration guide to give guidance
about the removed sub-module.&lt;/p&gt;
&lt;p&gt;Each time a specific deprecation warning is emitted from a sub-module,
the deprecation message should give a link that refer to the right
section of this migration guide.&lt;/p&gt;
&lt;p&gt;This migration guide will be hosted into the following path:&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;doc&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;source&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;migration&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;This specific migration guide should at least document the
removals of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo_service.wsgi&lt;/span&gt;&lt;/code&gt; and give tracks to follow (WSGI/ASGI (uwsgi,
uvicorn, etc), application layer (flask, etc), HTTP…). This part of the
documentation will follow the standards defined by &lt;a class="reference external" href="https://wiki.openstack.org/wiki/Eventlet-removal#The_HTTP_SGI_Working_Group"&gt;the HTTP SGI working group&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The other removed sub-modules which are specific to Eventlet (
eventlet_backdoor, fixture, etc…) won’t have to be documented.&lt;/p&gt;
&lt;p&gt;Once the Eventlet backend will be removed, this migration will be also
removed from the documentation.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;We propose to create two &lt;a class="reference external" href="https://docs.openstack.org/pbr/latest/user/using.html#environment-markers"&gt;extra environment markers&lt;/a&gt;.
One related the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;eventlet&lt;/span&gt;&lt;/code&gt; backend and one for the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;threading&lt;/span&gt;&lt;/code&gt; backend.
They would avoid installing useless packages and help to reduce the size
of packaging and disk size. By example, if the user decide to use the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;threading&lt;/span&gt;&lt;/code&gt; package, we do not need building a container that doesn’t
require &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;eventlet&lt;/span&gt;&lt;/code&gt; to be in it. Indeed, in many place the existence of
eventlet triggers a behavior change, avoid installing eventlet will reduce
the chance of facing this kind of situation.&lt;/p&gt;
&lt;p&gt;The extra environment markers will looks like too:&lt;/p&gt;
&lt;div class="highlight-cfg notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="k"&gt;[extras]&lt;/span&gt;
&lt;span class="na"&gt;eventlet&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="na"&gt;eventlet&amp;gt;&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;0.36.1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;# MIT&lt;/span&gt;
&lt;span class="na"&gt;threading&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="na"&gt;futurist&amp;gt;&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;3.0.0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;# Apache-2.0&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="na"&gt;cotyledon&amp;gt;&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;1.7.3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;# Apache-2.0&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;See the section below for further details and context about &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;futurist&lt;/span&gt;&lt;/code&gt; and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cotyledon&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;section id="id2"&gt;
&lt;h3&gt;Periodic task&lt;/h3&gt;
&lt;p&gt;For the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;periodic&lt;/span&gt; &lt;span class="pre"&gt;task&lt;/span&gt;&lt;/code&gt; module, we propose to use &lt;a class="reference external" href="https://docs.openstack.org/futurist/latest/"&gt;Futurist&lt;/a&gt; to replace Eventlet.
Indeed, Futurist is a library that provide periodic tasks management.&lt;/p&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo_service.periodic_task&lt;/span&gt;&lt;/code&gt; module will began a proxy of futurist.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="id3"&gt;
&lt;h3&gt;Service&lt;/h3&gt;
&lt;p&gt;&lt;a class="reference external" href="https://github.com/sileht/cotyledon"&gt;Cotyledon&lt;/a&gt; was created years ago
to offer an alternative to the Service module of oslo.service. An alternative
free from Eventlet. We propose to use cotyledon as underlying library for
the new implementation of the Service module of oslo.service.&lt;/p&gt;
&lt;p&gt;In other words, the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo_service.service&lt;/span&gt;&lt;/code&gt; module will began a proxy of
cotyledon.&lt;/p&gt;
&lt;/section&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/governance/+/902585"&gt;https://review.opendev.org/c/openstack/governance/+/902585&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This work is licensed under a Creative Commons Attribution 3.0
Unported License.
&lt;a class="reference external" href="http://creativecommons.org/licenses/by/3.0/legalcode"&gt;http://creativecommons.org/licenses/by/3.0/legalcode&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
</description><pubDate>Thu, 14 Nov 2024 00:00:00 </pubDate></item><item><title>Enable By Files Healthcheck Plugin</title><link>https://specs.openstack.org/openstack/oslo-specs/specs/dalmatian/enable_by_files_healthcheck_plugin.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/oslo.middleware/+spec/enable-by-files-healthcheck"&gt;https://blueprints.launchpad.net/oslo.middleware/+spec/enable-by-files-healthcheck&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;A generic healthcheck plugin to verify specific file path is available.&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 does 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;/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 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;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,/var/lib/glance/cache (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 addition we will also add a check to verify if both backends i.e.
&lt;cite&gt;disable_by_file&lt;/cite&gt; or &lt;cite&gt;enable_by_files&lt;/cite&gt; are mentioned then we will
raise appropriate exception which will exit the process with
failure.&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="impact-on-existing-apis"&gt;
&lt;h3&gt;Impact on Existing APIs&lt;/h3&gt;
&lt;p&gt;This new healthcheck plugin is exactly opposite of existing plugin
&lt;cite&gt;disable_by_file&lt;/cite&gt;. So operator needs to make sure that &lt;cite&gt;disable_by_file&lt;/cite&gt;
plugin should not be configured along with &lt;cite&gt;enable_by_files&lt;/cite&gt; plugin.&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="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="configuration-impact"&gt;
&lt;h3&gt;Configuration Impact&lt;/h3&gt;
&lt;p&gt;The middleware needs to be configured as shown in &lt;cite&gt;Proposed Change&lt;/cite&gt;
section.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer Impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing-impact"&gt;
&lt;h3&gt;Testing Impact&lt;/h3&gt;
&lt;p&gt;Middleware will be covered by the unittest
And also have a tempest test for each services that have integrated it.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;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 (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="milestones"&gt;
&lt;h3&gt;Milestones&lt;/h3&gt;
&lt;p&gt;Target Milestone for completion:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Dalmatian-3&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;Write the &lt;cite&gt;enable_by_files&lt;/cite&gt; healthcheck plugin&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update the applications to use it&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;N/A&lt;/p&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="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Glance NFS improvement spec - &lt;a class="reference external" href="https://review.opendev.org/917284"&gt;https://review.opendev.org/917284&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;EnableByFiles plugin PoC - &lt;a class="reference external" href="https://review.opendev.org/919666"&gt;https://review.opendev.org/919666&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This work is licensed under a Creative Commons Attribution 3.0
Unported License.
&lt;a class="reference external" href="http://creativecommons.org/licenses/by/3.0/legalcode"&gt;http://creativecommons.org/licenses/by/3.0/legalcode&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
</description><pubDate>Fri, 17 May 2024 00:00:00 </pubDate></item><item><title>http driver</title><link>https://specs.openstack.org/openstack/oslo-specs/specs/epoxy/http-driver.html</link><description>

&lt;p&gt;This is a proposal to create a new driver implementation which communicates
RPC client and server directly over HTTP without messaging queue.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;In oslo.messaging, RabbitMQ driver is widely used and validated that
the driver works very stably on most of OpenStack environment.
However, in PUB/SUB model using message queue, message queue itself
might be a single point of failure and also message queue is bit
difficult to support large scale of client and server communications.&lt;/p&gt;
&lt;p&gt;For example, if there are more than 10,000 hypervisors which host
nova-compute and neutron-agent, each RabbitMQ node must always support
large number (ex. more than 40,000) of network connections from nova
and neutron clients. In this situation, if RabbitMQ cluster restart
happens, large number of RPC clients started to connect RabbitMQ nodes
simultaneously, this makes RabbitMQ nodes unstable.&lt;/p&gt;
&lt;p&gt;Also due to large number of hypervisors, RabbitMQ must support huge
number of message queues to allow to communicate neutron-server and
neutron-agent, for example. All queue data must be synchronized between
all RabbitMQ nodes, so having large number of queue also makes RabbitMQ
cluster unstable.&lt;/p&gt;
&lt;p&gt;Note, this is not a proposal to deny RabbitMQ (PUB/SUB model) backend.
The proposal should be aware both PUB/SUB model and REQ/RESP model have
different advantages described in the following section.&lt;/p&gt;
&lt;section id="pub-sub-advantage-examples"&gt;
&lt;h3&gt;PUB/SUB advantage examples&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Simple architecture in a small cluster&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Easy ACL configuration in a secure cluster&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="req-resp-advantage-examples"&gt;
&lt;h3&gt;REQ/RESP advantage examples&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Fault tolerant against control plane (consul) down&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Easy to scale out the cluster&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As mentioned in above, the PUB/SUB model has simple and easy to use
most of the cases, but for large scale OpenStack environment, REQ/RESP
model for all RPC communications could be more proper and reliable.&lt;/p&gt;
&lt;p&gt;This specification proposes to implement OpenAPI based REQ/RESP model
driver called &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;http&lt;/span&gt; &lt;span class="pre"&gt;driver&lt;/span&gt;&lt;/code&gt; which enable to communicates between RPC
client to RPC server directly without a component which is single point
of failure for OpenStack internal communication.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;This is overview diagram of HTTP driver for RPC Call/Cast/Cast Fanout requests.
There are 4 main components to realize the driver.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;RPC client&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;RPC server&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Endpoint datastore (ex. Consul)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Broadcaster&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight-none notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;              +--------------+
      +------&amp;gt;|   Consul     |&amp;lt;------------------+
      |       +--------------+                   |
      |                                     +-------------+
      |                                +---&amp;gt;|  RPC server |
      |                                |    +-------------+
+-------------+   Call/Cast RPC        |    +-------------+
| RPC client  +---------------------------&amp;gt; |  RPC server |
+-------------+                        |    +-------------+
      |                                |    +-------------+
      | Cast Fanout                    +---&amp;gt;|  RPC server |
      |                                |    +-------------+
      |       +--------------+         |
      +------&amp;gt;| Broadcaster  |---------+
              +--------------+
           Send Cast to all RPC servers
&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;Scope of the proposal&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;The scope of this proposal covers Call/Cast/Cast Fanout RPC cases&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Notification is out of scope in this proposal&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;section id="main-points-to-be-improved-by-the-architecture"&gt;
&lt;h3&gt;Main points to be improved by the architecture&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Separate control plane from data plane&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Allow direct API call without single point of failure&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Reduce RPC communication between multiple availability zones&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Responsibility of each components like followings.&lt;/p&gt;
&lt;section id="rpc-client"&gt;
&lt;h4&gt;RPC Client&lt;/h4&gt;
&lt;p&gt;Fetch the RPC server list from the consul cluster for
an RPC target service.
Pick up appropriate RPC server for the RPC, then send a RPC request
over HTTP protocol.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rpc-server"&gt;
&lt;h4&gt;RPC Server&lt;/h4&gt;
&lt;p&gt;Listen and handle an in-coming rpc request over HTTP protocol&lt;/p&gt;
&lt;p&gt;When the RPC server starts, the server registers its RPC server
information to Consul cluster as Consul’s “service”.
Also the PRC Server works as &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Push&lt;/span&gt; &lt;span class="pre"&gt;Style&lt;/span&gt;&lt;/code&gt;, not poll style.&lt;/p&gt;
&lt;p&gt;For RPC client/server communication over HTTP with RESTful API, OpenAPI
allows us to define formatted RESTful API definition easily. Once API
definition is generated, it can be launched as http server using
Web framework and WSGI server. For example, they are candidate for Web
framework and WSGI server to enable HTTP client and server.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Web famework: &lt;a class="reference external" href="https://connexion.readthedocs.io/en/latest/"&gt;connexion&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;WSGI server: eventlet&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="endpoint-datastore"&gt;
&lt;h4&gt;Endpoint datastore&lt;/h4&gt;
&lt;p&gt;Store the RPC server information.&lt;/p&gt;
&lt;p&gt;The server information includes following items.
oslo.messaging layer information(exchange, topic and server)
RPC server information (IP address, port and etc).&lt;/p&gt;
&lt;p&gt;In this spec, &lt;a class="reference external" href="https://developer.hashicorp.com/consul/api-docs"&gt;Consul&lt;/a&gt;
is one example imeplementation for the endpoint datastore.&lt;/p&gt;
&lt;p&gt;For other use-case, the service discovery feature code with backend
selectable implementation should be added for users who would like
to avoid introducing new dependency for datastore.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="http-broadcaster"&gt;
&lt;h4&gt;HTTP Broadcaster&lt;/h4&gt;
&lt;p&gt;An amplifier for an HTTP request&lt;/p&gt;
&lt;p&gt;HTTP protocol doesn’t have broadcast mechanism though the oslo
RPC has Cast Fanout RPC.
The Broadcaster sends an in-coming RPC to all target RPC servers.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="sample-rpc-communication-flow-for-nova"&gt;
&lt;h3&gt;Sample RPC communication flow for Nova&lt;/h3&gt;
&lt;div class="highlight-none notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;              +--------------+
      +------&amp;gt;|   Consul     |
      |       +--------------+
      |
      |             * Call RPC
+----------------+  (1) select_destinations    +----------------+
| nova-conductor +---------------------------&amp;gt; | nova-scheduler |
|                +------+                      +----------------+
+----------------+      | * Cast RPC
                        | (2) build_and_run_instance
                        |                      +----------------+
                        +---------------------&amp;gt;|  nova-compute  |
                                               +----------------+
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;In this figure, nova-conductor on left side is RPC client and each
nova-scheduler and nova-compute on right side are RPC servers.&lt;/p&gt;
&lt;section id="select-destinations-call-rpc"&gt;
&lt;h4&gt;select_destinations() Call RPC&lt;/h4&gt;
&lt;p&gt;During instance creation, in order to choose target nova-compute
node to launch new instance, nova-conductor make a Call RPC request
select_destinations() to nova-scheduler.
In this case, Call RPC communication works with following steps.&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;A nova-conductor fetches nova-scheduler’s hostn and port
port information from Consul, and pick one of Call RPC
target randomly&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A nova-conductor makes a select_destinations() Call RPC and
wait a response.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
&lt;section id="build-and-run-instance-cast-rpc"&gt;
&lt;h4&gt;build_and_run_instance() Cast RPC&lt;/h4&gt;
&lt;p&gt;During instance creation, once target nova-compute is choosen by
scheduler, nova-conductor sends instance creation request to
target nova-compute using build_and_run_instance() Cast RPC.
In this case, Cast RPC communication works with following steps.&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;A nova-conductor fetches a target nova-compute’s host and
port information from Consul&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A nova-conductor makes a build_and_run_instance() Cast RPC and
return immediately without waiting actual instance creation&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="sample-rpc-server-information-registered-in-consul"&gt;
&lt;h3&gt;Sample RPC server information registered in Consul&lt;/h3&gt;
&lt;section id="nova-s-rpc-server-information"&gt;
&lt;h4&gt;Nova’s RPC server information&lt;/h4&gt;
&lt;p&gt;This figure shows Nova’s RPC server information registered into &lt;cite&gt;nova&lt;/cite&gt; AZ.
Nova has nova.scheduler, nova-conductor, nova-compute and nova-consoleauth
as RPC server.&lt;/p&gt;
&lt;a class="reference internal image-reference" href="../../_images/consul-service-list.png"&gt;&lt;img alt="../../_images/consul-service-list.png" class="align-left" src="../../_images/consul-service-list.png" style="width: 850px;"/&gt;
&lt;/a&gt;
&lt;/section&gt;
&lt;section id="nova-condutor-rpc-server-list"&gt;
&lt;h4&gt;nova-condutor RPC server list&lt;/h4&gt;
&lt;p&gt;This figure shows nova-conductor RPC server list on &lt;cite&gt;nova&lt;/cite&gt; AZ.
Each nova-conductor has &amp;lt;service name&amp;gt;:&amp;lt;port number&amp;gt; and also
&amp;lt;IP address&amp;gt;:&amp;lt;port number&amp;gt; identifier. RPC client access to
RPC server via the &amp;lt;IP address&amp;gt;:&amp;lt;port number&amp;gt;.&lt;/p&gt;
&lt;a class="reference internal image-reference" href="../../_images/conductor-service-list.png"&gt;&lt;img alt="../../_images/conductor-service-list.png" class="align-left" src="../../_images/conductor-service-list.png" style="width: 850px;"/&gt;
&lt;/a&gt;
&lt;/section&gt;
&lt;section id="health-check-status-of-one-of-nova-condutor-rpc-server"&gt;
&lt;h4&gt;Health check status of one of nova-condutor RPC server&lt;/h4&gt;
&lt;p&gt;Consul has health check mechanism for registered HTTP endpoint.
The figure shows one of nova-conductor RPC server respond 200 OK
to Consul’s periodical health check. If the endpoint is healthy,
the endpoint marked as green check.&lt;/p&gt;
&lt;a class="reference internal image-reference" href="../../_images/conductor-health-check.png"&gt;&lt;img alt="../../_images/conductor-health-check.png" class="align-left" src="../../_images/conductor-health-check.png" style="width: 850px;"/&gt;
&lt;/a&gt;
&lt;/section&gt;
&lt;section id="multi-az-support"&gt;
&lt;h4&gt;Multi-AZ support&lt;/h4&gt;
&lt;p&gt;Consul has a feature to federate multiple Consul cluster into one to
support multiple datacenter case. In the figure, there are multiple
nova AZ such as &lt;cite&gt;nova&lt;/cite&gt;, &lt;cite&gt;az-1&lt;/cite&gt;, &lt;cite&gt;az-2&lt;/cite&gt; and &lt;cite&gt;az-3&lt;/cite&gt;, then each nova AZ
has one Consul cluster. These 4 Consule clusters are manged as one
cluster using Consul federation.&lt;/p&gt;
&lt;a class="reference internal image-reference" href="../../_images/consul-federation.png"&gt;&lt;img alt="../../_images/consul-federation.png" class="align-left" src="../../_images/consul-federation.png" style="width: 850px;"/&gt;
&lt;/a&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h2&gt;Alternatives&lt;/h2&gt;
&lt;section id="datastore-for-host-topic-management"&gt;
&lt;h3&gt;Datastore for host/topic management&lt;/h3&gt;
&lt;p&gt;In above architecture, Consul is chosen because it supports healthcheck
mechanism and multi DC federation so that these features enable user to
monitor RPC server status easily, and scale out easily to support large
scale OpenStack.&lt;/p&gt;
&lt;p&gt;But alternatively, managing service endpoint using Keystone service
catalog, DNS or registering data into Redis cluster similar to ZeroMQ
are another choices.&lt;/p&gt;
&lt;p&gt;Once the endpoint datastore supports selectable mechanism, these
alternative datasotre plugin can be developped based on use-cases.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="cast-fanout-support-design"&gt;
&lt;h3&gt;Cast Fanout support design&lt;/h3&gt;
&lt;p&gt;In above diagram, broadcaster process is splitted out as one another
service from RPC client. The Cast Fanout could be implemented into
RPC client, but it takes much CPU and memory if number of targets are
quite huge. Instead, by splitting out the broadcaster, the user easily
scale out number of broadcaster processes based on number targets on
OpenStack cluster.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="api-framework"&gt;
&lt;h3&gt;API framework&lt;/h3&gt;
&lt;p&gt;For API schema definition, any approaches are available.
For example, there are REST, OpenAPI, json-rpc, gRPC or any http
protocol implementation are available if it allow to integrated with
eventlet which is used by oslo.service.
In above diagram, OpenAPI is chosen in order to realize HTTP protocol
client-server model.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="advanced-feature"&gt;
&lt;h2&gt;Advanced feature&lt;/h2&gt;
&lt;section id="multi-availability-zones-support"&gt;
&lt;h3&gt;Multi Availability zones support&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Consul provides Federation mechanism between multiple Consul clusters.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;By using the Federation, Consul cluster can be splitted per OpenStack
Availability zones.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Splitting Consul to multiple cluster reduces workload of Consul and makes
the cluster stable.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Also in basic, RPC client and server communication happen in one Availability
zone. This reduces network communication between multiple AZ.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight-none notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;Availability Zone-A                Availability Zone-B
+----------------+                 +----------------+
|                |   RPC Request   |                |
|   RPC server   |        +-------&amp;gt;+   RPC server   |
|       |        |        |        |       |        |
|       |        |        |        |       |        |
|   RPC client   +--------+        |   RPC client   |
|       |        |                 |       |        |
|       |        |   Federation    |       |        |
| Consul Cluster +&amp;lt;---------------&amp;gt;+ Consul Cluster |
|                |                 |                |
+----------------+                 +----------------+
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="impact-on-existing-apis"&gt;
&lt;h3&gt;Impact on Existing APIs&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;OpenAPI supports SSL based communication between client and server.
This enables secure RPC communication same as other messaging drivers.&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;Performance should become better because RPC client communicates to
RPC server directly over HTTP.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="configuration-impact"&gt;
&lt;h3&gt;Configuration Impact&lt;/h3&gt;
&lt;p&gt;New config options to configure http server are needed.
Here is sample config parameters which is defined in oslo.messaging
library user configuration file like nova.conf, neutron.conf.&lt;/p&gt;
&lt;div class="highlight-ini notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="k"&gt;[oslo_messaging_http]&lt;/span&gt;
&lt;span class="na"&gt;port_range&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;20000:20100&lt;/span&gt;

&lt;span class="k"&gt;[consul]&lt;/span&gt;
&lt;span class="na"&gt;port&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;8500&lt;/span&gt;
&lt;span class="na"&gt;host&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;&amp;lt;Consul hostname&amp;gt;&lt;/span&gt;
&lt;span class="na"&gt;token&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;&amp;lt;Consul token&amp;gt;&lt;/span&gt;
&lt;span class="na"&gt;check_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;60s&lt;/span&gt;
&lt;span class="na"&gt;check_deregister&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;30m&lt;/span&gt;

&lt;span class="k"&gt;[http_driver]&lt;/span&gt;
&lt;span class="na"&gt;http_token&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;&amp;lt;Token to access OpenAPI server&amp;gt;&lt;/span&gt;
&lt;span class="na"&gt;http_api_config_file&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;&amp;lt;OpenAPI definition&amp;gt;&lt;/span&gt;
&lt;span class="na"&gt;enable_ssl&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;True&lt;/span&gt;
&lt;span class="na"&gt;ssl_certfile&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;&amp;lt;Path for SSL Cert file&amp;gt;&lt;/span&gt;
&lt;span class="na"&gt;ssl_keyfile&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;&amp;lt;Path for SSL Key file&amp;gt;&lt;/span&gt;
&lt;span class="na"&gt;listen_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;60&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;section id="detailed-design-for-port-range"&gt;
&lt;h4&gt;Detailed design for port_range&lt;/h4&gt;
&lt;p&gt;For port_range, following spec could reduce complexity of this option.&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;If the port_range is not defined, unused ephemeral port is chosen randomly.
For most of use cases, this satisfies the requirement.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If the port_range is defined, RPC server pick port from the specified range
during service launch.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Here is the reason why multiple ports are required for RPC server.
For example, Nova has “conductor.workers” config parameter and Neutron-server
has “rpc_workers” config parameter. By specifying more than “1” for these configs,
multiple RPC workers are launched on single host. Therefore, from RPC client-server
communication perspective, each RPC worker must have individual destination port
number to launch it on a host.&lt;/p&gt;
&lt;p&gt;And purpose of port_range is to support secure cloud environment which strictly
manages network communication using dest/source port at firewall, it would be better
that default behavior is random choice from unused ephemeral port.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer Impact&lt;/h3&gt;
&lt;p&gt;If other OpenStack component use http rpc_backend, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo_messaging_http&lt;/span&gt;&lt;/code&gt;,
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;consul&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;http_driver&lt;/span&gt;&lt;/code&gt; configuration section must be defined based
on Consul and OpenAPI configuration.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing-impact"&gt;
&lt;h3&gt;Testing Impact&lt;/h3&gt;
&lt;p&gt;Basic unit test and integration test (using DevStack) will be implemented.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Mitsuhiro Tanino (mitsuhiro-tanino)&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Xiang Wang&lt;/p&gt;
&lt;p&gt;Yushiro Furukawa (y-furukawa-2)&lt;/p&gt;
&lt;p&gt;Masahito Muroi (masahito-muroi)&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="milestones"&gt;
&lt;h3&gt;Milestones&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Propose driver and test codes&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Release note and docs&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;The http driver documentation will be added to the library.
This documentation will follow the style of documentation provided by the
other drivers and should include the following topics:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Overview of http driver architecture&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;pre-requisites&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;driver options overview&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Consul configuration&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;HTTP broadcaster configuration&lt;/p&gt;&lt;/li&gt;
&lt;/ul&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="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This work is licensed under a Creative Commons Attribution 3.0
Unported License.
&lt;a class="reference external" href="http://creativecommons.org/licenses/by/3.0/legalcode"&gt;http://creativecommons.org/licenses/by/3.0/legalcode&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
</description><pubDate>Fri, 22 Mar 2024 00:00:00 </pubDate></item><item><title>local notification driver</title><link>https://specs.openstack.org/openstack/oslo-specs/specs/zed/unix-socket-oslo-messaging-notifications-driver.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/oslo.messaging/+spec/unix-socket-oslo-messaging-notifications-driver"&gt;https://blueprints.launchpad.net/oslo.messaging/+spec/unix-socket-oslo-messaging-notifications-driver&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Exporting oslo notifications via a local Unix socket.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Today, if you have two daemons/agents on the same host and one wants
to consume notifications from the other there is no practical driver
that can be used which does not require non-local networking,
complex setup or misuse of multiple feature to emulate a local notification
driver.&lt;/p&gt;
&lt;p&gt;As an operator, I would like to be able to locally consume notifications
with minimal configuration, overhead, or maintenance.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;To address this gap this spec proposes adding a minimal Unix socket driver
which will relay all notification to any subscriber to the socket.&lt;/p&gt;
&lt;p&gt;To keep resource utilization and complexity to a minimum the Unix-socket driver
will not queue notification if there are no clients and will instead drop all
notifications&lt;/p&gt;
&lt;p&gt;Multiple client can either be supported by using multiple instance of the
driver or multiplexing over a single socket.&lt;/p&gt;
&lt;p&gt;As with the log driver the Unix socket driver will serialize the message to
JSON.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;An operator could abuse the notification log driver to emit notification to the
Python logging system and then use a Python log handler to redirect the log
stream for the notification topic to a Unix socket.&lt;/p&gt;
&lt;p&gt;An operator could use AMQP with a local or remote message bus.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="impact-on-existing-apis"&gt;
&lt;h3&gt;Impact on Existing APIs&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. Simple filesystem users and groups will provide security for the socket.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None. This is expected to have little overhead similar to the Python log
driver.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="configuration-impact"&gt;
&lt;h3&gt;Configuration Impact&lt;/h3&gt;
&lt;p&gt;A new config options to specify the socket URI will be provided by the driver.
This will be required if using the driver.&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;[oslo_messaging_notifications]&lt;/span&gt;
&lt;span class="na"&gt;sock_path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/run/&amp;lt;service&amp;gt;/notifications.sock&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer Impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing-impact"&gt;
&lt;h3&gt;Testing Impact&lt;/h3&gt;
&lt;p&gt;The test surface is expected to be small and simple unit and functional tests
will be provided in line with the logging driver. Integration testing via a
dedicated DevStack-based job is not planned, although an existing job could
perhaps be extended to also enable it if required.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;sean-k-mooney&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="milestones"&gt;
&lt;h3&gt;Milestones&lt;/h3&gt;
&lt;p&gt;Target Milestone for completion: milestone 2&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 driver&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add tests&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Release note and docs&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Profit&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Documentation impact will be limited to the config options and release notes&lt;/p&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="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This work is licensed under a Creative Commons Attribution 3.0
Unported License.
&lt;a class="reference external" href="http://creativecommons.org/licenses/by/3.0/legalcode"&gt;http://creativecommons.org/licenses/by/3.0/legalcode&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
</description><pubDate>Thu, 28 Apr 2022 00:00:00 </pubDate></item><item><title>So You Want to Contribute…</title><link>https://specs.openstack.org/openstack/oslo-specs/specs/policy/contributing.html</link><description>

&lt;p&gt;For general information on contributing to OpenStack, please check out the
&lt;a class="reference external" href="https://docs.openstack.org/contributors/"&gt;contributor guide&lt;/a&gt; to get started.
It covers all the basics that are common to all OpenStack projects: the accounts
you need, the basics of interacting with our Gerrit review system, how we
communicate as a community, etc.&lt;/p&gt;
&lt;p&gt;Below will cover the more project specific information you need to get started
with Oslo, which includes all of the projects listed on
&lt;a class="reference external" href="https://wiki.openstack.org/wiki/Oslo#Libraries"&gt;the Oslo wiki&lt;/a&gt;.&lt;/p&gt;
&lt;section id="communication"&gt;
&lt;h2&gt;Communication&lt;/h2&gt;
&lt;p&gt;IRC: #openstack-oslo on OFTC&lt;/p&gt;
&lt;p&gt;Mailing list: Messages tagged with [oslo] on
&lt;a class="reference external" href="http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-discuss"&gt;openstack-discuss&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Meeting: Weekly. Full details on
&lt;a class="reference external" href="http://eavesdrop.openstack.org/#Oslo_Team_Meeting"&gt;eavesdrop&lt;/a&gt;&lt;/p&gt;
&lt;/section&gt;
&lt;section id="contacting-the-core-team"&gt;
&lt;h2&gt;Contacting the Core Team&lt;/h2&gt;
&lt;p&gt;See &lt;a class="reference external" href="https://wiki.openstack.org/wiki/Oslo#The_Oslo_Team"&gt;The Oslo Team&lt;/a&gt; on
the wiki.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="new-feature-planning"&gt;
&lt;h2&gt;New Feature Planning&lt;/h2&gt;
&lt;p&gt;Oslo uses a spec process for major new features. See details
&lt;a class="reference external" href="https://wiki.openstack.org/wiki/Oslo#Design_Proposals"&gt;on the wiki&lt;/a&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="task-tracking"&gt;
&lt;h2&gt;Task Tracking&lt;/h2&gt;
&lt;p&gt;We track our tasks in Launchpad.&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://bugs.launchpad.net/oslo"&gt;https://bugs.launchpad.net/oslo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Each individual library also has its own Launchpad project.&lt;/p&gt;
&lt;p&gt;If you’re looking for some smaller, easier work item to pick up and get started
on, search for the ‘low-hanging-fruit’ tag.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="reporting-a-bug"&gt;
&lt;h2&gt;Reporting a Bug&lt;/h2&gt;
&lt;p&gt;You found an issue and want to make sure we are aware of it? You can do so on
&lt;a class="reference external" href="https://bugs.launchpad.net/oslo"&gt;Launchpad&lt;/a&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="how-to-contribute"&gt;
&lt;h2&gt;How to contribute&lt;/h2&gt;
&lt;p&gt;If you would like to contribute to the development of OpenStack, you must
follow the steps in this page:&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://docs.openstack.org/infra/manual/developers.html"&gt;https://docs.openstack.org/infra/manual/developers.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Once those steps have been completed, changes to OpenStack should be submitted
for review via the Gerrit tool, following the workflow documented at:&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://docs.openstack.org/infra/manual/developers.html#development-workflow"&gt;https://docs.openstack.org/infra/manual/developers.html#development-workflow&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Pull requests submitted through GitHub will be ignored.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="getting-your-patch-merged"&gt;
&lt;h2&gt;Getting Your Patch Merged&lt;/h2&gt;
&lt;p&gt;In general, Oslo requires 2 +2’s in order to merge a patch. Under some
circumstances a single +2 may be sufficient. This is generally reserved for
repetitive patches such as trivial tox changes that have been pre-approved by
the team. Some other circumstances (such as gate blocking bugs) may call for
single approval at the discretion of the core team.&lt;/p&gt;
&lt;p&gt;Unit tests are preferred for changes that are not already covered by existing
unit tests, and will usually help patches merge more quickly.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="project-team-lead-duties"&gt;
&lt;h2&gt;Project Team Lead Duties&lt;/h2&gt;
&lt;p&gt;PTL duties are documented in the
&lt;a class="reference external" href="https://specs.openstack.org/openstack/oslo-specs/specs/policy/ptl.html"&gt;Oslo PTL Guide&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;All common PTL duties are enumerated in the &lt;a class="reference external" href="https://docs.openstack.org/project-team-guide/ptl.html"&gt;PTL guide&lt;/a&gt;.&lt;/p&gt;
&lt;/section&gt;
</description><pubDate>Mon, 19 Jul 2021 00:00:00 </pubDate></item><item><title>Migrate Default Policy Format from JSON to YAML</title><link>https://specs.openstack.org/openstack/oslo-specs/specs/victoria/policy-json-to-yaml.html</link><description>

&lt;p&gt;A combination of factors has resulted in problems with deprecating policies.
We need to make some changes in order to allow policy deprecation without
causing pain to OpenStack deployers.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;There is an intersection of a few separate but related things that are causing
pain when deprecating policies:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Packagers like to generate a sample policy for users to reference as they
configure a service.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;oslo.policy still defaults the filename of the policy file to policy.json
for backward compatibility reasons. This encourages packages to generate
a JSON sample policy file, which is not what we want.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Generating a sample policy file in JSON results in all the policy-in-code
rules being overridden because it is not possible to comment out the default
rules in JSON.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Because of the above, when a policy rule is deprecated in a service, users who
have a JSON sample policy file will have the new rule applied immediately on
upgrade. This does not give them a chance to deal with the change, as intended
by the deprecation mechanism in oslo.policy (which would ordinarily apply an
OR operation on the old rule and the new rule to ensure environments relying
on the old rule will continue to work).&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;We want to officially deprecate JSON file format support and switch the
oslo.policy default to YAML.&lt;/p&gt;
&lt;p&gt;In order to do this, we will need careful coordination with consumers of
oslo.policy. It is dangerous to change the default value for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;policy_file&lt;/span&gt;&lt;/code&gt;
without making every effort to communicate the change to deployers. If a
deployer misses this change, it is possible that their custom policy may fail
to be applied, creating significant security problems.&lt;/p&gt;
&lt;p&gt;The proposal made here is for each project to add an upgrade check that will
look for a JSON-formatted policy file and fail if one is found. Once a project
has this check in place, they can use
&lt;a class="reference external" href="https://opendev.org/openstack/oslo.policy/src/branch/master/oslo_policy/opts.py#L121"&gt;set_defaults&lt;/a&gt;
to change the default value for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;policy_file&lt;/span&gt;&lt;/code&gt; to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;policy.yaml&lt;/span&gt;&lt;/code&gt;. A release
note about the change should be added to each project as well.&lt;/p&gt;
&lt;p&gt;To facilitate this migration, we should write a tool to migrate an existing
policy to YAML. The tool would make the format change, and it should also
comment out any rules that match the default from policy-in-code. Only rules
that have actually been customized by the deployer should be present in the
resulting file. We may be able to use the
&lt;a class="reference external" href="https://opendev.org/openstack/oslo.policy/src/branch/master/oslo_policy/generator.py#L389"&gt;oslopolicy-policy-upgrade&lt;/a&gt;
tool to do this.&lt;/p&gt;
&lt;p&gt;In parallel we can officially deprecate JSON format support in oslo.policy.
If we detect that a JSON file is in use for policy we should log a warning.
Support for JSON in CLI tools will also need to be deprecated.&lt;/p&gt;
&lt;p&gt;We may also want to make existence of a JSON file a hard error on the
oslo.policy side. We could provide a flag that services can set once they have
completed their migration to YAML. If that flag is set and we find a
policy.json file that would be a fatal error and stop the service from even
starting. That would prevent us from silently opening security holes in a
deployment.&lt;/p&gt;
&lt;p&gt;A related change that is not strictly necessary for changing the default file
format, but would further improve the deprecation process, is to add a runtime
check for redundant rules in a policy file. This would provide the same
functionality as
&lt;a class="reference external" href="https://docs.openstack.org/oslo.policy/latest/cli/index.html#oslopolicy-list-redundant"&gt;oslopolicy-list-redundant&lt;/a&gt;.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Leave things as they are and try to communicate better that deployers should
be using YAML. This was essentially the original plan around policy-in-code
and it has obviously not been effective.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="impact-on-existing-apis"&gt;
&lt;h3&gt;Impact on Existing APIs&lt;/h3&gt;
&lt;p&gt;Support for policy files in JSON format will be deprecated.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;Policy has a significant security impact so we need to be very careful with
how we make this change. It will require coordination with Oslo consumers
to ensure we make the change in the safest way possible.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None in the short term. When JSON support is removed we will be able to stop
checking for JSON formatted files which may slightly improve performance when
reading policy files.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="configuration-impact"&gt;
&lt;h3&gt;Configuration Impact&lt;/h3&gt;
&lt;p&gt;The default value for the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;policy_file&lt;/span&gt;&lt;/code&gt; option in oslo.policy will change
from &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;policy.json&lt;/span&gt;&lt;/code&gt; to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;policy.yaml&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer Impact&lt;/h3&gt;
&lt;p&gt;Each project will need an upgrade check to warn users who still have a JSON
policy file present.&lt;/p&gt;
&lt;p&gt;Each project will need to override the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;policy_file&lt;/span&gt;&lt;/code&gt; default once they have
added an upgrade check.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing-impact"&gt;
&lt;h3&gt;Testing Impact&lt;/h3&gt;
&lt;p&gt;We will want to come up with a test matrix covering all the possible cases we
may encounter. For example, deployers may have:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;policy.json&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;policy.yaml&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;both policy.json and policy.yaml&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;a JSON file at a custom path&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;a YAML file at a custom path&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We need to make sure to test all of those to ensure we do the right thing.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;gmann&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;???&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="milestones"&gt;
&lt;h3&gt;Milestones&lt;/h3&gt;
&lt;p&gt;Target Milestone for completion:&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;Coordinate with other projects to add upgrade checks and change the default
for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;policy_file&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Provide a tool to convert existing policy files to YAML, preferrably with
functionality to comment out any rules from the original file that match the
default from policy-in-code.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Once all projects have upgrade checks in place, change the default for
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;policy_file&lt;/span&gt;&lt;/code&gt; in oslo.policy so all future projects will have the correct
default.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Deprecate JSON support in oslo.policy.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Deprecate JSON output in policy CLI tools.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Release notes to warn deployers about this will be important. Per-project
documentation advising against JSON may also be helpful. Note that the
oslo.policy docs already recommend using YAML over JSON.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;We will need all projects to have upgrade checks in place in order to safely
change this default.&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.opendev.org/p/oslo-victoria-topics"&gt;Oslo Victoria Virtual PTG Etherpad&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 work is licensed under a Creative Commons Attribution 3.0
Unported License.
&lt;a class="reference external" href="http://creativecommons.org/licenses/by/3.0/legalcode"&gt;http://creativecommons.org/licenses/by/3.0/legalcode&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
</description><pubDate>Thu, 04 Jun 2020 00:00:00 </pubDate></item><item><title>Switching oslo.vmware’s backing SOAP library</title><link>https://specs.openstack.org/openstack/oslo-specs/specs/victoria/oslo-vmware-soap-library-switch.html</link><description>

&lt;p&gt;We want to switch the SOAP library used in olso.vmware to another library,
&lt;a class="reference external" href="https://python-zeep.readthedocs.io/en/master/"&gt;zeep&lt;/a&gt;, because the
currently-used library (&lt;a class="reference external" href="https://bitbucket.org/jurko/suds"&gt;suds-jurko&lt;/a&gt;) is
unmaintained, not compatible with Python 3.10 and lacks in performance.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;With Python 2 being removed from all of OpenStack, we need the library backing
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo.vmware&lt;/span&gt;&lt;/code&gt;’s SOAP calls to be compatible with Python 3. We see
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;suds-jurko&lt;/span&gt;&lt;/code&gt; as being unmaintained &lt;a class="reference external" href="https://bitbucket.org/jurko/suds/commits/"&gt;upstream&lt;/a&gt;, so we cannot rely on any changes
happening. Since we currently already see deprecation warnings generated by
nova’s tests for Python 3.6, we need a fix before the release of Python 3.10 or
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo.vmware&lt;/span&gt;&lt;/code&gt; will stop working alltogether.&lt;/p&gt;
&lt;p&gt;Additionally, the vast number of VMs handled by a single compute-node with
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova&lt;/span&gt;&lt;/code&gt;’s VMware driver makes &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;suds-jurko&lt;/span&gt;&lt;/code&gt; a performance bottleneck. This
can be overcome with switching to a library more optimized for parsing XML.&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 change the backing library of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo.vmware&lt;/span&gt;&lt;/code&gt; to &lt;a class="reference external" href="https://python-zeep.readthedocs.io/en/master/"&gt;zeep&lt;/a&gt;. The library is&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Still maintained&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Written for Python 2 and 3&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Uses &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;lxml&lt;/span&gt;&lt;/code&gt; for faster XML parsing&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;With the interface of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;zeep&lt;/span&gt;&lt;/code&gt; being similar but not the same as &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;suds&lt;/span&gt;&lt;/code&gt;, we
have to introduce some compatibility functions. This is also necessary, because
some library-specific representation of objects, e.g. attribute access to
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ManagedObjectReference&lt;/span&gt;&lt;/code&gt; objects, leaked through to consuming projects. We
therefore propose to change the library and consuming projects in multiple
phases.&lt;/p&gt;
&lt;p class="rubric"&gt;Phase 1&lt;/p&gt;
&lt;p&gt;Add compatibility functions to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo.vmware&lt;/span&gt;&lt;/code&gt; for value and type access of
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ManagedObjectReference&lt;/span&gt;&lt;/code&gt; and add additional functions/helpers for attribute
access to move all code using &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;suds&lt;/span&gt;&lt;/code&gt;-specificas into &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo.vmware&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p class="rubric"&gt;Phase 2&lt;/p&gt;
&lt;p&gt;Introduce patches to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cinder&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova&lt;/span&gt;&lt;/code&gt; for using the functions introduced
in phase 1.&lt;/p&gt;
&lt;p class="rubric"&gt;Phase 3&lt;/p&gt;
&lt;p&gt;Switch the code in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo.vmware&lt;/span&gt;&lt;/code&gt; to use &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;zeep&lt;/span&gt;&lt;/code&gt; instead of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;suds-jurko&lt;/span&gt;&lt;/code&gt;
while keeping the interface for consuming projects the same. The core of these
changes should be confined to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo_vmware.service&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;There’s another fork of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;suds&lt;/span&gt;&lt;/code&gt; based on &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;suds-jurko&lt;/span&gt;&lt;/code&gt; called &lt;a class="reference external" href="https://github.com/suds-community/suds"&gt;suds-community&lt;/a&gt;, which is still maintained, but
while using it may solve the Python compatibility problem it doesn’t improve
performance.&lt;/p&gt;
&lt;p&gt;While there are other libraries around, see e.g. this list in the &lt;a class="reference external" href="https://wiki.python.org/moin/WebServices#SOAP"&gt;Python wiki&lt;/a&gt;, a quick glance at most of
them shows them as unmaintained, not supporting Python 3 or having an interface
that requires too many compatibility shims for keeping changes in consuming
projects minimal.&lt;/p&gt;
&lt;p&gt;Another alternative would be to get rid of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo.vmware&lt;/span&gt;&lt;/code&gt; alltogether, which
is mainly hindered by nova and cinder still including drivers using this
library.&lt;/p&gt;
&lt;p&gt;An alternatives to adding helper functions for hiding the differences between
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;suds&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;zeep&lt;/span&gt;&lt;/code&gt; would be changing the depending project’s drivers to use
the new interface instead. But this would still leak implementation details of
the SOAP library backing &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo.vmare&lt;/span&gt;&lt;/code&gt; into depending projects, which can
also hinder future library switches.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="impact-on-existing-apis"&gt;
&lt;h3&gt;Impact on Existing APIs&lt;/h3&gt;
&lt;p&gt;Consuming code will be required to use the newly introduced helper-functions
for compatibility in attribute access.&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="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;With the XML parser of the library switching to the C-based &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;lxml&lt;/span&gt;&lt;/code&gt;, we expect
a performance increase. In our (very simple) tests, we achieved up to 50 %
reduction in request times and CPU load.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="configuration-impact"&gt;
&lt;h3&gt;Configuration 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;Consuming code will be required to use the newly introduced helper-functions
for compatibility in attribute access.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing-impact"&gt;
&lt;h3&gt;Testing Impact&lt;/h3&gt;
&lt;p&gt;Since there’s a new way to access &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ManagedObjectReference&lt;/span&gt;&lt;/code&gt;’s attributes, we
need to update all tests - including depending project’s - to use the helper
functions we are going to introduce.  Additionally, we will have to update fake
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ManagedObjectReference&lt;/span&gt;&lt;/code&gt; objects defined in the tests of depending projects
to include both old and new attributes for the transition phase. This is
necessary, because the project’s tests have to work indepedently of the backing
libraries helper-function implementation, so that introduces changes doesn’t
break them. An alternative to this would be providing fake objects importabable
via &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo.vmware&lt;/span&gt;&lt;/code&gt;. Even then there can still be cases where &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo.vmware&lt;/span&gt;&lt;/code&gt;’s
backing SOAP library’s object representation might leak into depending object’s
tests, because there are other objects, that are not
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ManagedObjectReferences&lt;/span&gt;&lt;/code&gt;, but behave exactly the same.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;jkulik&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="milestones"&gt;
&lt;h3&gt;Milestones&lt;/h3&gt;
&lt;p&gt;Target Milestone for completion: unclear&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 helper functions in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo.vmware&lt;/span&gt;&lt;/code&gt; for compatibility layer&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Patch &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova&lt;/span&gt;&lt;/code&gt;’s VMware driver to use helper functions&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Patch &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cinder&lt;/span&gt;&lt;/code&gt;’s VMware driver to use helper functions&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;zeep&lt;/span&gt;&lt;/code&gt; to global requirements as &lt;a class="reference external" href="https://docs.openstack.org/project-team-guide/dependency-management.html"&gt;documented&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Implement &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Service&lt;/span&gt;&lt;/code&gt; object using &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;zeep&lt;/span&gt;&lt;/code&gt; client in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo.vmware&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&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="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;This adds &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;zeep&lt;/span&gt;&lt;/code&gt; into OpenStack’s requirements, while removing
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;suds-jurko&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;Initial mailing list post: &lt;a class="reference external" href="http://lists.openstack.org/pipermail/openstack-discuss/2020-March/013449.html"&gt;http://lists.openstack.org/pipermail/openstack-discuss/2020-March/013449.html&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Bug regarding &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;suds&lt;/span&gt;&lt;/code&gt; packaging problems for debian: &lt;a class="reference external" href="https://bugs.launchpad.net/oslo.vmware/+bug/1465016"&gt;https://bugs.launchpad.net/oslo.vmware/+bug/1465016&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This work is licensed under a Creative Commons Attribution 3.0
Unported License.
&lt;a class="reference external" href="http://creativecommons.org/licenses/by/3.0/legalcode"&gt;http://creativecommons.org/licenses/by/3.0/legalcode&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
</description><pubDate>Tue, 26 May 2020 00:00:00 </pubDate></item><item><title>PTL Guide</title><link>https://specs.openstack.org/openstack/oslo-specs/specs/policy/ptl.html</link><description>

&lt;p&gt;There are some Oslo-specific aspects to being the Oslo PTL. This document is
a place to capture those for future reference.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem Description&lt;/h2&gt;
&lt;p&gt;Each PTL learns things about the position during the time in which they serve
it. However, historically they’ve kept private notes that had to be passed
along from PTL to PTL, which is not ideal. First, if the handoff doesn’t happen
for any reason, the new PTL will have to start over from scratch. Second, it
makes these notes hidden from public view, which is not useful for potential
future PTL candidates.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-policy"&gt;
&lt;h2&gt;Proposed Policy&lt;/h2&gt;
&lt;p&gt;This should be a living document that is updated by PTLs as they discover
new best practices and tips for leading the Oslo project.&lt;/p&gt;
&lt;p&gt;A new or future PTL should first read the &lt;a class="reference external" href="https://docs.openstack.org/project-team-guide/ptl.html"&gt;Project Team Guide PTL Document&lt;/a&gt;.
It contains a wealth of useful information that a PTL should know. Pay
particular attention to the parts about delegating.&lt;/p&gt;
&lt;section id="releases"&gt;
&lt;h3&gt;Releases&lt;/h3&gt;
&lt;p&gt;In general, the PTL or release liaison should &lt;a class="reference external" href="https://releases.openstack.org/reference/using.html#requesting-a-release"&gt;propose releases&lt;/a&gt; for all Oslo
libraries that need one weekly. Generally this is done early in the week, and
releasing on Friday is avoided when possible to avoid anyone having to work
the weekend to fix a breakage. If a critical fix needs to be released
immediately, it does not have to wait for the regular weekly release cycle.
The intent of the weekly cycle is to ensure changes get released in a timely
fashion, not to prevent anything from being released.&lt;/p&gt;
&lt;p&gt;Exceptions to the weekly release schedule can be made at the discretion of the
PTL. Releasing immediately before a holiday when most of the team will not be
around is not ideal. It is also a good idea to wait to release master after a
new stable branch has been cut until the release associated with the stable
branch has shipped. This allows backports of things like dependency bumps in
case bugs are found during final testing of an OpenStack release. In that case,
a minor version bump would be needed and if master has already been released
then that minor version will already be taken.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;In general, minor version changes are not allowed on stable branches,
but exceptions can be made if the situation warrants it. See
the &lt;a class="reference external" href="https://docs.openstack.org/project-team-guide/stable-branches.html#appropriate-fixes"&gt;stable branch guide&lt;/a&gt; for more details.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;When making releases, there are some useful commands to know. First, to find
all the changes in all the Oslo libraries since they were last released, use
the following commands in the openstack/releases repo:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;./tools/list_unreleased_changes.sh master $(.tox/venv/bin/list-deliverables --team oslo -r)
./tools/list_unreleased_changes.sh master $(.tox/venv/bin/list-deliverables --team oslo -r --series independent)
&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;These commands assume that the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;venv&lt;/span&gt;&lt;/code&gt; tox environment has been
created. That can be done with the command &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tox&lt;/span&gt; &lt;span class="pre"&gt;-e&lt;/span&gt; &lt;span class="pre"&gt;venv&lt;/span&gt; &lt;span class="pre"&gt;--notest&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;Oslo contains both libraries that are tied to the OpenStack release
as well as some that are independent of it. That’s why two commands
are needed to cover all of them.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;To do the same for a stable branch, use the following (replace the branch names
as appropriate):&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;./tools/list_unreleased_changes.sh stable/train $(.tox/venv/bin/list-deliverables --team oslo -r --series train)
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="meetings"&gt;
&lt;h3&gt;Meetings&lt;/h3&gt;
&lt;p&gt;The Oslo team typically meets weekly. The specific day and time can be found
on the &lt;a class="reference external" href="http://eavesdrop.openstack.org/#Oslo_Team_Meeting"&gt;eavesdrop page&lt;/a&gt;. The PTL normally chairs the meeting, but other
contributors can also do so if desired or needed. The &lt;a class="reference external" href="https://wiki.openstack.org/wiki/Meetings/Oslo#Agenda_for_Next_Meeting"&gt;meeting agenda&lt;/a&gt;
can be found on the wiki page. Chairing the meeting involves going through
the topics in the agenda - some weeks this takes 15 minutes or less, others
it takes the full hour or more.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="ping-list"&gt;
&lt;h3&gt;Ping List&lt;/h3&gt;
&lt;p&gt;The Oslo team uses a courtesy ping list in the &lt;a class="reference external" href="https://wiki.openstack.org/wiki/Meetings/Oslo#Agenda_Template"&gt;meeting agenda template&lt;/a&gt; so
regular meeting attendees can be reminded of the start of the meeting.
Attendees can add or remove their names as desired and the person running
the weekly meeting should copy the ping list into IRC so everyone on the list
gets a notification.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="weekly-wayward-review"&gt;
&lt;h3&gt;Weekly Wayward Review&lt;/h3&gt;
&lt;p&gt;This meeting topic requires a bit more explanation. The idea is to find an old
review and move it along in some way. This means at the end of the meeting,
the review should either be approved, -1’d, or have someone assigned to follow
up after the meeting.&lt;/p&gt;
&lt;p&gt;bnemec uses &lt;a class="reference external" href="https://opendev.org/openstack/reviewstats"&gt;reviewstats&lt;/a&gt; to find the oldest open reviews in Oslo.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="beginning-of-cycle-activities"&gt;
&lt;h3&gt;Beginning of Cycle Activities&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The ping list should be cleared each cycle to avoid pinging people who no
longer work on Oslo. A new ping list can be created in parallel to the old
one to allow contributors who want to stay on the list to sign up before the
list is cleared. These parallel lists should both exist for a couple of weeks
to give everyone a chance to update the new one.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When a new release name is announced, it needs to be added to the oslo.log
versionutils module. See this &lt;a class="reference external" href="https://opendev.org/openstack/oslo.log/commit/adef9b6ecbecedad9836e96a092c32cc8a17eb97"&gt;versionutils review&lt;/a&gt; for an example.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;At the start of each cycle, the Oslo &lt;a class="reference external" href="http://specs.openstack.org/openstack/oslo-specs/specs/policy/feature-freeze.html"&gt;feature freeze&lt;/a&gt; date should be added
to the release calendar. See this &lt;a class="reference external" href="https://github.com/openstack/releases/commit/58585a1fa0084fb8aca8146c848d338ccc7766ba#diff-6590df7965d3a63150e201d8881d33f9"&gt;feature freeze date review&lt;/a&gt; for an
example of doing that. A detailed explanation of why Oslo has its own
feature freeze can be found in the &lt;a class="reference external" href="http://specs.openstack.org/openstack/oslo-specs/specs/policy/feature-freeze.html"&gt;feature freeze&lt;/a&gt; policy.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Check the &lt;a class="reference external" href="https://launchpad.net/~oslo-coresec"&gt;oslo-coresec&lt;/a&gt; group and make sure all members are active Oslo
cores so private security bugs are not being sent out to people who don’t
need to see them. If necessary, add current core team members to ensure
that there are enough people on the coresec team to handle any security bugs
that come in.&lt;/p&gt;
&lt;p&gt;For more details on managing the coresec team, see the
&lt;a class="reference external" href="https://governance.openstack.org/tc/reference/tags/vulnerability_managed.html#requirements"&gt;vulnerability management team’s requirements&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="end-of-cycle-activities"&gt;
&lt;h3&gt;End of Cycle Activities&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Make sure all libraries get released before non-client library freeze, even
if they don’t have changes that would normally prompt a release (such as
doc or test changes). This may be handled automatically by the release team
now, but it’s still good to do it explicitly. It is important for all changes
to be released before stable branches are cut because branches are based on
the last released commit, not what was on master at the time. If there are
unreleased doc or test changes they may be lost on the stable branch and need
to be backported.&lt;/p&gt;
&lt;p&gt;When doing the final release of a library for the cycle, also request to
create the appropriate stable branch. For an example of doing so, see
&lt;a class="reference external" href="https://review.opendev.org/#/c/718760/"&gt;this branch creation request&lt;/a&gt;. In the future this can all be done in one
review, but it’s a change in the previous process so there are no example
reviews for that yet.&lt;/p&gt;
&lt;p&gt;When doing a final release, you can easily include the branch creation
with it by adding &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;--stable-branch&lt;/span&gt;&lt;/code&gt; to the new_release.sh call. 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="o"&gt;./&lt;/span&gt;&lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;new_release&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sh&lt;/span&gt; &lt;span class="n"&gt;ussuri&lt;/span&gt; &lt;span class="n"&gt;oslo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="n"&gt;feature&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;stable&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;branch&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="ptl-handoff-activities"&gt;
&lt;h3&gt;PTL Handoff Activities&lt;/h3&gt;
&lt;p&gt;Hopefully most of these activities are automated, but one thing that needs to
be done manually is to make the new PTL an administrator on the
&lt;a class="reference external" href="https://launchpad.net/~oslo-coresec"&gt;oslo-coresec&lt;/a&gt; group in Launchpad.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="alternatives-history"&gt;
&lt;h2&gt;Alternatives &amp;amp; History&lt;/h2&gt;
&lt;p&gt;As discussed in the problem description, we could continue to have the Oslo
PTL maintain a private set of notes that is passed individually to the next
PTL. This is not preferred for the reasons mentioned there.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="author-s"&gt;
&lt;h3&gt;Author(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary author:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;bnemec&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Future PTLs&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="milestones"&gt;
&lt;h3&gt;Milestones&lt;/h3&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;p&gt;Writing the policy itself is the main work item. Updating it as the community
evolves will be an ongoing process.&lt;/p&gt;
&lt;/section&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://governance.openstack.org/tc/goals/selected/ussuri/project-ptl-and-contrib-docs.html"&gt;Ussuri community goal&lt;/a&gt;&lt;/p&gt;
&lt;/section&gt;
&lt;section id="revision-history"&gt;
&lt;h2&gt;Revision History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Ussuri&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This work is licensed under a Creative Commons Attribution 3.0
Unported License.
&lt;a class="reference external" href="http://creativecommons.org/licenses/by/3.0/legalcode"&gt;http://creativecommons.org/licenses/by/3.0/legalcode&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
</description><pubDate>Thu, 23 Apr 2020 00:00:00 </pubDate></item><item><title>Proposed new library oslo.metrics</title><link>https://specs.openstack.org/openstack/oslo-specs/specs/ussuri/oslo-metrics.html</link><description>

&lt;p&gt;This is a proposal to create a new library to collect metrics of oslo libraries.&lt;/p&gt;
&lt;section id="proposed-library-mission"&gt;
&lt;h2&gt;Proposed library mission&lt;/h2&gt;
&lt;p&gt;The mission of oslo.metrics is exposing internal metrics information of oslo
libraries. OpenStack processes create a connection to other middleware using
oslo library, e.g. oslo.messaging to connect another OpenStack process and
oslo.db to connect DB. The oslo.messaging creates its own RPC protocol over the
connection to RabbitMQ, which is a default messaging middleware in OpenStack
project. The usage of RabbitMQ can be monitored by RabbitMQ management tool,
but the usage of oslo.messaging’s RPC can’t be monitored. Enabling OpenStack
admin and operator to monitor usage of oslo libraries is the goal of
oslo.metrics.&lt;/p&gt;
&lt;p&gt;The oslo.metrics supports metrics of the oslo.messaging’s RPC as first goal.
The metrics information of the RPC doesn’t appear anywhere. For example, when
a user calls the Create New Instance API to Nova, there is no infomation about
how many RPC calls are made, which RPC targets are used, and etc. And for another
case, if operator adds 10 compute nodes to their OpenStack cluster, how may RPC
will be increased, and etc.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="consuming-projects"&gt;
&lt;h2&gt;Consuming projects&lt;/h2&gt;
&lt;p&gt;There are two type of consumers. One is the OpenStack services, which use
oslo.messaging as its internal communication. Another is Monitoring systems,
which consume the metrics exposed by the oslo.metrics.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="alternatives-library"&gt;
&lt;h2&gt;Alternatives library&lt;/h2&gt;
&lt;p&gt;If oslo.messaging exposes its metrics, the notification feature of
oslo.messaging can be a one of alternatives. However, the notification is
also implemented over the RabbitMQ. It makes cross reference in the metrics
so it’s not good idea to do.&lt;/p&gt;
&lt;p&gt;The rpc_monitor is also another alternatives. This library focuses on collecting
oslo.messaging metrics, and exposes its metrics to Prometheus. The rpc_monitor
has not been developed long time. And the oslo.metrics will support multi type
of monitoring system as an official library. So it’s difficult to use the
rpc_monitor itself. However, the goal of rpc_monitor is similar to the
oslo.metrics’s first goal. When implementing the oslo.metrics the Prometheus
support, it’s better to consult the rpc_monitor’s implementation.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-adoption-model-plan"&gt;
&lt;h2&gt;Proposed adoption model/plan&lt;/h2&gt;
&lt;p&gt;The basic architecture is the oslo.metrics works as metrics data serializer
for outside system.
The existing oslo libraries send original metrics information through
a unix socket, then the oslo.metrics gathers the metrics information
and exposes the data.&lt;/p&gt;
&lt;p&gt;The oslo.metrics listens to unix sockets to receive metrics data from
each of the OpenStack processes. The reason oslo.metrics uses the socket
is to collect messaging metrics information from multiple processes which
runs on the same node. One metrics process represents one node or one
OpenStack project.&lt;/p&gt;
&lt;p&gt;The consumer of oslo.metrics, e.g. oslo.messaging, needs to send its metrics
information to the unix socket. The olso.messaging sends its metric data to
the socket as well as the actual RPC request to another oslo.messaging server.
The metrics data sending feature is configured by a new flag in oslo.messaging
library.&lt;/p&gt;
&lt;p&gt;If we have a control server, then both Neutron-Server and Nova-API running
in the controller would share their metrics to one unix socket which can
get data from other OpenStack processes as well. The Unix Socket running
in one Node would handle all OpenStack processes of that node&lt;/p&gt;
&lt;p&gt;The oslo.messaging sends the RPC information one by one to oslo.metrics
with oslo.metrics’s format. All information sent by oslo.messaging are
put together into one metrics data in oslo.metrics. Then oslo.metrics
exposes the one data to any monitoring system.&lt;/p&gt;
&lt;p&gt;The monitoring system is really depending on operator. So oslo.metrics exposes
the data by common format. The de facto standard is &lt;a class="reference external" href="https://prometheus.io/docs/instrumenting/exposition_formats/#text-based-format"&gt;the Prometheus exposition
format&lt;/a&gt;.
We decide to use this format and expose the metrics on the HTTP endpoint. It
allows integration with most monitoring systems, like e.g. Prometheus or
Monasca.&lt;/p&gt;
&lt;p&gt;The data oslo.messaging sends to the oslo.metrics includes but is not limited
to:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;topic&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;namespace&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;version&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;server&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;fanout&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;timeout&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;type of call: call or cast&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;timestamp of the call&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;project_id&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Hostname are added by oslo.metrics side.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;The actual information schema is WIP and can be changed during the
implementation.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="highlight-none notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;+--------------+        +--------------+     +-------------+
|              |        |              |     | any         |
|oslo.messaging+--------&amp;gt; oslo.metrics &amp;lt;-----&amp;gt; monitoring  |
|              |        |              |     | system      |
+--------------+        +--------------+     +-------------+
               unix socket
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="security-concerns"&gt;
&lt;h2&gt;Security Concerns&lt;/h2&gt;
&lt;p&gt;The metrics information exposed by the oslo.metrics may have the sensitive
information, which should be isolated from normal user. The oslo.metrics is
an admin tool and it’s expected to work inside of isolated internal network.
The isolated network usually has another security protection from normal user’s
access. Because of that security protection this sensitive information is not
exposed to a normal user or end user of cloud.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="reviewer-activity"&gt;
&lt;h2&gt;Reviewer activity&lt;/h2&gt;
&lt;p&gt;For the changes in oslo.messaging, the support from oslo.messaging core is needed.
For the oslo.metrics, the member of Large Scale SIG could review the patches.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h2&gt;Performance Impact&lt;/h2&gt;
&lt;p&gt;The oslo.metrics requests oslo.messaing to send another information. This may
cause a performance impact to the RPC request. After implementing first spec,
this library should be tested how much the additional information sending cause
performance impact.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="author-s"&gt;
&lt;h3&gt;Author(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary authors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Masahito Muroi (masahito-muroi)&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;Create a new library named oslo.metrics
* The implementation includes unit tests and functional tests as well as its codes&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Change oslo.messaging to support metrics sending&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Investigation of performance impact of oslo.messaging RPC&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&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;Discussion in Large-Scale SIG:  &lt;a class="reference external" href="https://etherpad.openstack.org/p/large-scale-sig-cluster-scaling"&gt;https://etherpad.openstack.org/p/large-scale-sig-cluster-scaling&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Mirantis rpc_monitor: &lt;a class="reference external" href="https://github.com/Mirantis/rpc_monitor"&gt;https://github.com/Mirantis/rpc_monitor&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="revision-history"&gt;
&lt;h2&gt;Revision History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Ussuri&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This work is licensed under a Creative Commons Attribution 3.0
Unported License.
&lt;a class="reference external" href="http://creativecommons.org/licenses/by/3.0/legalcode"&gt;http://creativecommons.org/licenses/by/3.0/legalcode&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
</description><pubDate>Thu, 26 Mar 2020 00:00:00 </pubDate></item><item><title>Support notification Transports per oslo messaging notifications</title><link>https://specs.openstack.org/openstack/oslo-specs/specs/victoria/support-transports-per-oslo-notifications.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/oslo.messaging/+spec/support-transports-per-oslo-notifications"&gt;https://blueprints.launchpad.net/oslo.messaging/+spec/support-transports-per-oslo-notifications&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Large clouds where the cloud is being maintained with multiple regions,
operators usually configure global components(for ex: Designate, Ceilometer)
in the DR(Disaster Recovery) fashion. The core services like Nova and
Neutron are then configured to send oslo.messaging notifications to both
the region based components(for ex: Searchlight) and at the same time to
global components. Currently oslo.messaging only allows to send all the
notifications to just one underlying messaging transport(for ex:
one rabbitmq cluster which has deployed region based components).
This spec proposes to add feature into oslo.messaging which enables operators
to define different transport_url for each notification so that they can be
sent to the different messaging transport(for ex: rabbitmq clusters)&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo.messaging&lt;/span&gt;&lt;/code&gt; allows to specify the drivers and notifications transports
in each components config files like below For example, in nova.&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;[oslo_messaging_notifications]&lt;/span&gt;
&lt;span class="na"&gt;driver&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;messaging&lt;/span&gt;
&lt;span class="na"&gt;topics&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;notifications,notifications_designate&lt;/span&gt;
&lt;span class="na"&gt;transport_url&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;rabbit://username:password@rabbit001.com:5672&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;With above configuration the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;notifications&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;notifications_designate&lt;/span&gt;&lt;/code&gt;
related notifications are sent to the defined &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;transport_url&lt;/span&gt;&lt;/code&gt; to
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;rabbit001.com&lt;/span&gt;&lt;/code&gt;. If the designate service is deployed onto different
region/cluster which is using different rabbitmq cluster, currently there is no
way to send only the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;notifications_designate&lt;/span&gt;&lt;/code&gt; to say &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;rabbit002.com&lt;/span&gt;&lt;/code&gt; which
is designate service rabbitmq cluster.&lt;/p&gt;
&lt;p&gt;Operators should be allowed to send the notifications into different underlying
messaging transport based on the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;transport_url&lt;/span&gt; &lt;span class="pre"&gt;per&lt;/span&gt; &lt;span class="pre"&gt;notification&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;The spec proposes to follow the same implementation of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;enabled_backends&lt;/span&gt;&lt;/code&gt;
done Cinder &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; and Glance &lt;a class="footnote-reference brackets" href="#id4" id="id2" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;2&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; components.&lt;/p&gt;
&lt;section id="define-dynamic-new-config-group-for-each-notification"&gt;
&lt;h3&gt;Define dynamic new config group for each notification&lt;/h3&gt;
&lt;p&gt;For example:&lt;/p&gt;
&lt;div class="highlight-ini notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="k"&gt;[oslo_messaging_notifications]&lt;/span&gt;
&lt;span class="na"&gt;driver&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;messaging&lt;/span&gt;
&lt;span class="na"&gt;topics&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;notifications,notifications_designate,any_other_notification&lt;/span&gt;
&lt;span class="na"&gt;transport_url&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;rabbit://username:password@rabbit001.com:5672&lt;/span&gt;

&lt;span class="k"&gt;[oslo_messaging_topic_notifications]&lt;/span&gt;
&lt;span class="na"&gt;transport_url&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;rabbit://username:password@rabbit001.com:5672&lt;/span&gt;

&lt;span class="k"&gt;[oslo_messaging_topic_notifications_designate]&lt;/span&gt;
&lt;span class="na"&gt;transport_url&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;rabbit://username:password@rabbit002.com:5672&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;As described in the above config section, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[oslo_messaging_notifications]&lt;/span&gt;&lt;/code&gt;
section contains the list of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;topics&lt;/span&gt;&lt;/code&gt; being used for notifications.
Each of the notification is then dynamically grouped later and has its own
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;transport_url&lt;/span&gt;&lt;/code&gt;. The format of the topic based section will be
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo_messaging_topic_&amp;lt;topic-name&amp;gt;&lt;/span&gt;&lt;/code&gt; to avoid collisions between topic
names and possibly other config section names.&lt;/p&gt;
&lt;p&gt;By default if the transport_url is not defined for any of the notification
it will fall back to the main sections transport_url
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[oslo_messaging_notifications]&lt;/span&gt;&lt;/code&gt; and if it is defined over there as well then
it will finally fallback to the transport_url defined in the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[oslo_messaging_rabbit]&lt;/span&gt;&lt;/code&gt;.
In the above example &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;notifications&lt;/span&gt;&lt;/code&gt; topic uses &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;rabbit001.com&lt;/span&gt;&lt;/code&gt; rabbitmq
cluster. &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;notifications_designate&lt;/span&gt;&lt;/code&gt; uses &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;rabbit002.com&lt;/span&gt;&lt;/code&gt; rabbitmq cluster
and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;any_other_notification&lt;/span&gt;&lt;/code&gt; used &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;rabbit001.com&lt;/span&gt;&lt;/code&gt; rabbitmq cluster.&lt;/p&gt;
&lt;p&gt;The notifications will inherit all the other config option values like
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;driver&lt;/span&gt;&lt;/code&gt; etc.&lt;/p&gt;
&lt;p&gt;This change is backward compatible so even if operator do not specify each
notifications transport_urls they will fall back to the main sections.&lt;/p&gt;
&lt;p&gt;This change does not require any changes to oslo.config since everything is
already supported.&lt;/p&gt;
&lt;p&gt;Also this will not require the clients like Nova, Neutron to change their
config files if they don’t want to send notifications to different clusters.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;This use case can be implemented with below new feature:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Add &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;MultiOptGroup&lt;/span&gt;&lt;/code&gt; support in oslo.conf same as &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;MultiOpt&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Make use of  &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;MultiOptGroup&lt;/span&gt;&lt;/code&gt; in oslo.messaging and in the clients like
Nova and Neutron&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;For example:&lt;/p&gt;
&lt;div class="highlight-ini notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="k"&gt;[oslo_messaging_notifications]&lt;/span&gt;
&lt;span class="na"&gt;driver&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;messaging&lt;/span&gt;
&lt;span class="na"&gt;topics&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;notifications&lt;/span&gt;
&lt;span class="na"&gt;transport_url&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;rabbit://username:password@rabbit001.com:5672&lt;/span&gt;

&lt;span class="k"&gt;[oslo_messaging_notifications]&lt;/span&gt;
&lt;span class="na"&gt;driver&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;messaging&lt;/span&gt;
&lt;span class="na"&gt;topics&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;notifications_designate&lt;/span&gt;
&lt;span class="na"&gt;transport_url&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;rabbit://username:password@rabbit002.com:5672&lt;/span&gt;

&lt;span class="k"&gt;[oslo_messaging_notifications]&lt;/span&gt;
&lt;span class="na"&gt;driver&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;messaging&lt;/span&gt;
&lt;span class="na"&gt;topics&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;any_other_notification&lt;/span&gt;
&lt;span class="na"&gt;transport_url&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;rabbit://username:password@rabbit001.com:5672&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;This solution requires to add a new feature in oslo.config which will allow to
define the option group multiple times as shown above which can be used in
oslo.messaging to define the transport_urls per notification.
This feature might be useful in other use-cases as well where it is required
to define the group multiple times.&lt;/p&gt;
&lt;p&gt;One more alternative could be to use RabbitMQ Shovel plugin (in case if you are
using rabbitmq as a messaging backend) to move messages from one cluster to
other cluster. You can define separate shovel policy for each &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;notification&lt;/span&gt;&lt;/code&gt;
with different &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;dest-uri&lt;/span&gt;&lt;/code&gt; to send them to different rabbitmq clusters.
One disadvantage of using shovel approach is RabbitMQ shovel plugin actually
creates a non-existent queue on the RabbitMQ node as a durable queues because
thats the behaviour of Shovel plugin and if the OpenStack service is not using
durable queues the service will fail to send the messages to rabbitmq and gives
below error:
Error: Queue.declare: (406) PRECONDITION_FAILED&lt;/p&gt;
&lt;/section&gt;
&lt;section id="impact-on-existing-apis"&gt;
&lt;h3&gt;Impact on Existing APIs&lt;/h3&gt;
&lt;p&gt;No impact.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;No impact.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;No impact.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="configuration-impact"&gt;
&lt;h3&gt;Configuration Impact&lt;/h3&gt;
&lt;p&gt;Each notification will have its own group which can be defined like above.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer Impact&lt;/h3&gt;
&lt;p&gt;No impact.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing-impact"&gt;
&lt;h3&gt;Testing Impact&lt;/h3&gt;
&lt;p&gt;Additional unit tests will be required to cover the added functionality.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Dinesh_Bhor (&lt;a class="reference external" href="mailto:bhordinesh07%40gmail.com"&gt;bhordinesh07&lt;span&gt;@&lt;/span&gt;gmail&lt;span&gt;.&lt;/span&gt;com&lt;/a&gt;)&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;volunteers?&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="milestones"&gt;
&lt;h3&gt;Milestones&lt;/h3&gt;
&lt;p&gt;..TODO(Dinesh_Bhor): figure this out&lt;/p&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Implement the new dynamic &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;notifications&lt;/span&gt;&lt;/code&gt; OptGroup generation.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Integrate it in &lt;cite&gt;get_notifications_transport&lt;/cite&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Notifier&lt;/span&gt;&lt;/code&gt; class.&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;Update the sample configuration generator to include the variable names.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update the documentation generator to include the variable names.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="incubation"&gt;
&lt;h2&gt;Incubation&lt;/h2&gt;
&lt;p&gt;N/A&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 will need to be updated to indicate that notification option
can be overridden with its own dedicated group.&lt;/p&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="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;aside class="footnote-list brackets"&gt;
&lt;aside class="footnote brackets" id="id3" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id1"&gt;1&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://github.com/openstack/glance/blob/0bb0fca24c23d8e8000ce7a3cabc695aec52f334/doc/source/admin/multistores.rst"&gt;https://github.com/openstack/glance/blob/0bb0fca24c23d8e8000ce7a3cabc695aec52f334/doc/source/admin/multistores.rst&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id4" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id2"&gt;2&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://github.com/openstack/cinder/blob/ea04cda682168b642ae2fa823338c4dd26e5c86c/doc/source/admin/blockstorage-multi-backend.rst"&gt;https://github.com/openstack/cinder/blob/ea04cda682168b642ae2fa823338c4dd26e5c86c/doc/source/admin/blockstorage-multi-backend.rst&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;/aside&gt;
&lt;/section&gt;
</description><pubDate>Thu, 31 Oct 2019 00:00:00 </pubDate></item><item><title>Provide a AMQP 1.0 implementation for oslo.messaging</title><link>https://specs.openstack.org/openstack/oslo-specs/specs/juno/amqp10-driver-implementation.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/oslo.messaging/+spec/amqp10-driver-implementation"&gt;https://blueprints.launchpad.net/oslo.messaging/+spec/amqp10-driver-implementation&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;We already have rabbit and qpid drivers for earlier (and different!)
versions of AMQP, the proposal would be to add an additional driver
for a _protocol_ not a particular broker.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;The purpose of allowing for different drivers is to give users
choice. However every driver supported increases the maintenance
burden.&lt;/p&gt;
&lt;p&gt;By targeting a clear mapping on to a protocol, rather than a specific
implementation, we would simplify the task in the future for anyone
wishing to move to any other system that spoke AMQP 1.0[1]. That would no
longer require a new driver, merely different configuration and
deployment. That would then allow openstack to more easily take
advantage of any emerging innovations in this space.&lt;/p&gt;
&lt;p&gt;As an example, this would allow the use of the Dispatch Router from
the Apache Qpid project to be used. This has been designed as a
distributed router rather than a single-process, store-and-forward
broker and offers simple scalability and redundancy.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;A new driver will be added to oslo.messaging (a patch for this has
been available for review at &lt;a class="reference external" href="https://review.openstack.org/75815"&gt;https://review.openstack.org/75815&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;The mapping outlined below considers the inter-mediated case
(i.e. where the driver connects to a message broker or network of
brokers). AMQP 1.0 would allow communication (in part or as a whole)
to be conducted directly between peers, without the use of
intermediaries. Development of this aspect however is considered a future
extension (see Appendix A for some more detailed discussion).&lt;/p&gt;
&lt;p&gt;The aim is to support as many of the existing 1.0 enabled
intermediaries as we can without overly distorting the use of the AMQP
1.0 protocol.&lt;/p&gt;
&lt;p&gt;In AMQP 1.0, addressable entities within a broker (or similar) are
called ‘nodes’ (e.g. queues or topics). Nodes are message ‘sinks’ or
‘sources’, to which messages are then typically sent by establishing a
sending or receiving ‘link’ to or from the given node. AMQP 1.0 does
not provide any standard configuration mechanism for configuring such
nodes on the fly (with the exception of dynamic reply queues). However
by allowing deployment specific prefixes to the addresses specified in
the source and target for receiving and sending links respectively, it
should be possible to get the required functionality working with a
variety of implementations and offer considerable flexibility to
deployers.&lt;/p&gt;
&lt;p&gt;In RPC, there are three patterns for invocations, and a different
address format will be used for each.&lt;/p&gt;
&lt;p&gt;(A) For invocations on a specific server the address will be formed by
concatenating the topic name and the server name and will be prefixed
by the exchange if specified and/or by a deployment specific
‘server_request_prefix’ string. The default value for this prefix is
‘exclusive’.&lt;/p&gt;
&lt;p&gt;(B) For invocations on one of a group of servers the address will be
the topic name and will be prefixed by the exchange if specified
and/or by a deployment specific ‘group_request_prefix’ string. The
default value for this prefix is ‘unicast’.&lt;/p&gt;
&lt;p&gt;(C) For invocations on all of a group of servers the address will be
the topic name, prefixed by the exchange if specified and also
prefixed with a configurable ‘broadcast_prefix’ string. The default
value of this prefix is ‘/broadcast/’.&lt;/p&gt;
&lt;p&gt;Each pattern of communication is therefore identifiable through a
customisable pattern of address. This allows either the broker (or
equivalent) to be configured to match what the driver is using, or it
allows the driver to be configured to take account of built-in (and
non-configurable) conventions for a given broker.&lt;/p&gt;
&lt;p&gt;So for example, Qpid Dispatch Router could be configured to recognise
three patterns based on the default prefixes. Any message for an
address starting with ‘unicast’ (or ‘exclusive’) would be routed to
only one subscriber for that address. Any message for an address
starting with ‘broadcast’ would be sent to all subscribers for that
address. [Some more detail on configuration is provided in Appendix B
for Qpid Dispatch Router and Appendix C for qpidd.]&lt;/p&gt;
&lt;p&gt;Some other broker might not be configurable in this way, but might
have built in conventions around address patterns. E.g. all address of
the form ‘/queues/foo’ would be treated as queues and messages sent to
them would be allocated to only one consumer. Addresses of the form
‘/topics/bar’ (or ‘/exchanges/bar’) would be considered pub-sub topics
and the message would be distributed to all subscribers.&lt;/p&gt;
&lt;p&gt;For each send request, the appropriate address will be deduced from
the specified target. If the server value on the target is specified,
it implies an invocation on a specific server and the address format
described above in (A) is used. If the server is not specified then
the fanout flag is considered. If that is specified it implies an
invocation on the entire group of servers identified by the topic and
the address format described in (C) is used. If neither the server
nor the fanout flag is specified it implies an invocation on one of
the group of servers identified by the topic and the address format
described in (B) is used.&lt;/p&gt;
&lt;p&gt;A cache of sender links per target will be maintained to avoid the
overhead of recreating them on each request. (The alternative of using
a single sending link and setting the ‘to’ field is also a
possibility, but not all intermediaries might support that so it would
be an unnecessary limitation on choice). If there is no sender link
yet for the specified address one will be created and added to the
cache. The cache will be cleared on reconnect.&lt;/p&gt;
&lt;p&gt;A single connection and session will be used for all the sender
links. If a timeout is specified for the request, this will be set as
a ttl on the request. The request will also have the ‘to’ field set to
the value used in the target for the link. This accommodates any
intermediary that may expect or prefer that means of addressing.&lt;/p&gt;
&lt;p&gt;There will be a single receiver link per driver instance for replies,
this will have the dynamic flag set on the source.  Each request will
have the reply-to address set to the address to which this listener
is subscribed.  Each request will have a message-id set. This will be
echoed back in the correlation-id of any response message allowing it
to be correlated back to the waiting send request.&lt;/p&gt;
&lt;p&gt;A server will subscribe for messages by creating three receiving
links: one to subscribe to requests specific to the server, one to
subscribe to requests for one of the servers group and one to
subscribe to broadcasts for all the servers in the group (i.e. one for
each form of address described in A, B and C above).  The first two
receiver links will have the distribution mode set to move, the third
will have the distribution mode set to copy. (Note: the distribution
mode is defined by the AMQP 1.0 specification to determine if/how
message are distributed between multiple subscribers).&lt;/p&gt;
&lt;p&gt;Requests and responses for RPC will be sent pre-settled, meaning that
they are not explicitly acknowledged and therefore may be lost on
failover. Ideally notifications would be acknowledged both when
published and when received by a listener. (Note: at present the
rabbit driver acknowledges notifications when delivered, but published
notifications are not aknowledged. For the current qpid driver
notifications are not acknowledged either on publication or delivery).&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;The rabbit driver is the only one that appears to be adequately
maintained at present. The qpid driver suffers from an impedance
mismatch between the API offered by qpid.messaging and that used for
the rabbit driver. The attempt to use a common architecture for these
two quite different APIs has led to the qpid driver being hard to
understand and inefficient in its mapping to AMQP 0-10.&lt;/p&gt;
&lt;p&gt;One alternative to adding a new driver is to only support the rabbit
driver. That reduces the maintenance burden and gives clarity to
users. It does however restrict choice.&lt;/p&gt;
&lt;p&gt;Another alternative would be to choose a different protocol as the
basis of the new driver. MQTT is focused on a pub-sub pattern and
doesn’t incorporate competing consumers as is required for the current
oslo.messaging semantics. STOMP doesn’t define interoperable
mechanisms for request-response. Since two of the existing drivers use
earlier versions of AMQP, AMQP supports all the patterns needed and
AMQP is an open standard (now standardised under ISO) it seems a
fairly obvious candidate.&lt;/p&gt;
&lt;p&gt;Though this driver is not being suggested as a replacement for existing
drivers (merely an alternative), it does offer a path to greater
consolidation as it could also accommodate the non-intermediated style
of communication embraced by ZeroMQ. Perhaps even more powerful would
be a hybrid approach, where again the use of a common, standard
protocol would be advantageous.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="impact-on-existing-apis"&gt;
&lt;h3&gt;Impact on Existing APIs&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 implications are identical to that of the other
drivers. SSL will be supported as an option to secure the messaging
traffic where desired.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;There would be no impact whatsoever unless the driver is selected for
use. The overall performance will depend on which server components
are selected for use with the driver (unlike the existing drivers,
selection of this driver doesn’t restrict the choice to a single
broker implementation).&lt;/p&gt;
&lt;p&gt;Initial experience with the code[2] indicate that this driver in
conjunction with either qpidd or Qpid Dispatch Router compares very
favourably with existing drivers.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="configuration-impact"&gt;
&lt;h3&gt;Configuration Impact&lt;/h3&gt;
&lt;p&gt;The driver would be selected via the existing transport_url
option. The ‘amqp’ scheme in the url is used to select the AMQP
protocol.&lt;/p&gt;
&lt;p&gt;There would be further configuration options to tailor the behaviour
of the driver to different deployments if desired, such as the various
prefix options described above. The defaults have been selected to
make broker configuration simple. In general configuration of the
messaging infrastructure is preferred to configuration of the driver
as it allows for more transparent, centralised changes.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer Impact&lt;/h3&gt;
&lt;p&gt;Any future changes to the driver API would need to be reflected in
another driver if this one were added.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;&lt;a class="reference external" href="mailto:kgiusti%40redhat.com"&gt;kgiusti&lt;span&gt;@&lt;/span&gt;redhat&lt;span&gt;.&lt;/span&gt;com&lt;/a&gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;&lt;a class="reference external" href="mailto:gsim%40redhat.com"&gt;gsim&lt;span&gt;@&lt;/span&gt;redhat&lt;span&gt;.&lt;/span&gt;com&lt;/a&gt;
&lt;a class="reference external" href="mailto:fpercoco%40redhat.com"&gt;fpercoco&lt;span&gt;@&lt;/span&gt;redhat&lt;span&gt;.&lt;/span&gt;com&lt;/a&gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="milestones"&gt;
&lt;h3&gt;Milestones&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Target Milestone for completion:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Juno-1&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 review; the driver has been available for review via Gerritt for
some time. There is quite a lot of code in this that is in fact very
generic, and would be applicable beyond the use in olso.messaging. It
has been suggested (requested?) that this should be moved out of the
driver into its own library. There is in fact already a library that
contains this generic code, pyngus, and one task would be to update
the driver patch to rely on that as a dependency.&lt;/p&gt;
&lt;p&gt;Automated testing should be set up. I have submitted a patch for
functional tests of the oslo.messaging API (which I used to test the
driver during development). In addition any relevant tests from
Tempest could be run using this driver and an appropriately configured
backend.&lt;/p&gt;
&lt;p&gt;I have tested against both qpidd and Qpid dispatch router. Based on my
experience with other applications, I believe the driver would work
against the current ActiveMQ release (as well as ApolloMQ). For
RabbitMQ, the lack of support for the ‘dynamic’ flag on link source is
the main issue at present (which could be worked around if
desired). In theory it should also work against Microsofts ServiceBus
and IITs SwiftMQ as they support the aspects of the protocol
used. Those might require much more manual configuration at present, I
haven’t used them so am unable to say for sure.&lt;/p&gt;
&lt;p&gt;Allowing for reliable delivery of notifications by having publication
and delivery to consumers acknowledged.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="incubation"&gt;
&lt;h2&gt;Incubation&lt;/h2&gt;
&lt;p&gt;Though this does not add a new (public) module, it would be prudent to
allow some time for the new driver to mature. Having some sort of
‘beta’ phase would be good, where the driver could be selected for
testing by interested parties and feedback provided.&lt;/p&gt;
&lt;section id="adoption"&gt;
&lt;h3&gt;Adoption&lt;/h3&gt;
&lt;p&gt;The driver should be usable by any service using oslo.messaging&lt;/p&gt;
&lt;/section&gt;
&lt;section id="library"&gt;
&lt;h3&gt;Library&lt;/h3&gt;
&lt;p&gt;oslo.messaging&lt;/p&gt;
&lt;/section&gt;
&lt;section id="anticipated-api-stabilization"&gt;
&lt;h3&gt;Anticipated API Stabilization&lt;/h3&gt;
&lt;p&gt;There is no API impact. Stabilization of the new driver option itself
will take some time.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;The availability of an alternative option would at some point need to
be documented.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;This driver depends on the qpid-proton python library for AMQP 1.0
support. Pyngus may be added as dependency, see Work Items above.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="appendix-a-some-discussion-of-direct-communication"&gt;
&lt;h2&gt;Appendix A: Some discussion of direct communication&lt;/h2&gt;
&lt;p&gt;Supporting direct communication, where messages do not go through an
application layer intermediary user process, requires that
communicants accept incoming connections and can determine the correct
hostname and port to connect to.&lt;/p&gt;
&lt;p&gt;Though this can be done by convention, e.g. using the server name as
the hostname and agreeing well-known ports, that can be restrictive
and cumbersome. A better approach is to have a registry of servers and
the host and ports they listen on.&lt;/p&gt;
&lt;p&gt;This registry is much like the matchmaker used for 0MQ and the choices
applicable there would also be applicable to this driver.&lt;/p&gt;
&lt;p&gt;However since there is already support for communication through n
intermediary, that can be used to dynamically distribute the data for
the registry to all communicants. This keeps configuration simple and
allows the system to adapt to changes.&lt;/p&gt;
&lt;p&gt;Different schemes would be possible. One example would be to add a
configuration option that caused servers to start listenting on a
particular port. They would then advertise this fact by attaching a
property to any reply sent back for a request that identifies them
directly. The RPC clients could then cache these alternate addresses
and use them for any subsequent requests to the same server. In this
approach the communicants use the messaging intermediaries to locate
each other, but having done so they then ‘offload’ further
communication to a direct connection to reduce the load on the
intermediaries.&lt;/p&gt;
&lt;p&gt;Another approach would be to have a special ‘matchmaker’ topic that
clients would subscribe to and servers would announce themselves
over. This would allow direct comunication even from the first request
to a given server.&lt;/p&gt;
&lt;p&gt;These and indeed other schemes could be easily accomplished in a backward
compatible manner.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="appendix-b-configuring-qpid-dispatch-router"&gt;
&lt;h2&gt;Appendix B: Configuring Qpid Dispatch Router&lt;/h2&gt;
&lt;p&gt;Using the default prefixes, the following address configuration, if
added to the configuration file for Dispatch Router, would setup the
required semantics for openstack:&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;fixed&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;address&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;prefix&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;unicast&lt;/span&gt;
    &lt;span class="n"&gt;fanout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;single&lt;/span&gt;
    &lt;span class="n"&gt;bias&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;closest&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;fixed&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;address&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;prefix&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;exclusive&lt;/span&gt;
    &lt;span class="n"&gt;fanout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;single&lt;/span&gt;
    &lt;span class="n"&gt;bias&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;closest&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;fixed&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;address&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;prefix&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;broadcast&lt;/span&gt;
    &lt;span class="n"&gt;fanout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;multiple&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="appendix-c-configuring-qpidd"&gt;
&lt;h2&gt;Appendix C: Configuring Qpidd&lt;/h2&gt;
&lt;p&gt;Using the default prefixes, passing the following options to qpidd
(0.28 or later) would setup the required semantics for openstack:&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;queue&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;patterns&lt;/span&gt; &lt;span class="n"&gt;exclusive&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;queue&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;patterns&lt;/span&gt; &lt;span class="n"&gt;unicast&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;topic&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;patterns&lt;/span&gt; &lt;span class="n"&gt;broadcast&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&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.oasis-open.org/amqp/core/v1.0/amqp-core-complete-v1.0.pdf"&gt;http://docs.oasis-open.org/amqp/core/v1.0/amqp-core-complete-v1.0.pdf&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;[2] &lt;a class="reference external" href="http://people.apache.org/~gsim/oslo.messaging_scalability.pdf"&gt;http://people.apache.org/~gsim/oslo.messaging_scalability.pdf&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 work is licensed under a Creative Commons Attribution 3.0
Unported License.
&lt;a class="reference external" href="http://creativecommons.org/licenses/by/3.0/legalcode"&gt;http://creativecommons.org/licenses/by/3.0/legalcode&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
</description><pubDate>Fri, 06 Sep 2019 00:00:00 </pubDate></item><item><title>Policy in code</title><link>https://specs.openstack.org/openstack/oslo-specs/specs/newton/policy-in-code.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/oslo?searchtext=policy-in-code"&gt;https://blueprints.launchpad.net/oslo?searchtext=policy-in-code&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;For a while now there has been a desire to embed sane policy defaults in code
and allow for a policy file to override them. This would allow deployers to
only configure policies that they specifically want to override which could
reduce the size and complexity of those files. It would also allow for
generating a sample policy file which includes an exhaustive list of all
policies.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;There are two issues being addressed here:&lt;/p&gt;
&lt;p&gt;Given a deployed policy file it is not trivial to determine how much it differs
from the defaults that a project expects. This is due to there not being an
authoritative place to find all policies and their defaults. Some projects
provide sample files but they’re not always exhaustive. And it’s not easy to
diff a production policy file against the sample file after extensive
modification.&lt;/p&gt;
&lt;p&gt;Given an authenticated request context it is not possible to determine which
policies will pass. This is because policy checks are ad hoc throughout the
code with no central registry of all possible checks. And a policy file may not
have all policies listed as some may be left to fallback to the default rule.&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 that any policy that should be checked in the code can be
registered with the Enforcer class, similar to how configuration
registration is done. A new method for policy enforcement will be added which
errors if the policy being checked has not previosly been registered. Current
methods of policy loading from a file and policy checking will not be affected.&lt;/p&gt;
&lt;p&gt;Registration will require two pieces of data:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;The rule name, e.g. “compute:get” or “os_compute_api:servers:index”&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The rule, e.g. “rule:admin_or_owner” or “role:admin”&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Registration will optionally take a third piece of data:&lt;/p&gt;
&lt;ol class="arabic simple" start="3"&gt;
&lt;li&gt;&lt;p&gt;A description string. This can help guide admins with information on each
policy.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The rule name is needed for later lookups. The rule is necessary in order to
set the defaults and generate a sample file. The description can be added as a
comment to policy sample files.&lt;/p&gt;
&lt;p&gt;Registration will be done by passing a PolicyOpt class to
Enforcer.register_rule or a list of PolicyOpt’s to Enforcer.register_rules.&lt;/p&gt;
&lt;p&gt;As an example, based on how Nova might use 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="o"&gt;--&lt;/span&gt; &lt;span class="n"&gt;nova&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;policy&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;create&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;py&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;oslo_policy&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;policy&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;nova&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;policy&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;nova_policy&lt;/span&gt;

&lt;span class="n"&gt;server_policies&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="n"&gt;policy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PolicyOpt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rulename&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'os_compute_api:servers:create'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                     &lt;span class="n"&gt;rule&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'rule:admin_or_owner'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                     &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'Checked on POST /servers'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;policy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PolicyOpt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rulename&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'os_compute_api:servers:create:forced_host'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                     &lt;span class="n"&gt;rule&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'rule:admin_or_owner'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                     &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'Controls whether the forced_host '&lt;/span&gt;
                     &lt;span class="s1"&gt;'scheduler hint is allowed.'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;policy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PolicyOpt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rulename&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'os_compute_api:servers:create:attach_volume'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                     &lt;span class="n"&gt;rule&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'rule:admin_or_owner'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                     &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'Checks if a volume can be attached '&lt;/span&gt;
                     &lt;span class="s1"&gt;'during instance create.'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;policy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PolicyOpt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rulename&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'os_compute_api:servers:create:attach_network'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                     &lt;span class="n"&gt;rule&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'rule:admin_or_owner'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                     &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'Checks if a network can be attached '&lt;/span&gt;
                     &lt;span class="s1"&gt;'during instance create.'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;policy_engine&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;nova_policy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_policy&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="c1"&gt;# registration will error if a duplicate policy is defined&lt;/span&gt;
&lt;span class="n"&gt;policy_engine&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;register_rules&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;server_policies&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="o"&gt;--&lt;/span&gt; &lt;span class="n"&gt;nova&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;api&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;compute&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;servers&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;py&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;nova&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;policy&lt;/span&gt;

&lt;span class="n"&gt;policy_engine&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;policy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_policy&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="o"&gt;...&lt;/span&gt;
    &lt;span class="n"&gt;policy_engine&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;authorize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'os_compute_api:servers:create'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;creds&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# This would error because the policy is not registered&lt;/span&gt;
        &lt;span class="n"&gt;policy_engine&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;authorize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="s1"&gt;'os_compute_api:servers:create_not_registered'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;creds&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;pass&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;volume_to_attach&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;policy_engine&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;authorize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="s1"&gt;'os_compute_api:servers:create:attach_volume'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;creds&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The proposed change to oslo.policy is that the Enforcer class will gain two new
methods: “register_rule” and “register_rules”.  These methods will process and
store the registered policies.  The “load_rules” method will be modified to
merge rules loaded from policy files in with the registered defaults. Rules
loaded from files will overwrite registered defaults.&lt;/p&gt;
&lt;p&gt;An “authorize” method will be updated so that attempting to check against a
rule that doesn’t exist will be an error. In other words the default rule loses
its special status and is not a fallback for rules that are not defined. It
will still remain as a reference for other rules to use.&lt;/p&gt;
&lt;p&gt;A PolicyOpt class will be added which defines a policy to be registered. It
will initially hold rulenames, rules, and descriptions.&lt;/p&gt;
&lt;p&gt;Files to change:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;oslo_policy/policy.py&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Rather than modifying the Enforcer class in oslo_policy/policy.py a new Policy
class could be added which handles registration and contains a new “authorize”
method. The Policy class would mostly handle registration and storage of
policies and would proxy to Enforcer for loading policy from files and handling
the actual enforcement. Over time it may make sense to pull the loading of
policy from files out of the Enforcer class and into Policy.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="impact-on-existing-apis"&gt;
&lt;h3&gt;Impact on Existing APIs&lt;/h3&gt;
&lt;p&gt;A new “register” method will be added to the Enforcer class.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;There is no security impact from this change. The way that policies are
enforced does not change, just where they’re loaded from.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;Registration of policies from code will have a slight peformance at the time of
registration, but this should be no different than registering configuration
options&lt;/p&gt;
&lt;/section&gt;
&lt;section id="configuration-impact"&gt;
&lt;h3&gt;Configuration Impact&lt;/h3&gt;
&lt;p&gt;There is no direct configuration impact from this change. This change will
allow projects who have registered policies to not need a policy file in order
to use those defaults. This will allow deployers to trim down, or remove, their
policy files if they are running close to the defaults.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer Impact&lt;/h3&gt;
&lt;p&gt;It will not be required, but it will be encouraged, that projects switch to
registering policy rules before using them. So developers will need to get in
the habit of adding that registration before use, similar to adding a new
configuration option.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing-impact"&gt;
&lt;h3&gt;Testing Impact&lt;/h3&gt;
&lt;p&gt;Unit testing should be sufficient here. This adds a new capability that can be
used by other projects but it is not directly dependent on anything.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;alaski&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="milestones"&gt;
&lt;h3&gt;Milestones&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Target Milestone for completion:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;newton-1&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 PolicyOpt class to oslo_policy/policy.py&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add a “register_rule” method to Enforcer for registration of rules&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add a “register_rules” method to Enforcer for registration of rules&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update Enforcer.load_rules() to merge registered rules with file loaded rules&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add an “authorize” method to Enforcer which functions like “enforce” but
errors if the policy being checked has not been registered.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="incubation"&gt;
&lt;h2&gt;Incubation&lt;/h2&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;section id="adoption"&gt;
&lt;h3&gt;Adoption&lt;/h3&gt;
&lt;p&gt;Nova would like to use this functionality.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="library"&gt;
&lt;h3&gt;Library&lt;/h3&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;section id="anticipated-api-stabilization"&gt;
&lt;h3&gt;Anticipated API Stabilization&lt;/h3&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;The ability to register policy rules will be documented in developer facing
documentation. Any deployer facing changes will be the responsibility of
consuming projects to document as they switch over to using policy
registration.&lt;/p&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="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;Nova spec for this capability: &lt;a class="reference external" href="https://review.openstack.org/#/c/290155/"&gt;https://review.openstack.org/#/c/290155/&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 work is licensed under a Creative Commons Attribution 3.0
Unported License.
&lt;a class="reference external" href="http://creativecommons.org/licenses/by/3.0/legalcode"&gt;http://creativecommons.org/licenses/by/3.0/legalcode&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
</description><pubDate>Fri, 06 Sep 2019 00:00:00 </pubDate></item><item><title>Policy sample file generation</title><link>https://specs.openstack.org/openstack/oslo-specs/specs/newton/policy-sample-generation.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/oslo?searchtext=policy-sample-generation"&gt;https://blueprints.launchpad.net/oslo?searchtext=policy-sample-generation&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;It is useful to deployers to have a sample configuration file outlining all
available options, and it is a burden on projects to try to keep that sample
file up to date. It would be preferable to generate that file from policies
registered in the project in the same way that it’s done for configuration
options.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Projects which provide a sample policy file need to manually keep that up to
date with what’s being checked in the code. In practice it can often be out of
date. If all used policies are already registered in code that sample file
should just be generated.&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 few helpers to oslo.policy. These are intended to help
deployers maintain and trim their policy files.&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;An oslo-policy-sample-generator along the same lines as the
oslo-config-generator that exists in oslo.config. A console script
‘oslo-policy-sample-generator’ will be added to oslo.policy. This script
will look at the namespace(s) in an oslo.policy.policies entry point and
from there load in a list of oslo_policy.policy.RuleDefault objects. The
sample file will be generated from this list. RuleDefault objects may
include a description string which will be included as a comment. Output
will be in the yaml format since it can include comments.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A method for generating a policy file that contains the effective configured
policy. This will merge rules defined in a policy file with registered
default rules and output a full policy file with the result. By referencing
this file a deployer can know exactly how a rule is set.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A method for retrieving a list of policies loaded from a policy file which
match the default registered rules. These are policies that are not
necessary to be in a policy file so this output will help deployers trim
their file overrides.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A method for generating a yaml version of a policy file. This will read in
the current policy file(s) and output a yaml version of those rules. This
can be used to convert from a json format poliy file to yaml format. It must
be noted that rules are not sorted so the output may not be directly
diffable against the output of #1 or #2 above.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Files to change:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;oslo_policy/generator.py (new file)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;setup.cfg (register an entry point)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Policy sample files could continue to be maintained manually.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="impact-on-existing-apis"&gt;
&lt;h3&gt;Impact on Existing APIs&lt;/h3&gt;
&lt;p&gt;A new “oslo-policy-sample-generator” console script would be registered in
setup.cfg.  This doesn’t affect existing APIs, it is purely additive.&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="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None. This is done outside of a service running and serving requests.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="configuration-impact"&gt;
&lt;h3&gt;Configuration Impact&lt;/h3&gt;
&lt;p&gt;Sample policy.yaml files can be generated. This does not affect any current
configuration, it is a tool to help those who would like to configure their
policies.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer Impact&lt;/h3&gt;
&lt;p&gt;Projects wishing to take advantage of this will need to register all policy
checks in order to be included in the sample file. Developers should add this
registration for existing policy checks, and register new policy checks when
they are added.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing-impact"&gt;
&lt;h3&gt;Testing Impact&lt;/h3&gt;
&lt;p&gt;There is no direct testing impact here. However this does enable other projects
to have a test job which ensure that the sample file can be generated. Details
on how this might be accomplished will be documented as part of this change.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;alaski&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="milestones"&gt;
&lt;h3&gt;Milestones&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Target Milestone for completion:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;newton-1&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 oslo_policy/generator.py modeled after the one on oslo.config.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add policy sample generation.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add generation of effective policy.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add method for determining default rule definitions in a policy file.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add generation of yaml policy file from current policy file(s).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add an entry_point to oslo.policy setup.cfg to create a console script.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Document how a consuming project might configure themselves to use the file
generation ability, or setup a tox target to be used for testing.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="incubation"&gt;
&lt;h2&gt;Incubation&lt;/h2&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;section id="adoption"&gt;
&lt;h3&gt;Adoption&lt;/h3&gt;
&lt;p&gt;Nova would like to use this&lt;/p&gt;
&lt;/section&gt;
&lt;section id="library"&gt;
&lt;h3&gt;Library&lt;/h3&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;section id="anticipated-api-stabilization"&gt;
&lt;h3&gt;Anticipated API Stabilization&lt;/h3&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;The ability to generate policy files will be documented in developer facing
documentation. Any deployer facing changes will be the responsibility of
consuming projects to document as they switch over to using policy
registration.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;‘policy-in-code’ spec.&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;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This work is licensed under a Creative Commons Attribution 3.0
Unported License.
&lt;a class="reference external" href="http://creativecommons.org/licenses/by/3.0/legalcode"&gt;http://creativecommons.org/licenses/by/3.0/legalcode&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
</description><pubDate>Fri, 06 Sep 2019 00:00:00 </pubDate></item><item><title>Graduating oslo.i18n</title><link>https://specs.openstack.org/openstack/oslo-specs/specs/juno/graduate-oslo-i18n.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/oslo.i18n/+spec/graduate-oslo-i18n"&gt;https://blueprints.launchpad.net/oslo.i18n/+spec/graduate-oslo-i18n&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;oslo.i18n includes modules related to internationalization and
localization. The initial version focuses on translation utilities
built on top of the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;gettext&lt;/span&gt;&lt;/code&gt; module.&lt;/p&gt;
&lt;section id="library-name"&gt;
&lt;h2&gt;Library Name&lt;/h2&gt;
&lt;p&gt;This library includes some code that may eventually be useful outside
of OpenStack, but it does assert some policies and behaviors that are
specific to OpenStack, so it was placed in the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo&lt;/span&gt;&lt;/code&gt; namespace
package as &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo.i18n&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="contents"&gt;
&lt;h2&gt;Contents&lt;/h2&gt;
&lt;p&gt;The code for this library was exported from the incubator before we
started using specs documents. See
&lt;a class="reference external" href="https://opendev.org/openstack/oslo.i18n"&gt;https://opendev.org/openstack/oslo.i18n&lt;/a&gt;&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;openstack/common/gettextutils.py&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;tests/unit/test_gettextutils.py&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="early-adopters"&gt;
&lt;h2&gt;Early Adopters&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Keystone&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Doug Hellmann (doug-hellmann)&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="primary-maintainer"&gt;
&lt;h3&gt;Primary Maintainer&lt;/h3&gt;
&lt;p&gt;Each graduated library needs a primary maintainer. That may be the
same person who started the code, the person who graduated it, or it
may be someone who is taking over maintenance duties.&lt;/p&gt;
&lt;p&gt;If more than one person &lt;em&gt;who is not already on the oslo-core team&lt;/em&gt;
intends to participate as a core reviewer for the new library, list
them under “Other Contributors”.&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary Maintainer:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Mark McLoughlin (markmc)&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other Contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Doug Hellmann (doug-hellmann)&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="security-contact"&gt;
&lt;h3&gt;Security Contact&lt;/h3&gt;
&lt;p&gt;Each graduated library needs a contact for the OpenStack Vulnerability
Management team. It may be the same as the primary maintainer, an
existing Oslo team member who helps with security issues, or it may be
someone else on the development team for the new library.&lt;/p&gt;
&lt;p&gt;Talk with the Oslo and Vulnerability management teams about who the
person is, and make sure they agree to their participation before
proceeding.&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Security Contact:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Doug Hellmann (doug-hellmann)&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="milestones"&gt;
&lt;h3&gt;Milestones&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Target Milestone for completion:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Juno-1&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;&lt;a class="reference external" href="https://wiki.openstack.org/wiki/Oslo/CreatingANewLibrary"&gt;https://wiki.openstack.org/wiki/Oslo/CreatingANewLibrary&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Before the library was exported the API was changed so that
USE_LAZY is only evaluated once at startup. That won’t work for
libraries that are using their own translations, though, since they
may be initialized through imports that happen before the
application has an opportunity to establish whether it wants lazy
translation enabled. We need to correct that, probably by updating
_make_translation_func() to work with USE_LAZY at runtime again.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Since each consuming app and library will have their own copy of
the marker functions, we can remove the global marker functions
from gettextutils.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="adoption-notes"&gt;
&lt;h2&gt;Adoption Notes&lt;/h2&gt;
&lt;p&gt;The translation marker functions are essentially global variables that
are partial functions that have their translation domain argument
baked in. In the past, there was one global translation marker
function (&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;_()&lt;/span&gt;&lt;/code&gt;), which was created one time using the application’s
name. This was accomplished by having the string &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo&lt;/span&gt;&lt;/code&gt; replaced
with the application name when gettextutils.py was copied out of the
incubator into the application’s source tree. We won’t be copying
gettextutils.py into the application any more, and we will have
libraries creating their own translation marker functions, so we need
a way have multiple marker functions defined with &lt;em&gt;different&lt;/em&gt;
translation domains.&lt;/p&gt;
&lt;p&gt;The simplest approach to achieve that is to create a small
“integration module” in each consuming app or library that
instantiates the functions, and then have the app or library use that
module instead of using oslo.i18n directly. This is documented in the
usage.rst page for the library:
&lt;a class="reference external" href="http://docs.openstack.org/developer/oslo.i18n/usage.html"&gt;http://docs.openstack.org/developer/oslo.i18n/usage.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;In addition to the marker functions, some apps are using the
&lt;code class="xref py py-class docutils literal notranslate"&gt;&lt;span class="pre"&gt;Message&lt;/span&gt;&lt;/code&gt; class from &lt;code class="xref py py-mod docutils literal notranslate"&gt;&lt;span class="pre"&gt;gettextutils&lt;/span&gt;&lt;/code&gt;. That class is meant
to be a private implementation detail of lazy translation, and is not
exposed in the public API of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo.i18n&lt;/span&gt;&lt;/code&gt;. To convert a Message to a
translated string, use &lt;code class="xref py py-func docutils literal notranslate"&gt;&lt;span class="pre"&gt;translate()&lt;/span&gt;&lt;/code&gt;. To instantiate a new
Message, use &lt;code class="xref py py-func docutils literal notranslate"&gt;&lt;span class="pre"&gt;enable_lazy()&lt;/span&gt;&lt;/code&gt; to turn lazy translation on and then
use a property of a &lt;code class="xref py py-class docutils literal notranslate"&gt;&lt;span class="pre"&gt;TranslatorFactory&lt;/span&gt;&lt;/code&gt; (e.g.,
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;TranslatorFactory().primary&lt;/span&gt;&lt;/code&gt;) to get a translation function, which
will return a Message object.&lt;/p&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://blueprints.launchpad.net/oslo/+spec/log-messages-translation-domain-rollout"&gt;https://blueprints.launchpad.net/oslo/+spec/log-messages-translation-domain-rollout&lt;/a&gt;
is related but is not blocked on this blueprint.&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;Discussion at the Icehouse summit: &lt;a class="reference external" href="https://etherpad.openstack.org/p/icehouse-oslo-status"&gt;https://etherpad.openstack.org/p/icehouse-oslo-status&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Discussion at the Juno summit: &lt;a class="reference external" href="https://etherpad.openstack.org/p/juno-oslo-release-plan"&gt;https://etherpad.openstack.org/p/juno-oslo-release-plan&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/Oslo/Dependencies"&gt;https://wiki.openstack.org/wiki/Oslo/Dependencies&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/Oslo/GraduationStatus"&gt;https://wiki.openstack.org/wiki/Oslo/GraduationStatus&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This work is licensed under a Creative Commons Attribution 3.0
Unported License.
&lt;a class="reference external" href="http://creativecommons.org/licenses/by/3.0/legalcode"&gt;http://creativecommons.org/licenses/by/3.0/legalcode&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
</description><pubDate>Tue, 23 Apr 2019 00:00:00 </pubDate></item><item><title>Add Support for a Router-based Message Bus</title><link>https://specs.openstack.org/openstack/oslo-specs/specs/newton/amqp-dispatch-router.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/oslo?searchtext=amqp-dispatch-router"&gt;https://blueprints.launchpad.net/oslo?searchtext=amqp-dispatch-router&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This specification proposes changes to the existing AMQP 1.0 driver
that will allow message transport over a brokerless AMQP 1.0 message
bus.  The blueprint for the original driver can be found here &lt;a class="footnote-reference brackets" href="#id8" id="id1" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; and
the original architecture is described in &lt;a class="footnote-reference brackets" href="#id9" id="id2" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;2&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;.  The changes described
by this specification are a refactoring of the original design.  The
modified driver will still adhere to the AMQP 1.0 protocol standard in
order to remain agnostic to the particular message bus implementation.
Therefore support for existing AMQP 1.0 broker-based messaging
backends will be preserved.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;The Qpid C++ Broker was the only messaging service that supported the
AMQP 1.0 protocol when the original driver was developed.  As such,
the original driver was designed and tested only against a
broker-based message bus deployment.&lt;/p&gt;
&lt;p&gt;The AMQP 1.0 standard differs from its predecessors in that a broker
intermediary is no longer required.  This makes possible non-broker
based AMQP 1.0 messaging systems.  One such brokerless messaging
solution is a &lt;em&gt;message routed mesh&lt;/em&gt;. This messaging solution is
composed of multiple interconnected &lt;em&gt;message routers&lt;/em&gt; which route
messages to their destination using a shortest path algorithm.  Think
of it as an internet router, but at the message address level instead
of IP address.&lt;/p&gt;
&lt;p&gt;The message router is &lt;strong&gt;not a broker&lt;/strong&gt;.  It differs from broker
in the following significant ways:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;it is deployed with other routers in a mesh topology&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;the router is queue-less&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;it never accepts ownership of a message&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;any acknowledgment is end-to-end&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;availability is provided by redundancy, not clustering&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;it aims for availability of the communication pathways rather than of individual messages&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;it allows other message services to plug into the mesh&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;this includes brokers&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Unlike a broker a messaging mesh composed of a single router is
sub-optimal. The router is designed to be deployed as a mesh of
inter-connected router nodes.  Each router has dedicated TCP
connections to one or more of its peers.  Clients connect to the
mesh by connecting to one of the routers using a single TCP
connection.  When a client creates a subscription the address used
for the subscription is propagated beyond the locally-connected
router.  All routers in the mesh become aware of the subscription
and compute an optimal path from each router back to the consuming
client.  When another client publishes to that subscription the
routers forward the message along the appropriate path to the
subscriber which consumes the message.&lt;/p&gt;
&lt;p&gt;The following is a depiction of a four router mesh:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt; &lt;span class="o"&gt;+-----------+&lt;/span&gt;       &lt;span class="o"&gt;+-----------+&lt;/span&gt;
 &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;RPC&lt;/span&gt; &lt;span class="n"&gt;Server1&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;       &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;RPC&lt;/span&gt; &lt;span class="n"&gt;Caller1&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
 &lt;span class="o"&gt;+-----+-----+&lt;/span&gt;       &lt;span class="o"&gt;+----+------+&lt;/span&gt;
       &lt;span class="o"&gt;|&lt;/span&gt;                  &lt;span class="o"&gt;|&lt;/span&gt;
       &lt;span class="o"&gt;|&lt;/span&gt;                  &lt;span class="o"&gt;|&lt;/span&gt;
   &lt;span class="o"&gt;+---&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="o"&gt;----+&lt;/span&gt;         &lt;span class="o"&gt;+---&lt;/span&gt;&lt;span class="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;Router&lt;/span&gt; &lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="c1"&gt;#########+Router B|&lt;/span&gt;
   &lt;span class="o"&gt;+---+----+&lt;/span&gt;         &lt;span class="o"&gt;+----+---+&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;------+&lt;/span&gt;
       &lt;span class="c1"&gt;#    ##       ##    #            |&lt;/span&gt;
       &lt;span class="c1"&gt;#      ##   ##      #        +---+--+&lt;/span&gt;
       &lt;span class="c1"&gt;#        ##         #        |Broker|&lt;/span&gt;
       &lt;span class="c1"&gt;#      ##  ##       #        +------+&lt;/span&gt;
       &lt;span class="c1"&gt;#    ##       ##    #&lt;/span&gt;
   &lt;span class="o"&gt;+---+----+&lt;/span&gt;         &lt;span class="o"&gt;+-----+--+&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;------+&lt;/span&gt;
   &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;Router&lt;/span&gt; &lt;span class="n"&gt;C&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="c1"&gt;#########+Router D|  +-----+-----+&lt;/span&gt;
   &lt;span class="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;RPC&lt;/span&gt; &lt;span class="n"&gt;Caller2&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
       &lt;span class="o"&gt;^&lt;/span&gt;                    &lt;span class="o"&gt;^&lt;/span&gt;     &lt;span class="o"&gt;+-----------+&lt;/span&gt;
       &lt;span class="o"&gt;|&lt;/span&gt;                    &lt;span class="o"&gt;|&lt;/span&gt;
       &lt;span class="o"&gt;|&lt;/span&gt;                    &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="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;RPC&lt;/span&gt; &lt;span class="n"&gt;Caller3&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;              &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;RPC&lt;/span&gt; &lt;span class="n"&gt;Server2&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;+-----------+&lt;/span&gt;              &lt;span class="o"&gt;+-----------+&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The ‘#’ denote the inter-router TCP connections among Router A, B, C,
and D.  Router A has a single RPC server client attached.  Router B
has both an RPC caller and a broker attached.  Another RPC caller is
attached to Router C. An RPC server and an RPC caller are attached to
Router D.&lt;/p&gt;
&lt;p&gt;Since shortest path routing is used RPC call/cast messages from RPC
Caller3 to RPC Server1 would only transit Router A and Router C.
Likewise RPC calls from Caller1 to Server2 would transit Router B and
Router D.  RPC Caller2 invoking a method on Server2 would only transit
Router D.  In this example notice that only those routers along the
shortest path between two communicating endpoints are involved in the
message transfer.  This provides for a degree of parallelism not
possible when using a single broker messaging service.&lt;/p&gt;
&lt;p&gt;Note well that when a message transits a router on its way to its
final destination no queueing is done.  To be specific, none of the
routers along the path claim ownership of the message - i.e. the
routers do not acknowledge the message.  Instead the ack from the
consuming client is propagated back through the mesh to the origin
sender.  In other words, the router mesh does &lt;em&gt;end-to-end
acknowledgment&lt;/em&gt;. In contrast a broker &lt;em&gt;does&lt;/em&gt; claim ownership of the
message. However, an ack coming from the broker does not guarantee
that the message will be consumed.  It merely indicates that the
message has been queued.&lt;/p&gt;
&lt;p&gt;Since routers compute the optimal path for a message it is possible to
configure redundant paths across the messaging mesh. By deploying
the routers over a physically redundant network it becomes possible to
suffer a degree of infrastructure loss without affecting the messaging
service.  Given that the routers themselves are stateless there is no
need for a clustering capability as there is in broker deployments.
While the mesh may be partitioned due to infrastructure failure,
there is no possibility of ‘split-brain’ occurring as there is no
master/slave relationship among connected routers.  All routers are
equal peers.&lt;/p&gt;
&lt;p&gt;One limitation of a router mesh is that it cannot provide a message
store-and-forward service since the routers are queue-less.  However
brokers provide excellent store-and-forward capabilities and can be
integrated into the router mesh for exactly that purpose.&lt;/p&gt;
&lt;p&gt;Support for integrated brokers are not a target for the Newton
release.  Therefore only limited support for Notification traffic will
be provided when using a routed mesh as a messaging backend.  Since
the mesh cannot store a notification message any attempt to publish a
notification for which there is no active subscriber will result in a
message delivery failure. For those applications which cannot tolerate
loss of a notification message it is recommended to use a broker as
the messaging backend for the notification service.  Since it is
possible to configure different messaging backends for RPC and
Notifications, it is possible to use a mesh for RPC traffic and a
broker for Notification traffic.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Three issues need to be resolved in the driver in order to support RPC
over a routed messaging mesh:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;optimal message addressing&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;credit management&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;undeliverable messages&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;section id="addressing"&gt;
&lt;h3&gt;Addressing&lt;/h3&gt;
&lt;p&gt;The current addressing scheme embeds the message delivery semantics
into the prefix of the address.  This prefix is used by the Qpid C++
Broker to automatically provision the proper node - either queue or
topic - for a given publish/subscribe request.  For more detail refer
to &lt;a class="footnote-reference brackets" href="#id9" id="id3" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;2&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The qpidd broker identifies itself during connection set up it will be
possible to introduce a new addressing syntax while preserving the
existing syntax for backward compatibility. The original address
syntax used when connected to qpidd will remain unchanged to allow for
rolling upgrades.  The new address syntax will only be used when the
driver connects to a router mesh.  A configuration option will be
provided to manually select between the two addressing modes if
desired.&lt;/p&gt;
&lt;p&gt;When comparing addresses the router employs a &lt;em&gt;longest prefix match&lt;/em&gt;
algorithm. In contrast traditional brokers tend to use either a
pattern match or a simple exact match.  The router address syntax will
use the prefix of the address as an address space classification.&lt;/p&gt;
&lt;p&gt;There are a few additional points to consider for routable addressing
that do not apply for broker addressing:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Other applications may reside on the same mesh.  The addressing
scheme should be designed to avoid collisions with an address space
in use by a completely separate set of applications.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Application aware routing.  It should be possible to distinguish
RPC-related traffic from Notification traffic at the address level.
This will allow the routers to route notification traffic to a
broker(s) while RPC messages can travel point to point.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Configurable routing subdomains.  It should be possible to further
partition traffic on a per-project basis.  This could provide some
traffic isolation between projects as well as allow for parallel
oslo.messaging buses on the same mesh.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And like the existing address structure the delivery semantics
(e.g. fanout, direct, shared, etc.) must be provided to the mesh in
order to ensure the desired delivery pattern is used.&lt;/p&gt;
&lt;p&gt;For RPC services there are 4 message delivery patterns that addressing
must allow:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;fanout&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;direct to a given RPC server&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;a shared subscription (e.g. shared queue)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;RPC reply&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For Notification services there is only one delivery pattern: shared
subscription.&lt;/p&gt;
&lt;p&gt;The following address syntax is proposed for the above patterns with
the exception of RPC reply:&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;Use&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Format&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;RPC Fanout&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;openstack.org/om/rpc/multicast/$EXCHANGE/$TOPIC&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;RPC Server&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;openstack.org/om/rpc/unicast/$EXCHANGE/$TOPIC/$SERVER&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;RPC Shared&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;openstack.org/om/rpc/anycast/$EXCHANGE/$TOPIC&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Notifications&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;openstack.org/om/notify/anycast/$EXCHANGE/$TOPIC.$PRIORITY&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The prefix ‘openstack.org’ establishes the root domain of the address
space and is reserved for use only by OpenStack applications.  The
‘om’ tag further classifies this address as belonging to the
oslo.messaging service.  Reserving the address space prefixed by the
string ‘openstack.org/om’ for oslo.messaging’s use will avoid
collisions should other applications also use the routing mesh.&lt;/p&gt;
&lt;p&gt;The ‘rpc’ and ‘notify’ segments classify the service address space.
The ‘rpc’ and ‘notify’ tags will be used by the mesh to identify the
service.  This means that the mesh may send notification traffic to a
broker while RPC traffic issent point to point.&lt;/p&gt;
&lt;p&gt;The ‘unicast’, ‘multicast’, and ‘anycast’ keywords determine the
messaging semantics that need to be applied when delivering a message.
‘unicast’ causes the message is to be delivered to one subscriber.
‘anycast’ causes the message to be delivered to one subscriber among
many &lt;a class="reference internal" href="#scheduling" id="id4"&gt;&lt;span&gt;[Scheduling]&lt;/span&gt;&lt;/a&gt;.  For ‘multicast’ the router(s) will deliver a copy
of the message to all subscribers.&lt;/p&gt;
&lt;div role="list" class="citation-list"&gt;
&lt;div class="citation" id="scheduling" 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;Scheduling&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;When serving multiple subscribers to a given queue
most brokers employ a &lt;em&gt;round-robin&lt;/em&gt; distribution policy. A
broker can guarantee that messages are evenly distributed to
each subscriber since the broker is the single point of
distribution.  There is no single ‘central distributer’ in a
messaging mesh, so a mesh employs a different approach to
‘anycast’ distribution. For example, a mesh will prioritize
deliveries based on the lowest path cost.  This means that
messages will be distributed to those subscribers with the
lowest link cost/fewer inter-router hops first.  A mesh may
also monitor credit levels across all consumers and detect
when individual consumers are not keeping up with the message
arrival rate (due to message processing delays).  This allows
the router to deliver the message to a different client - one
that is not exhibiting such a high backlog.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The values for $EXCHANGE, $TOPIC, and $SERVER are all taken from the
Target used for the subscription (or the destination when
call/casting).  It is possible to use the $EXCHANGE value to provide
further isolation of traffic based on the application’s configuration.&lt;/p&gt;
&lt;p&gt;The addressing for the RPC Reply will not use any of the above address
formats. RPC Reply addressing will work as it does today: the RPC
Reply address is dynamically assigned to the driver by the message bus
(broker or router) and is considered an opaque value.  The driver will
simply set the RPC Call message’s reply-to field to this value before
sending the message. The IncomingMessage will use this reply-to value
as the reply message’s address.&lt;/p&gt;
&lt;p&gt;A single reply address will be used per TCP connection to the
bus as is done today. RPC Call messages will be assigned a unique
message identifier that will be written to the ‘id’ field of the
message header.  The RPC Server will place this identifier in the
reply message’s ‘content-id’ field before sending it.  Received reply
messages will be de-muxed using the message’s ‘content-id’ value and
sent to the proper waiter.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="credit-management"&gt;
&lt;h3&gt;Credit Management&lt;/h3&gt;
&lt;p&gt;Since the router mesh is unable to queue messages it must not accept
messages from publishers unless there is a consumer ready to accept
that message.  The mesh can limit the number of messages a publisher can
send to the mesh by controlling the amount of &lt;em&gt;message credit&lt;/em&gt; that is
granted to the publisher.  The mesh will provide one credit for each
message it will accept from the publisher. The publisher cannot send a
message to the mesh unless it has credit to do so.&lt;/p&gt;
&lt;p&gt;The mesh itself does not create credit as it has no capacity to store
messages.  Credit is made available to the mesh by the subscribing
clients.  A subscriber grants credit to the mesh - one credit for each
message it is willing to consume.  The mesh “proxies” the credit to
the client(s) that want to publish to the address the subscriber is
consuming from.  Therefore the router will not grant credit to a
message publisher unless there is at least one consumer subscribed to
the message’s address that has granted credit to the mesh.  This
allows the mesh to block a sender until the consumer is ready to
consume from it.&lt;/p&gt;
&lt;p&gt;The driver will provide credit for each subscription that is created.
Each server maintains its own subscriptions for its Target.  There is
also the per-transport shared RPC reply address subscription.  Each
subscription will make credit available to the router mesh which will
in turn distribute it among clients publishing to those addresses.&lt;/p&gt;
&lt;p&gt;It is critical that the shared RPC reply subscription always has credit
available for replies coming from the RPC Servers.  Otherwise an RPC
Server can block attempting to send a reply to one particular client.
This would result in all RPC calls to that server also blocking
(i.e. head-of-line blocking). Fortunately the RPC call pattern is
self-limiting: a caller is blocked from sending any further requests
until a reply is received (or the call times out).  This means that
back pressuring the RPC callers via reply subscription credit is
probably unnecessary. Therefore the driver will grant a large batch of
credit to the reply subscription.  The driver will monitor the credit
level as messages arrive and are passed up to the client, replenishing
credit as needed. The amount of credit will be configurable with a default
of 200 credits.  This default may be altered in the course of tuning
the driver’s performance.&lt;/p&gt;
&lt;p&gt;RPC Server and Notification subscriptions cannot be as generous with
credit as the reply subscription.  A server needs to apply some
backpressure in the event that it fails to keep up with the incoming
message flow. Otherwise too many incoming messages will be buffered in
the driver. The goal will be to limit the amount of internal message
buffering per subscription while minimizing the performance impact.&lt;/p&gt;
&lt;p&gt;Each RPC Server and Notification subscription will be granted a batch
of 100 credits by default.  This default is configurable and may be
adjusted in the course of tuning. The driver will replenish credit
back to the default level once credit drops below one half of the
default level.  The credit level check will be performed at the point
where the client acknowledges the message.  This will limit the worst
case buffering to about 300 messages per RPC server (direct, fanout,
and shared) and 100 messages per Notification topic and priority
(shared).&lt;/p&gt;
&lt;p&gt;For tuning purposes the driver will maintain a count of detected
credit stalls - when the amount of outstanding credit hits zero before
the driver can replenish it.  The driver will issue a debug log
message when this event is detected.&lt;/p&gt;
&lt;p&gt;The credit levels must also be accounted for at the publisher’s
side. If no credit is available the driver must not allow the
publisher to send a message. Otherwise there would be no way to
prevent an unlimited number of messages from being buffered in the
driver waiting to be sent to the mesh.  Therefore the driver will
honor the credit limits imposed by the mesh and block senders until
credit is made available.&lt;/p&gt;
&lt;p&gt;An RPC caller already blocks until the reply is received or the call
times out. If no credit is made available during the timeout period
the driver will simply fail the call operation as it would if no reply
were received in time.&lt;/p&gt;
&lt;p&gt;Unlike an RPC call an RPC cast does not wait for a reply. When casting
the client will also be blocked if no credit is available.  In the
case of a &lt;em&gt;non-fanout&lt;/em&gt; cast the caller will also wait until an
acknowledgment is received from the destination (not the mesh).&lt;/p&gt;
&lt;p&gt;A &lt;em&gt;fanout&lt;/em&gt; cast will behave just like the cast case, except that the
acknowledgement comes from the mesh itself rather than the
destination.  This is a behavior of the mesh meant to prevent a return
acknowledgement “storm”.&lt;/p&gt;
&lt;p&gt;The driver will also obey the credit rules when RPC replies are sent.
The RPC Server will block when responding if no credit is available.&lt;/p&gt;
&lt;p&gt;There is one other credit-related issue that must be addressed by the
driver: what if credit is not made available in a timely manner?  Or
credit never arrives due to the lack of a consumer?&lt;/p&gt;
&lt;p&gt;The existing broker-based solutions address the lack of a consumer by
automatically creating a queue in response to a publish request. By
auto-creating a queue the broker allows the application to ‘ride out’
any delay in the arrival of a legitimate consumer.  Even if the
consumer never arrives the broker will accept the message.  This means
that as long as a broker is present a publisher will not have to wait
for a consumer to arrive.&lt;/p&gt;
&lt;p&gt;There is no telling how many applications have come to rely on this
behavior.  Unless the driver compensates for this in some way it is
likely that things will break badly.&lt;/p&gt;
&lt;p&gt;The driver will account for this by mandating a timeout for &lt;em&gt;every
message that is sent to the router mesh&lt;/em&gt;. If credit does not arrive
within the timeout an exception will be raised indicating that the
operation failed.&lt;/p&gt;
&lt;p&gt;The only caveat to the above is that the oslo.messaging API does not
&lt;em&gt;enforce&lt;/em&gt; use of a timeout when sending messages.  There are two send
methods in the base &lt;strong&gt;Driver&lt;/strong&gt; class: &lt;em&gt;send()&lt;/em&gt; and
&lt;em&gt;send_notification()&lt;/em&gt;.  In addition the &lt;strong&gt;IncomingMessage&lt;/strong&gt; class has
a &lt;em&gt;reply()&lt;/em&gt; method that is used to send RPC replies.  Only the
&lt;em&gt;send()&lt;/em&gt; method accepts a timeout parameter, the rest do not. In the
cases where a timeout value is not provided via the API the driver
will apply a default value. If the &lt;em&gt;send()&lt;/em&gt; method is invoked without
supplying a timeout value then the default timeout will be applied by
the driver.&lt;/p&gt;
&lt;p&gt;The proposed default timeout for RPC calls and casts (either with or
without fanout) will be 30 seconds.  If no credit arrives before the
timeout expires either a &lt;strong&gt;MessagingTimeout&lt;/strong&gt; or a
&lt;strong&gt;MessageDeliveryFailure&lt;/strong&gt; exception will be raised.  The
&lt;strong&gt;MessagingTimeout&lt;/strong&gt; exception will only be thrown in the case of a
&lt;em&gt;send()&lt;/em&gt; call that provided a timeout value.  The
&lt;strong&gt;MessageDeliveryFailure&lt;/strong&gt; will be raised in all other cases.&lt;/p&gt;
&lt;p&gt;Note also that the timeout will also encompass the time spent waiting
for the RPC reply to arrive.&lt;/p&gt;
&lt;p&gt;When sending a reply via the &lt;em&gt;reply()&lt;/em&gt; method it is critical that the
RPC Server never block indefinitely waiting for credit from the RPC
client.  This will cause the entire RPC server to hang, affecting other
clients with pending requests.&lt;/p&gt;
&lt;p&gt;Although the RPC client’s driver will grant a large amount of credit to
the reply subscription there still exists the possibility that the
client has become unreachable since the RPC call was processed.  The
client may have crashed or the mesh may have lost connectivity.  To
prevent this a default timeout will also be applied to the RPC
&lt;em&gt;reply()&lt;/em&gt; call.  Like an RPC cast, if no credit is made available or
no acknowledgment is received from the peer before the timeout expires
the reply will fail.  Unlike an RPC cast no exception will be thrown
since there is no way for the application to recover.  Instead an
error will be logged.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="undeliverable-messages"&gt;
&lt;h3&gt;Undeliverable Messages&lt;/h3&gt;
&lt;p&gt;It is possible that the destination of a message may become
unreachable while the message transits the router mesh.  The consumer
may have crashed or a network failure may occur leaving the message
with nowhere to go.  In this case the router mesh will send a negative
acknowledgment back to the original sender.  This takes the form of an
AMQP 1.0 disposition performative with a terminal delivery state of
either MODIFIED or RELEASED.  These states notify the original sender
that the message was never delivered.  Thus the message can be
retransmitted at a later time without risk of duplication.  However
there is no guarantee that &lt;em&gt;message order&lt;/em&gt; will be preserved on
retransmit.&lt;/p&gt;
&lt;p&gt;Re-delivery will not be a goal of the Newton release.  The driver will
simply treat the reception of a RELEASED or MODIFIED disposition as a
message delivery failure.  This may be addressed in a different
fashion in a future release.&lt;/p&gt;
&lt;p&gt;[Actually, it may be possible to safely resend RPC casts since cast
does &lt;em&gt;not&lt;/em&gt; guarantee strict message ordering. For now this is TBD]&lt;/p&gt;
&lt;p&gt;The disposition will be used by the driver to implement the optional
‘requeue’ feature defined by oslo.messaging.  When a consumer invokes
the requeue method on an incoming message the driver will send a
disposition with terminal state RELEASED back to the publisher.&lt;/p&gt;
&lt;p&gt;What actually happens to the released message depends on the
capability of the message bus.  A broker will simply re-queue the
message.  A mesh may either forward the message to another consumer
(if present), or proxy the RELEASED state back to the publisher.  As
described earlier the driver will treat a RELEASED state as a message
delivery failure in Newton.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;There are other alternative messaging backends that at first glance
appear to offer similar capabilities as a routed mesh.  ZeroMQ, for
example, is also a non-brokered solution.  ZeroMQ also provides a
point to point messaging pattern that can be used for RPC services.
However, there are some significant differences between ZeroMQ and a
routed mesh.&lt;/p&gt;
&lt;p&gt;First, clients of a routed mesh only require a single TCP
connection to the router mesh, whereas the ZeroMQ implementation
uses a TCP connection per destination.  In other words a ZeroMQ RPC
Server will require a TCP connection to every RPC client it
communicates with.  Therefore ZeroMQ will require more TCP-related
resources as the number of RPC Servers and clients scale up.&lt;/p&gt;
&lt;p&gt;Second, in a router mesh there is no need to have all clients
reachable via TCP as is required by ZeroMQ.  The router mesh does
message-layer routing, not IP address routing. This allows clients and
servers on separate private IP subnets to interoperate using the
router mesh as a bridge.  These subnets do not need to be visible
to each other over an IP mesh.  For example, RPC Servers may reside
on a private subnet in Company A, while the RPC Clients reside on a
different private subnet in Company B.  This can be accomplished by
ZeroMQ but would require proper configuration of firewalls and
NAT’ing.&lt;/p&gt;
&lt;p&gt;It also provides for better load-balancing where a call is made on a
service group. The client is not responsible for determining which
service instance in the group should get the message.&lt;/p&gt;
&lt;p&gt;Lastly, the router mesh inherently provides service discovery.  A
dedicated service discovery component is not needed.&lt;/p&gt;
&lt;p&gt;A federated broker network is another messaging bus that is somewhat
like the router mesh.  However a routed mesh is a much better
solution for distributed messaging. In fact message routing was
developed explicitly to provide a better solution than broker
federation for distributed messaging.  Versions of AMQP previous to
1.0 &lt;em&gt;required&lt;/em&gt; a broker intermediary. Therefore the only way to
distribute messages prior to 1.0 was to develop a broker-based routing
solution.  The 1.0 version of the protocol drops this broker
intermediary requirement and makes a routed messaging mesh
possible. A network of lightweight, stateless message switches
augmented by brokers only where store and forward is needed can
completely supplant a federated broker deployment in terms of
functionality.&lt;/p&gt;
&lt;p&gt;Messages travelling through a broker federation are queued at each
node, unlike a routed mesh.  This increases latency, hurts
throughput, and removes the possibility of end-to-end
acknowledgment. This makes it harder for the ‘client’ to know when to
resend the request and for the ‘service’ to know when to resend a
response. It can lead to trying to make the broker replicate all
messages which makes scaling harder.&lt;/p&gt;
&lt;p&gt;The router mesh is not the right solution for all deployments.  A
single broker is a much simpler solution if it can meet a deployment’s
messaging requirements.  ZeroMQ will be a good choice for those
distributed deployments not bound by routing or TCP resource
constraints.  Likewise there will be deployments where a router
mesh will be the optimal messaging backend.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="impact-on-existing-apis"&gt;
&lt;h3&gt;Impact on Existing APIs&lt;/h3&gt;
&lt;p&gt;The existing API should not require any changes.  These changes will
preserve compatibility with existing qpidd-based deployments.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;From the driver point-of-view there will be no change in the security
model.  The driver already supports both TLS server and client
authentication. It also supports SASL-based authentication, which
includes Kerberos support.  The driver conforms to the security model
as defined by the AMQP 1.0 specification and will work with any
compliant messaging service.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;Any performance impact should be limited to the users of the AMQP 1.0
driver.  Users of other drivers such as RabbitMQ will not be affected.
There may be an effect on the performance as it now stands with the
Qpid broker, however every effort will be made to minimize this.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="configuration-impact"&gt;
&lt;h3&gt;Configuration Impact&lt;/h3&gt;
&lt;p&gt;New configuration items for credit and timeout duration will be added.
The default values for these options will be determined as the driver
is tuned for performance.  These items include:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Credit limit for Reply subscription (Default: 200)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Credit limit for Server subscriptions (Default: 100 per subscription)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Driver-level default RPC call/cast timeout (Default: 30 seconds)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Driver-level default RPC response timeout (Default: 10 seconds)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Driver-level default Notification timeout (Default: 30 seconds)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Addressing Mode (Default: dynamic)&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 new features added to oslo.messaging that must be implemented via
driver modification would need to be implemented in this driver as
well. If such new features require behavior unique to a broker
backend it may be impossible to support them when using a routed
mesh.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing-impact"&gt;
&lt;h3&gt;Testing Impact&lt;/h3&gt;
&lt;p&gt;The Qpid Dispatch Router will be used as the messaging backend for
testing.  More information about this router can be found here &lt;a class="footnote-reference brackets" href="#id10" id="id5" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;3&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The Qpid Dispatch Router will need to be available in the CI
environment in order to fully test this driver.  This is gated by
inclusion of the router packages and its dependencies into Debian
testing.  The Apache Qpid community is in the process of submitting
the following packages for inclusion in Debian:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;qpid-dispatch-router&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;qpid-dispatch-router-tools&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;python-qpid-proton&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;qpid-proton-c&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;pyngus&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These packages are already available in the EPEL repositories.&lt;/p&gt;
&lt;p&gt;The driver must pass the existing amqp1 driver tests.&lt;/p&gt;
&lt;p&gt;The driver must pass the gate-oslo.messaging-src-dsvm-full and
gate-oslo.messaging-dsvm-functional tests.&lt;/p&gt;
&lt;p&gt;Devstack already supports using a standalone router &lt;a class="footnote-reference brackets" href="#id11" id="id6" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;4&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;.  It may be
necessary to add the qpidd broker as the notification transport in
order to pass the above gate tests.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;&lt;a class="reference external" href="mailto:kgiusti%40gmail.com"&gt;kgiusti&lt;span&gt;@&lt;/span&gt;gmail&lt;span&gt;.&lt;/span&gt;com&lt;/a&gt;  (kgiusti on IRC)&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;&lt;a class="reference external" href="mailto:ansmith%40redhat.com"&gt;ansmith&lt;span&gt;@&lt;/span&gt;redhat&lt;span&gt;.&lt;/span&gt;com&lt;/a&gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="milestones"&gt;
&lt;h3&gt;Milestones&lt;/h3&gt;
&lt;p&gt;Target Milestone for completion: newton&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 new addressing syntax&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Implement credit handling&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Implement new configuration items&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;Functional test integration&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Upstream CI integration&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="incubation"&gt;
&lt;h2&gt;Incubation&lt;/h2&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;section id="adoption"&gt;
&lt;h3&gt;Adoption&lt;/h3&gt;
&lt;p&gt;It is unlikely that this driver will be adopted in the majority of use
cases as a single broker is usually sufficient. Adoption is more
likely among those deployments that have medium to large clouds
deployed across a distributed mesh topology.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="library"&gt;
&lt;h3&gt;Library&lt;/h3&gt;
&lt;p&gt;oslo.messaging&lt;/p&gt;
&lt;/section&gt;
&lt;section id="anticipated-api-stabilization"&gt;
&lt;h3&gt;Anticipated API Stabilization&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;The library’s AMQP 1.0 documentation will need to be updated for the new backend &lt;a class="footnote-reference brackets" href="#id12" id="id7" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;5&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;The driver will require no additional dependencies.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;aside class="footnote-list brackets"&gt;
&lt;aside class="footnote brackets" id="id8" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id1"&gt;1&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/oslo.messaging/+spec/amqp10-driver-implementation"&gt;https://blueprints.launchpad.net/oslo.messaging/+spec/amqp10-driver-implementation&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id9" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;2&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class="backrefs"&gt;(&lt;a role="doc-backlink" href="#id2"&gt;1&lt;/a&gt;,&lt;a role="doc-backlink" href="#id3"&gt;2&lt;/a&gt;)&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://opendev.org/openstack/oslo-specs/src/branch/master/specs/juno/amqp10-driver-implementation.rst"&gt;https://opendev.org/openstack/oslo-specs/src/branch/master/specs/juno/amqp10-driver-implementation.rst&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id10" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id5"&gt;3&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="http://qpid.apache.org/components/dispatch-router/index.html"&gt;http://qpid.apache.org/components/dispatch-router/index.html&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id11" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id6"&gt;4&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://opendev.org/openstack/devstack-plugin-amqp1/commit/142d975ac38a6a22c3a1eee6f43009d2098b270d"&gt;https://opendev.org/openstack/devstack-plugin-amqp1/commit/142d975ac38a6a22c3a1eee6f43009d2098b270d&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id12" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id7"&gt;5&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="http://docs.openstack.org/developer/oslo.messaging/AMQP1.0.html"&gt;http://docs.openstack.org/developer/oslo.messaging/AMQP1.0.html&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;/aside&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This work is licensed under a Creative Commons Attribution 3.0
Unported License.
&lt;a class="reference external" href="http://creativecommons.org/licenses/by/3.0/legalcode"&gt;http://creativecommons.org/licenses/by/3.0/legalcode&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
</description><pubDate>Tue, 23 Apr 2019 00:00:00 </pubDate></item><item><title>Support policy files in YAML</title><link>https://specs.openstack.org/openstack/oslo-specs/specs/newton/policy-in-yaml.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/oslo?searchtext=policy-yaml"&gt;https://blueprints.launchpad.net/oslo?searchtext=policy-yaml&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;JSON is great for a wire format, but awful for a configuration file.
oslo.policy can easily also support a safe subset of YAML.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;The policy files for the services can be complicated and hard to use. Even
knowing what operations are protected by what rules is difficult since the
operation name (e.g., &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;identity:create_user&lt;/span&gt;&lt;/code&gt;) isn’t the same as the
operation the user performs (e.g., &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PUT&lt;/span&gt; &lt;span class="pre"&gt;/v3/users&lt;/span&gt;&lt;/code&gt;). The sample policy files
would be a lot more usable if we could simply put a comment in the file saying
what the user operation is for the rule, but the only format allowed (JSON)
doesn’t support comments.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;As a deployer, I should be able to comment the policy file with descriptions
for my custom roles and rules.&lt;/p&gt;
&lt;p&gt;As a developer, I should be able to provide a sample policy file that’s
self-describing. As in, add comments to the sample policy file.&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;Rather than parse the policy file using the JSON parser, oslo.policy will
parse it using the YAML parser (provided by PyYAML). Since JSON is a subset of
YAML existing JSON files will continue to work. Projects and deployers can
switch to simplified YAML and document using comments if they want.&lt;/p&gt;
&lt;p&gt;&lt;cite&gt;oslo.policy&lt;/cite&gt; will be changed to use PyYAML’s &lt;cite&gt;safe_load()&lt;/cite&gt; to parse the
policy file rather than the JSON parser ( &lt;cite&gt;jsonutils.loads()&lt;/cite&gt; ).&lt;/p&gt;
&lt;p&gt;For some reason the name of the method to read the policy file includes the
format. This was incorrect to begin with and is made even less accurate since
the format is YAML, so rename &lt;cite&gt;load_json()&lt;/cite&gt; to &lt;cite&gt;load()&lt;/cite&gt; (keeping the old
method name around but deprecated, using debtcollector).&lt;/p&gt;
&lt;p&gt;oslo.policy defines a &lt;cite&gt;policy_file&lt;/cite&gt; config option which defaults to
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;policy.json&lt;/span&gt;&lt;/code&gt;. So the default behavior is to look for a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;policy.json&lt;/span&gt;&lt;/code&gt;
file. The new default behavior will look first for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;policy.yaml&lt;/span&gt;&lt;/code&gt; and if that
doesn’t exist it will look for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;policy.json&lt;/span&gt;&lt;/code&gt;. As such, the default will be
removed and the new default behavior will be described in the help text.&lt;/p&gt;
&lt;p&gt;Files to change:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;oslo_policy/policy.py&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;oslo_policy/opts.py&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;requirements.txt&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 preprocess the JSON files to remove lines that look like comments.
But then the format isn’t really JSON and is not a standard format.&lt;/p&gt;
&lt;p&gt;We could have separate loaders for JSON vs YAML and use the parser based on
the file extension. This is possible but is unnecessary since JSON is a subset
of YAML.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="impact-on-existing-apis"&gt;
&lt;h3&gt;Impact on Existing APIs&lt;/h3&gt;
&lt;p&gt;The &lt;cite&gt;oslo_policy.policy.Rules&lt;/cite&gt; class’s &lt;cite&gt;load_json&lt;/cite&gt; method will be renamed to
&lt;cite&gt;load&lt;/cite&gt;. &lt;cite&gt;load_json&lt;/cite&gt; will be deprecated.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;In its most general form, YAML allows the document to contain executable code
that’s then run. We don’t want our policy files to be allowed to contain
executable code. As such, we’ll use &lt;cite&gt;safe_load()&lt;/cite&gt; instead of &lt;cite&gt;load()&lt;/cite&gt;.&lt;/p&gt;
&lt;p&gt;See &lt;a class="reference external" href="http://pyyaml.org/wiki/PyYAMLDocumentation#LoadingYAML"&gt;http://pyyaml.org/wiki/PyYAMLDocumentation#LoadingYAML&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;I don’t know if the YAML parser is a lot slower, but since it supports several
representations for the same result I assume it takes more work to parse it.
The policy file is read when the server starts and also whenever the file
changes (it used to be read on every request, but that’s been changed to check
the modification time), so I don’t think this is going to be noticeable.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="configuration-impact"&gt;
&lt;h3&gt;Configuration 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 different projects all have sample policy.json files. These files should
be renamed to policy.yaml, the format changed to simplified YAML, and comments
added. This doesn’t have to happen immediately since policy.json will continue
to work.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing-impact"&gt;
&lt;h3&gt;Testing Impact&lt;/h3&gt;
&lt;p&gt;The projects are already loading their policy files during gate testing.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;blk-u&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="milestones"&gt;
&lt;h3&gt;Milestones&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Target Milestone for completion:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;newton-1&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Change oslo.policy to use yaml.safe_load() rather than json.loads()&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Rename oslo_policy.policy.Rules load_json() to load(), use debtcollector
to rename.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Change oslo.policy to look for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;policy.yaml&lt;/span&gt;&lt;/code&gt; first and then look for
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;policy.json&lt;/span&gt;&lt;/code&gt;. &lt;cite&gt;policy_dirs&lt;/cite&gt; will also use this.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;References to JSON need to be changed to YAML in general:
** &lt;cite&gt;policy_file&lt;/cite&gt; help text.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="incubation"&gt;
&lt;h2&gt;Incubation&lt;/h2&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;section id="adoption"&gt;
&lt;h3&gt;Adoption&lt;/h3&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;section id="library"&gt;
&lt;h3&gt;Library&lt;/h3&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;section id="anticipated-api-stabilization"&gt;
&lt;h3&gt;Anticipated API Stabilization&lt;/h3&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;If the documentation mentions that the policy file is in JSON format then that
can be changed to say YAML format. Any policy sample files should be changed
to the simpler YAML format rather than JSON.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;oslo.policy will depend on PyYAML. This is already in global-requirements.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;debtcollector: &lt;a class="reference external" href="https://docs.openstack.org/debtcollector/latest/"&gt;https://docs.openstack.org/debtcollector/latest/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;JSON: &lt;a class="reference external" href="http://www.json.org/"&gt;http://www.json.org/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;oslo.policy: &lt;a class="reference external" href="https://docs.openstack.org/oslo.policy/latest/"&gt;https://docs.openstack.org/oslo.policy/latest/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;PyYAML: &lt;a class="reference external" href="http://pyyaml.org/"&gt;http://pyyaml.org/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;YAML: &lt;a class="reference external" href="http://yaml.org/"&gt;http://yaml.org/&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 work is licensed under a Creative Commons Attribution 3.0
Unported License.
&lt;a class="reference external" href="http://creativecommons.org/licenses/by/3.0/legalcode"&gt;http://creativecommons.org/licenses/by/3.0/legalcode&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
</description><pubDate>Tue, 23 Apr 2019 00:00:00 </pubDate></item><item><title>Configuration Validator</title><link>https://specs.openstack.org/openstack/oslo-specs/specs/ocata/oslo-validator.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/oslo.config/+spec/oslo-validator"&gt;https://blueprints.launchpad.net/oslo.config/+spec/oslo-validator&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Support the ability to validate oslo.config options at a basic level
against an operator configuration file, as-well-as potentially validation
of options on service start(example usage).&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;It is extremely easy to have invalid conf files for any project:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Invalid Sections&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Invalid Option Name&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Deprecated Options&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Misspellings&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Usage of Advanced Options (warnings)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Lack of Configured Required Options&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Usage of Choices Outside of Scope&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Usage of Default Values in Configuration File&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Configuration validation, in its basic form, can help alleviate these basic
issues by providing a way to validate options and configured values both
manually, via cli, and on service start(example usage).  Operators have been
asking for this functionality for some time now, as the deviation from version
to version, with regard to options, can be substantial.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;As an operator, being able to validate the configuration prior to deployment
is invaluable, providing a clear path for both CI/CD utilization and manual
checks.&lt;/p&gt;
&lt;p&gt;As a developer, being able to provide an option to operators for basic
validation against project configuration files.  This can be by way of shell
script traversing each namespace, as Neutron utilizes, or it could be by way of
an additional argument specific for config validation, i.e. &lt;cite&gt;ironic-api
–validate-config&lt;/cite&gt;.  Implementation is customizable per project.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;The new validator module would offer two avenues for consumption: cli
command and the ability to import the validator for use during service
start(example usage).  Oslo config validator would be a basic check on
common configuration mistakes and in no way offers an opinion on a correct
configuration or a desired configuration.&lt;/p&gt;
&lt;p&gt;For cli usage, a new entry point will be added to oslo.config,
&lt;cite&gt;oslo-config-validator&lt;/cite&gt;.  Similar to &lt;cite&gt;oslo-config-generator&lt;/cite&gt;, operators will
be able to pass an argument, &lt;cite&gt;–namespace&lt;/cite&gt;, to indicate what application
namespace their configuration file will validate against.  Or, optionally an
operator/developer can pass &lt;cite&gt;–validator-config-file&lt;/cite&gt;, which would contain the
application namespaces. In addition, &lt;cite&gt;–config-file&lt;/cite&gt; will be a required
argument to indicate the location of their configuration file. Ideally, each
project would implement a shell script tool to traverse the namespaces used
by the project for validation.  For example, here is the usage in Neutron:
neutron/blob/master/tools/generate_config_file_samples.sh&lt;/p&gt;
&lt;p&gt;For module import, developers will be able to utilize &lt;cite&gt;validator.validate&lt;/cite&gt;
and pass a required collection of configured options to check against the
registered namespaces and options in &lt;cite&gt;oslo.config&lt;/cite&gt;.  This could be
performed on service start(example usage), after configuration files are
ingested, and output to the configured log file.  It could be also used
in each project as an additional argument, i.e. &lt;cite&gt;ironic-api –validate-config&lt;/cite&gt;,
where the configuration is then validated as a separate operation, if a shell
script is not developed above.  Both options would be available, how each
project implements config validation is out of the scope of this spec.&lt;/p&gt;
&lt;p&gt;One use case for &lt;cite&gt;validator.validate&lt;/cite&gt; would be to fail on service start, where
&lt;cite&gt;validate&lt;/cite&gt; returns &lt;cite&gt;valid_configuration(bool)&lt;/cite&gt;, &lt;cite&gt;invalid_configuration_items(dict)&lt;/cite&gt;.
The return values can help determine if the service is capable of starting by
examining &lt;cite&gt;invalid_configuration_items[‘errors’] (bool)&lt;/cite&gt; if &lt;cite&gt;valid_configuration&lt;/cite&gt;
is &lt;cite&gt;false&lt;/cite&gt;.  This would allow developers to have control over warnings being
suppressed by having &lt;cite&gt;invalid_configuration_items[‘errors’] (bool)&lt;/cite&gt; and
&lt;cite&gt;invalid_configuration_items[‘warnings’] (bool)&lt;/cite&gt; separate with their own
respective iterable list of items considered in error:&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;invalid_configuration_items&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'config_errors'&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="s1"&gt;'config_item'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'namespace'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'item_name'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'DEFULT'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="s1"&gt;'message'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'Namespace DEFULT does not exist.'&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;'config_item'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'option'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'item_name'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'auth_uri'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="s1"&gt;'message'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'Option auth_uri has no value assigned.'&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 for configuration warnings:&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;invalid_configuration_items&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'config_warnings'&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="s1"&gt;'config_item'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'option'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'item_name'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'auth_strategy'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="s1"&gt;'message'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'Option is configured with the default value, not 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;'config_item'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'option'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'item_name'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'some_advanced_option'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="s1"&gt;'message'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'Option some_advanced_option is an advanced option and may'&lt;/span&gt;
                &lt;span class="s1"&gt;'effect performance.'&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;These are just examples of data structures potentially being returned and
may change when configuration validator is implemented.  In any case, a list of
errors/warnings will be returned for easy output to console or logs.&lt;/p&gt;
&lt;p&gt;Configuration validator would report on the following discrepancies:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Option not in namespace (error)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Option has no value (error)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Option has no value and is required (error)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Option value is not in range (error)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Option value is default, not required in config (warning)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Option is deprecated (warning)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Option is advanced (warning)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Option type validation, i.e. ‘2’ vs 2 (error)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Invalid configuration section (error)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Missing configuration section, i.e. [DEFAULT] (warning)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Files to add:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;oslo.config/oslo_config/validator.py&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;oslo.config/doc/source/validator.rst&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Files to modify:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;oslo.config/setup.cfg&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="impact-on-existing-apis"&gt;
&lt;h3&gt;Impact on Existing APIs&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="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;This could be an additional check on service start(example usage), which could
have an impact on the time it would take to become fully operational.  At its
most basic form, manual checks via cli would not have a performance impact.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="configuration-impact"&gt;
&lt;h3&gt;Configuration 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="testing-impact"&gt;
&lt;h3&gt;Testing Impact&lt;/h3&gt;
&lt;p&gt;Additional unit tests would be required to cover raised warnings and
errors provided by validator.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;ski&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="milestones"&gt;
&lt;h3&gt;Milestones&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Target Milestone for completion:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;ocata-1&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 new module &lt;cite&gt;validator.py&lt;/cite&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create new entrypoint &lt;cite&gt;oslo-config-validator&lt;/cite&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create new docs file &lt;cite&gt;validator.rst&lt;/cite&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="incubation"&gt;
&lt;h2&gt;Incubation&lt;/h2&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;section id="adoption"&gt;
&lt;h3&gt;Adoption&lt;/h3&gt;
&lt;p&gt;It is likely that this module will be used throughout OpenStack as it satisfies
operator need surrounding the complexity of configuration files.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="library"&gt;
&lt;h3&gt;Library&lt;/h3&gt;
&lt;p&gt;oslo.config&lt;/p&gt;
&lt;/section&gt;
&lt;section id="anticipated-api-stabilization"&gt;
&lt;h3&gt;Anticipated API Stabilization&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Will need to develop additional documentation in &lt;cite&gt;validator.rst&lt;/cite&gt; to detail how
validator can be consumed both at the cli level and as a module.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;This additional module will not require any dependencies.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;oslo.config: &lt;a class="reference external" href="https://docs.openstack.org/oslo.config/latest/"&gt;https://docs.openstack.org/oslo.config/latest/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;neutron: &lt;a class="reference external" href="https://docs.openstack.org/neutron/latest/"&gt;https://docs.openstack.org/neutron/latest/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;ironic: &lt;a class="reference external" href="https://docs.openstack.org/ironic/latest/"&gt;https://docs.openstack.org/ironic/latest/&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 work is licensed under a Creative Commons Attribution 3.0
Unported License.
&lt;a class="reference external" href="http://creativecommons.org/licenses/by/3.0/legalcode"&gt;http://creativecommons.org/licenses/by/3.0/legalcode&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
</description><pubDate>Tue, 23 Apr 2019 00:00:00 </pubDate></item><item><title>Config Opts From Environment</title><link>https://specs.openstack.org/openstack/oslo-specs/specs/rocky/config-from-environment.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/oslo.config/+spec/config-from-environment"&gt;https://blueprints.launchpad.net/oslo.config/+spec/config-from-environment&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;It is common and convenient in service management, especially container
orchestration, to manage configuration settings using environment variables set
by the controlling environment. This allows the service being managed to avoid
extraneous files and other artifacts, allowing service immutability and thus
straightforward elasticity. This specification proposes using the new
&lt;a class="reference external" href="http://specs.openstack.org/openstack/oslo-specs/specs/queens/oslo-config-drivers.html"&gt;drivers&lt;/a&gt; functionality provided by &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo.config&lt;/span&gt;&lt;/code&gt; to automatically support
overriding or setting configuration from environment variables with standard
and predictable names.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;A common way to pass instance specific settings to a container is to use
shell environment variables. For example, in docker:&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;docker&lt;/span&gt; &lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="mf"&gt;127.0.0.1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;8081&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;80&lt;/span&gt; \
  &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="s2"&gt;"DB_SYNC=True"&lt;/span&gt; \
  &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="s2"&gt;"AUTH_STRATEGY=noauth2"&lt;/span&gt; \
  &lt;span class="n"&gt;myservice&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;or in a (fragment of a) Kubernetes deployment:&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;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
  &lt;span class="n"&gt;containers&lt;/span&gt;&lt;span class="p"&gt;:&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;myservice&lt;/span&gt;
      &lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;myservice&lt;/span&gt;
      &lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;:&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;DB_SYNC&lt;/span&gt;
          &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"True"&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;AUTH_STRATEGY&lt;/span&gt;
          &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;noauth2&lt;/span&gt;
      &lt;span class="n"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;containerPort&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;In OpenStack these settings are usually managed by config files read by
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo.config&lt;/span&gt;&lt;/code&gt; into instances of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ConfigOpts&lt;/span&gt;&lt;/code&gt; classes. At this time there is
no unified way to use environment variables for these settings, meaning that in
many cases if a deployer would like to run an OpenStack service in a container,
they must provide a configuration file for that container, or provide some way
for the service to gather configuration at run time.&lt;/p&gt;
&lt;p&gt;The &lt;a class="reference external" href="http://specs.openstack.org/openstack/oslo-specs/specs/queens/oslo-config-drivers.html"&gt;drivers&lt;/a&gt; functionality being developed for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo.config&lt;/span&gt;&lt;/code&gt; provides one
model for that run time configuration, but does not specifically address
the case of using simple environment variables.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;The spec proposes using the drivers model to create a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ConfigurationSource&lt;/span&gt;&lt;/code&gt;
for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo.config&lt;/span&gt;&lt;/code&gt; that looks to the running environment for variables that
match expected names for registered configuration settings. The source will be
available by default, ideally coming second in the stack, after individual
command line overrides, but before any files or other sources. If this proves
impossible because of inter-dependencies in the file and command line handling,
first in the stack is the second-best option.&lt;/p&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ConfigurationSource&lt;/span&gt;&lt;/code&gt; will translate config option names to candidate
variable names. If those variables are set in the local environment (a member
of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os.environ&lt;/span&gt;&lt;/code&gt; in Python) the values will be returned. If they are not set,
further processing of other sources will proceed.&lt;/p&gt;
&lt;p&gt;There are two main challenges with this proposal. Resolving them in a
satisfactory fashion is why this spec is being written. They are:&lt;/p&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;&lt;p&gt;Determining a satisfactory scheme for translating configuration option names
to environment variable names in a way that is both predictable for humans
and highly unlikely to collide with variable names that might otherwise be
used. A strawman proposal is as follows:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Prefix each variable with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;OS_&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Followed by the group: &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;DEFAULT&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Separated from the name by a double-under &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;__&lt;/span&gt;&lt;/code&gt; (to allow unders in the
group)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Followed by the name, resulting in something like:
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;OS_PLACEMENT_DATABASE__CONNECTION&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This will result in quite long names in some cases, but that’s likely going
to be the case with any solution that satisfies both requirements. Note that
this format can be transformed in both directions: from option group and
name to environment variable name and vice versa.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Individual options in a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ConfigOpts&lt;/span&gt;&lt;/code&gt; have types. Environment variables, on
the other hand, are strings. We either need to establish a way of coercing
string-based representations of non-string types to the desired type
(&lt;a class="reference external" href="https://opendev.org/openstack/keystonemiddleware/src/branch/stable/rocky/keystonemiddleware/_common/config.py"&gt;keystonemiddleware&lt;/a&gt; has some code that does some of this) or we perhaps
initially only support &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;StrOpt&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Here is a contrived example that describes two options which have similar names
that demonstrates the importance of group handling. Configuration items as
follows:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;placement&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;database_connection&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;foo&lt;/span&gt;

&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;placement_database&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;connection&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;bar&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;would result in two environment variables &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;OS_PLACEMENT__DATABASE_CONNECTION&lt;/span&gt;&lt;/code&gt;
and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;OS_PLACEMENT_DATABASE__CONNECTION&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;This is not something that has to be done in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo.config&lt;/span&gt;&lt;/code&gt;. Individual
services could manage their own environment checking, but that’s not really
in keeping with the oslo principles nor the consistency goals of OpenStack.&lt;/p&gt;
&lt;p&gt;In some circumstances an &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Opt&lt;/span&gt;&lt;/code&gt; could set a default that reads from the
environment using &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;default=os.environ.get('SOMETHING')&lt;/span&gt;&lt;/code&gt; but this has a
critical disadvantage: The environment variable is only used if the option is
not already set in the configuration. Ideally the environment variable should
override configuration.&lt;/p&gt;
&lt;p&gt;Another way to do this would be to add another parameter to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Opt&lt;/span&gt;&lt;/code&gt; named
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;envvar&lt;/span&gt;&lt;/code&gt;. If set, the value would be used to override the automatically
generated environment variable name (as described above). This is considered
undesirable as it made lead to published inconsistencies in variable naming.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="impact-on-existing-apis"&gt;
&lt;h3&gt;Impact on Existing APIs&lt;/h3&gt;
&lt;p&gt;See above.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;There’s a slim chance that service behavior could change if pre-existing
environment variables are present that happen to match the naming scheme
described here.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;No significant performance impact is expected. Querying the environment is
quick and the querying is done as needed, not for all possible configuration
values.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="configuration-impact"&gt;
&lt;h3&gt;Configuration Impact&lt;/h3&gt;
&lt;p&gt;No new options will be added when registering options. Support for environment
variable-based overrides will be automatic.&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 an additional customization option available.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing-impact"&gt;
&lt;h3&gt;Testing Impact&lt;/h3&gt;
&lt;p&gt;Additional unit tests will be required to cover the added functionality.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;cdent&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;volunteers?&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="milestones"&gt;
&lt;h3&gt;Milestones&lt;/h3&gt;
&lt;p&gt;..TODO(cdent): figure this out&lt;/p&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Implement the new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ConfigurationSource&lt;/span&gt;&lt;/code&gt; driver.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Integrate it as a default driver.&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;Update the sample configuration generator to include the variable names.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update the documentation generator to include the variable names.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="incubation"&gt;
&lt;h2&gt;Incubation&lt;/h2&gt;
&lt;p&gt;N/A&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 will need to be updated to indicate that each option can be
overridden with an environment variable and to describe how the name of the
variable will be generated.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;This implementation is dependent on the emerging &lt;a class="reference external" href="http://specs.openstack.org/openstack/oslo-specs/specs/queens/oslo-config-drivers.html"&gt;drivers&lt;/a&gt; functionality in
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo.config&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;Backend Drivers for oslo.config:
&lt;a class="reference external" href="http://specs.openstack.org/openstack/oslo-specs/specs/queens/oslo-config-drivers.html"&gt;http://specs.openstack.org/openstack/oslo-specs/specs/queens/oslo-config-drivers.html&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Keystone Middleware option type coercing:
&lt;a class="reference external" href="https://opendev.org/openstack/keystonemiddleware/src/branch/stable/rocky/keystonemiddleware/_common/config.py"&gt;https://opendev.org/openstack/keystonemiddleware/src/branch/stable/rocky/keystonemiddleware/_common/config.py&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This work is licensed under a Creative Commons Attribution 3.0
Unported License.
&lt;a class="reference external" href="http://creativecommons.org/licenses/by/3.0/legalcode"&gt;http://creativecommons.org/licenses/by/3.0/legalcode&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
</description><pubDate>Tue, 23 Apr 2019 00:00:00 </pubDate></item><item><title>Privilege Separation Daemon</title><link>https://specs.openstack.org/openstack/oslo-specs/specs/liberty/privsep.html</link><description>

&lt;p&gt;It is difficult to sufficiently describe security policy at the
granularity of command lines.  Consequently numerous rootwrap entries
effectively grant full root access to anyone permitted to run
rootwrap.&lt;/p&gt;
&lt;p&gt;This spec proposes a replacement (dubbed “privsep”) that is both more
expressive and more limited in what it grants.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem Description&lt;/h2&gt;
&lt;p&gt;OpenStack’s privilege mechanism has evolved over time from simple
sudoers file to rootwrap.  Recent “rootwrap-daemon” work has greatly
increased the performance by avoiding the need to re-exec python.
Throughout this history, the basic API idiom has remained executing
command lines (almost always) as root.&lt;/p&gt;
&lt;p&gt;The rootwrap security policy revolves around whitelisting particular
command lines via the configuration of various “filters”.  Configuring
these correctly are hard, because the filters have limited
expressiveness, command line tools typically weren’t expected to be
the privilege boundary, and the “context” of the original operation
has already been lost at this level.&lt;/p&gt;
&lt;p&gt;For example, as shipped &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;nova/rootwrap.d/compute.filters&lt;/span&gt;&lt;/code&gt; contains:&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;chown&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;CommandFilter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;chown&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;root&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;This allows the invoking user to run chown with any arguments, as
root - effectively granting root access to the caller (consider
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;chown&lt;/span&gt; &lt;span class="pre"&gt;$user&lt;/span&gt; &lt;span class="pre"&gt;/etc/shadow&lt;/span&gt;&lt;/code&gt;).  The &lt;em&gt;actual&lt;/em&gt; requirement is that nova
needs to set the owner on various files produced by VMs to it’s own
UID, but this is not something that can be expressed through current
rootwrap filters.&lt;/p&gt;
&lt;p&gt;Repeatedly going through sudo for each invocation (or similar for
rootwrap-daemon) limits the ability to use more restricted privilege
mechanisms like Linux capabilities or SELinux, since the calls to sudo
effectively reset to “full privileges” mid-way through the call stack.&lt;/p&gt;
&lt;p&gt;Generating command lines and parsing textual output from tools is slow
and susceptible to inconsistencies across tool versions, since
typically this output was not designed as a programmatic API.  In
Neutron in particular, the command lines are often repeated
invocations of trivial ip(8) commands and the overhead is significant
compared to what should be cheap AF_NETLINK exchanges.&lt;/p&gt;
&lt;section id="why-have-a-privilege-mechanism-at-all"&gt;
&lt;h3&gt;Why have a privilege mechanism at all?&lt;/h3&gt;
&lt;p&gt;Otherwise known as “Why don’t we just run agents as root?”&lt;/p&gt;
&lt;p&gt;Running with the least privileges possible is a common defensive
security design.  The assumption is that it &lt;em&gt;might&lt;/em&gt; be possible to
remotely exploit your service via the publicly exposed network
protocols so you want to run the bulk of your code with reduced/no
privilege and only gain special privileges when absolutely required.
If an attacker gains control of the unprivileged code then they
achieve no interesting access, and still have to attempt a second
exploit against the unprivileged-&amp;gt;privileged boundary before gaining
useful powers.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-policy"&gt;
&lt;h2&gt;Proposed Policy&lt;/h2&gt;
&lt;p&gt;This spec proposes a new privilege mechanism that is based around
python function calls rather than command lines.  The intention is to
allow slightly more code into the privileged portion - enough that we
now have sufficient “context” to make better security decisions.  For
example move from “run chown” to “take ownership of VM output file”.&lt;/p&gt;
&lt;p&gt;Design priorities, in rough order of importance:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Security
* Avoid root as much as possible
* Security interface should be easy to audit&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Easy to use by developers
* Just add a new function with a decorator&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Performance
* Allows library use rather than parsing output of command line tools&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;In a similar way to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;rootwrap-daemon&lt;/span&gt;&lt;/code&gt;, privsep runs two processes -
one with and one without privileges.  The privileged process is as
minimal as possible, and is written to assume it is possibly under
attack by the unprivileged process.&lt;/p&gt;
&lt;p&gt;To limit the impact of a potential exploit, this spec proposes the
privileged process support the use of &lt;em&gt;Linux capabilities&lt;/em&gt; to allow
the process to drop broad root (uid=0) superpowers but keep a limited
subset.  See capabilities(7) manpage for an overview.  As an example,
the neutron agent might be configured to use privsep as a non-root
user but with CAP_NET_ADMIN - this allows just about all kernel
network options to be changed, but a compromised process could not
read &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/etc/shadow&lt;/span&gt;&lt;/code&gt; or load an arbitrary kernel module.&lt;/p&gt;
&lt;p&gt;A design limitation from using capabilities is that the privileged
process is limited to &lt;em&gt;only those&lt;/em&gt; capabilities.  Eg: most of Neutron
just requires CAP_NET_ADMIN and CAP_SYS_ADMIN (for network
namespaces), but there are some operations that require additional
permissions.  Extrapolating this to absurdity, eventually the
privileged process accumulates &lt;em&gt;all&lt;/em&gt; required capabilities and
effectively becomes all-powerful root again.  To combat this, privsep
allows a particularly diverse service to instantiate multiple privsep
daemons, each with their own set of permissions and privileged code.&lt;/p&gt;
&lt;p&gt;Unlike &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;rootwrap-daemon&lt;/span&gt;&lt;/code&gt;, this spec proposes that the privileged
process &lt;em&gt;share fate&lt;/em&gt; with the main (unprivileged) process.
Specifically: the privileged process should exit when the unprivileged
process has exited, and once started no attempt should be made to
restart the privileged process if it exits.  If the privileged process
exits for some reason, it is due to a bug and may be currently under
attack - restarting the process gives the attacker another
opportunity.  If the privileged process exits, the unprivileged
process will be unable to perform many functions, and will need to be
restarted by the admin - this is essentially similar to an uncaught
exception destroying a critical worker thread and leaving an
inconsistent state.&lt;/p&gt;
&lt;section id="privileged-run-time-environment"&gt;
&lt;h3&gt;Privileged run-time environment&lt;/h3&gt;
&lt;p&gt;After setup, there are two distinct processes joined with a
communication channel: The original process with no special
privileges, and a privileged process running as root and/or with extra
Linux capabilities.&lt;/p&gt;
&lt;p&gt;Project-provided python code running in the privileged process is run
with:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;A trusted &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo.config&lt;/span&gt;&lt;/code&gt; environment.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A trusted python module search path.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;uid/gid set to the configured values (default: root).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Linux capabilities are restricted to the configured set (default:
project-provided).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;stdin&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;stdout&lt;/span&gt;&lt;/code&gt; are closed and reopened to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/dev/null&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo.log&lt;/span&gt;&lt;/code&gt; is configured to log to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;stderr&lt;/span&gt;&lt;/code&gt;.  The unprivileged
code is expected to proxy this to the correct final location.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A communication channel is open to the unprivileged caller.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The trusted python module path and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo.config&lt;/span&gt;&lt;/code&gt; environment are
assumed and must be provided by whatever granted the initial elevated
privileges and executed the python interpreter (eg: &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;systemd&lt;/span&gt;&lt;/code&gt;
environment, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;sudoers&lt;/span&gt;&lt;/code&gt; configuration, etc).  Based on the
configuration found, the privileged startup code will configure the
rest and abort if any step fails.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="communication-with-privileged-process"&gt;
&lt;h3&gt;Communication with privileged process&lt;/h3&gt;
&lt;p&gt;The communication channel must be secure.  In particular, python
“pickle” and many other serialisation libraries are unsuitable because
they contain convenience features that can allow unexpected code to be
executed during deserialisation.  For its simplicity, this spec
proposes using &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;json&lt;/span&gt;&lt;/code&gt; and limiting function argument/return values
to the basic JSON datatypes (32-bit integer, 32-bit floats, unicode
string, boolean, array, dictionary), with the addition of a bytestring
type.  In the return direction (privileged to unprivileged), there
will also be support for catching and re-raising most exception
objects (assumes the class can be found on the unprivileged side and
the common &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;.args&lt;/span&gt;&lt;/code&gt; convention).&lt;/p&gt;
&lt;p&gt;The underlying communication channel must not be exposed remotely -
Unix sockets or pipes are obvious choices.&lt;/p&gt;
&lt;p&gt;Note the communication channel is only between the privileged and
unprivileged portions of privsep.  Specific serialisation and
communication choices are implementation details and can be changed
over time without compatibility concerns.&lt;/p&gt;
&lt;p&gt;The current prototype offers several alternatives that all produce the
same end result: Two processes connected over a local communication
channel.&lt;/p&gt;
&lt;p&gt;The 2nd option (sudo/rootwrap) is used by default if no specific
“start” method has been invoked by the first call to a privsep client
stub function.  We may want to revisit these choices as the
recommended OpenStack secure deployment story evolves.&lt;/p&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;&lt;p&gt;Basic &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;socketpair()&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;fork()&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;This just creates a pair of anonymous connected Unix sockets, and
then forks the new privileged process.  The assumption is that the
original process was started with at least the required privileges
(perhaps from something like systemd), and this “start” function is
invoked early in the process startup - prior to the regular
unprivileged process dropping all privileges.&lt;/p&gt;
&lt;p&gt;This is designed to mirror the “normal” way that Unix daemons work,
and does not use sudo at any point.  It requires an additional call
inserted in main() and changes to the initial process environment,
so poses the most difficult migration.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;sudo&lt;/span&gt;&lt;/code&gt; or &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;rootwrap&lt;/span&gt;&lt;/code&gt; and a Unix socket&lt;/p&gt;
&lt;p&gt;This is intended for use with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;sudo&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;rootwrap&lt;/span&gt;&lt;/code&gt;, or
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;rootwrap-daemon&lt;/span&gt;&lt;/code&gt;.  This is complicated by the fact that &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;sudo&lt;/span&gt;&lt;/code&gt;
closes all open file descriptors except stdin/stdout/stderr, and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;rootwrap-daemon&lt;/span&gt;&lt;/code&gt; doesn’t allow long-lived commands, nor
streaming data over stdin/stdout.&lt;/p&gt;
&lt;p&gt;This approach opens a new Unix socket on the unprivileged side, and
executes a helper command via &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;rootwrap&lt;/span&gt;&lt;/code&gt; (or &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;sudo&lt;/span&gt;&lt;/code&gt;) with the
path to the Unix socket as an argument.  The helper command (now
running with root privileges) connects back to this socket then
forks and exits, allowing &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;rootwrap-daemon&lt;/span&gt;&lt;/code&gt; (if used) to see a
timely process exit.  The unprivileged process accepts the first
connection to its listening socket[#unpriv_socket], and continues.&lt;/p&gt;
&lt;p&gt;Note that (unlike &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;rootwrap-daemon&lt;/span&gt;&lt;/code&gt;) the connection is made from
the privileged side to the unprivileged side.  At no point is the
privileged process exposing an access point where other processes
can attempt to connect to it.  Simply accepting the first
connection to the unprivileged socket is safe because the
filesystem permissions only allow the same uid, or root - and a
process running as the same uid is already entrusted to start its own
privileged daemon via &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;sudo&lt;/span&gt;&lt;/code&gt;/&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;rootwrap&lt;/span&gt;&lt;/code&gt;, so this would grant no
additional privilege.&lt;/p&gt;
&lt;p&gt;This approach is the default since it requires no change to
existing OpenStack deployments (other than an updated rootwrap
filter).&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Regardless of the approach used to create the communication channel,
the privileged process continues acting on requests until the
communication channel is closed.  At this point, the privileged
process exits.  Since it is a local IPC channel, there should be no
“legitimate” reason for the channel to drop and no attempt is made by
either side to recreate the connection.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-s-point-of-view"&gt;
&lt;h3&gt;Developer’s Point of View&lt;/h3&gt;
&lt;p&gt;From the python developer’s point of view, the goal is to be as simple
as adding a regular python function.  This spec proposes the following
API (using Neutron as an example and final function names subject to
change):&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="c1"&gt;# In (eg) neutron_privileged/foo.py&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;os&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;neutron_privileged&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;privsep&lt;/span&gt;

&lt;span class="nd"&gt;@privsep&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;entrypoint&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;example_task_that_requires_privileges&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;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getuid&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;To use this function, unprivileged code just needs to call it.&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;neutron_privileged&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;foo&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;bar&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;uid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;example_task_that_requires_privileges&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="nb"&gt;print&lt;/span&gt; &lt;span class="s2"&gt;"privsep is running as &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="n"&gt;uid&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The magic is in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;neutron_privileged/__init__.py&lt;/span&gt;&lt;/code&gt;.  This file needs to
invoke some &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo.privsep&lt;/span&gt;&lt;/code&gt; code at import time to create the
decorator used on privileged entrypoints:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="c1"&gt;# In neutron_privileged/__init__.py (once per project)&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;oslo_privsep&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;capabilities&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;oslo_privsep&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;priv_context&lt;/span&gt;

&lt;span class="n"&gt;CFG_SECTION&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'privsep'&lt;/span&gt;  &lt;span class="c1"&gt;# important with multiple privsep daemons&lt;/span&gt;
&lt;span class="n"&gt;DEFAULT_CAPS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CAP_SYS_ADMIN&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CAP_NET_ADMIN&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;  &lt;span class="c1"&gt;# eg&lt;/span&gt;
&lt;span class="n"&gt;privsep&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;priv_context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PrivContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="vm"&gt;__name__&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cfg_section&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;CFG_SECTION&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;default_capabilities&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;DEFAULT_CAPS&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 decorator internally wraps each function like this (pseudo-code):&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="c1"&gt;# Resulting pseudo code, after decorator is applied&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;example_function&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="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;in_unprivileged_mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;privsep_channel&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;send&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;CALL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'example_function'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&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;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;privsep_channel&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="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;raised_exception&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
            &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exc_class&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exc_args&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;result&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# privileged_mode&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;_real_example_function&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;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The unprivileged “client stub” function will serialise any arguments,
communicate with the privsep process, and deserialise the return
value.  Note (by choice) only basic “json-ish” python types are
accepted in args or return values - no user-defined objects.  If the
privileged code raises an exception, it will be caught and re-raised
on the unprivileged side (using the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;.args&lt;/span&gt;&lt;/code&gt; property).&lt;/p&gt;
&lt;p&gt;As described earlier, the privileged daemon will be started when the
first stub is called unless the daemon has already been started.  Once
started, the same channel is reused and the privileged daemon persists
until the channel is closed (presumably when the main process exits).&lt;/p&gt;
&lt;p&gt;Functions that are not marked with the privsep decorator are not
available across the privsep channel.  The imported module is
otherwise available as normal so module-level constants, etc are
available as expected.  Note that the unprivileged process is a
separate process, so modifying an imported global will have no effect
on the privileged code.&lt;/p&gt;
&lt;p&gt;The decorator can be set to “privileged mode” even within the
unprivileged process, in which case it will pass calls through to the
real wrapped function.  The function will run without any special
privileges and presumably fail.  This is rarely expected to be useful
outside unittests with mocked environments.&lt;/p&gt;
&lt;p&gt;Importing &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;foo.bar.baz&lt;/span&gt;&lt;/code&gt; involves loading (and hence trusting)
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;foo/__init__.py&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;foo/bar/__init__.py&lt;/span&gt;&lt;/code&gt;.  Consequently, this
spec recommends projects create a new top-level python package within
their regular git repository to hold modules intended to be used via
privsep (eg: create &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;neutron.git/neutron_privileged/...&lt;/span&gt;&lt;/code&gt; as in the
examples above), although this is not technically required.&lt;/p&gt;
&lt;section id="debugging"&gt;
&lt;h4&gt;Debugging&lt;/h4&gt;
&lt;p&gt;Moving to function-based primitives necessarily leads to more complex
python code on the privileged side than with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;rootwrap&lt;/span&gt;&lt;/code&gt;, and thus
being able to easily debug this python code is critical.  The
prototype code includes sufficient changes to the neutron testsuite to
correctly fail tests and capture any stacktraces triggered from
privileged code, and display them as expected in unittest output.
Incorporating similar changes will be an important part of projects
migrating to privsep.&lt;/p&gt;
&lt;p&gt;Interactive debugging (via &lt;a class="reference external" href="https://docs.python.org/3/library/pdb.html"&gt;pdb&lt;/a&gt;) of the privileged process, and in
particular use of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;pdb.set_trace()&lt;/span&gt;&lt;/code&gt; within privileged code requires
pdb to have a suitable channel available for interaction.  Since stdin
and stdout are closed in the privileged process, a helper function
will be provided to start pdb on a new Unix socket.  A debugging
side-channel is unsafe in a production deployment for obvious reasons,
and will require the developer to patch in an appropriate call before
using pdb.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="code-coverage"&gt;
&lt;h4&gt;Code coverage&lt;/h4&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;coverage.py&lt;/span&gt;&lt;/code&gt; has support for collecting coverage statistics across
sub-processes &lt;a class="footnote-reference brackets" href="#coverage-subproc" 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;.  To do this, the privileged process
will need to call &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;coverage.process_startup()&lt;/span&gt;&lt;/code&gt; as early as possible
(eg: from &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;main()&lt;/span&gt;&lt;/code&gt;), which enables coverage features if the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;COVERAGE_PROCESS_START&lt;/span&gt;&lt;/code&gt; environment variable is set.  If the
privileged process was invoked through sudo, then the sudo policy must
be explicitly configured to allow this environment variable to be
propagated.&lt;/p&gt;
&lt;p&gt;The specific tox environment details to enable this will be worked out
in later changes.  It looks possible with a little work and needs
explicit support from the initial execution environment, so will not
affect the security of a regular deployment.&lt;/p&gt;
&lt;aside class="footnote-list brackets"&gt;
&lt;aside class="footnote brackets" id="coverage-subproc" 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;See &lt;a class="reference external" href="http://nedbatchelder.com/code/coverage/subprocess.html"&gt;Measuring subprocess&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;/aside&gt;
&lt;/section&gt;
&lt;section id="profiling"&gt;
&lt;h4&gt;Profiling&lt;/h4&gt;
&lt;p&gt;Python &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;profile&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cProfile&lt;/span&gt;&lt;/code&gt; modules are intended for
collecting statistics on specific function calls, and have no support
for collecting statistics across process boundaries.  Profiling within
&lt;em&gt;either&lt;/em&gt; the unprivileged or privileged processes will work as
expected, but attempting to profile &lt;em&gt;across&lt;/em&gt; the privilege boundary
will collect statistics for the local side of the communication
channel only.&lt;/p&gt;
&lt;p&gt;Because each process can be profiled, it is &lt;em&gt;possible&lt;/em&gt; to build a
unified profile in future.  Doing so is considered out of scope of
this spec, however.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="operator-s-point-of-view"&gt;
&lt;h3&gt;Operator’s Point of View&lt;/h3&gt;
&lt;p&gt;Configuration files will require an additional section:&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;privsep&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;novapriv&lt;/span&gt;
&lt;span class="n"&gt;group&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;novapriv&lt;/span&gt;
&lt;span class="n"&gt;capabilities&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;CAP_SYS_ADMIN&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;CAP_NET_ADMIN&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;This is the uid, gid and capabilities that the privileged process
should run with.  By default, the privileged process continues to run
with whatever uid/gid the process was originally started with
(probably root).  The default value for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;capabilities&lt;/span&gt;&lt;/code&gt; is provided
by the instantiating project code, and may need to be overridden to
suit the particular config options/modules in use.&lt;/p&gt;
&lt;p&gt;A diverse service like nova may use more than one separate privileged
daemon, and each will have their own named config section with
different default capabilities.&lt;/p&gt;
&lt;p&gt;In the most paranoid setup, each privileged process should run as a
dedicated non-root user, separate from the unprivileged user (and
separate to any other privsep processes).  Neither privileged nor
unprivileged user should be able to write to the service configuration
files nor anywhere in the python load path.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="alternatives-history"&gt;
&lt;h2&gt;Alternatives &amp;amp; History&lt;/h2&gt;
&lt;p&gt;The evolution of rootwrap is simple:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;“We need to run a few commands as root” -&amp;gt; start using sudo&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;“too many commands and sudoers is becoming unwieldy” -&amp;gt; introduce rootwrap&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;“rootwrap is expensive to reinvoke every time” -&amp;gt; rootwrap-daemon&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;section id="run-the-entire-python-process-with-required-privileges"&gt;
&lt;h3&gt;Run the entire python process with required privileges&lt;/h3&gt;
&lt;p&gt;Provided the unprivileged&amp;lt;-&amp;gt;privileged boundary contains any hole that
effectively grants root to the caller, then there is little benefit to
having the separation and we may as well enjoy the code
simplicity/performance benefits of just running everything in a
unified process.&lt;/p&gt;
&lt;p&gt;A variation of this is to drop “effective” privileges in a way that
can be regained in-process while performing privileged operations (eg:
&lt;cite&gt;seteuid(2)&lt;/cite&gt;).  This protects against “accidental” abuse of privileges,
but won’t grant additional security against a malicious attacker with
control over the process.&lt;/p&gt;
&lt;p&gt;I think there’s a lot to be said for this point of view.  However,
given the popularity and importance of OpenStack VMs as a security
target, I think we need to continue to strive for better in this area.
This spec is an attempt to make an effective security boundary and
grant a true additional layer of defence, while being almost as easy
to work with as an in-process function call.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="use-multiprocessing-library"&gt;
&lt;h3&gt;Use &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;multiprocessing&lt;/span&gt;&lt;/code&gt; library&lt;/h3&gt;
&lt;p&gt;The python &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;multiprocessing&lt;/span&gt;&lt;/code&gt; library already has client processes
talking to worker processes over an IPC channel.  We could reuse that
as the core communication mechanism (and indeed rootwrap-daemon uses
multiprocessing just like this).&lt;/p&gt;
&lt;p&gt;This is reasonable, and perhaps something we may yet choose to do.  I
chose not to use multiprocessing initially because it was written to
be a convenient single-user worker pool and not a privilege separation
boundary.  As can be seen in rootwrap-daemon, serialisation and
several “magic proxy” choices need to be worked around to provide
security, and I felt such workarounds resulted in fragile and
difficult to audit code right at the place you want neither.&lt;/p&gt;
&lt;p&gt;Thankfully, we only require a narrow set of features and rewriting the
core communication code from scratch is straight forward.  The result
is significantly less ambiguous code at the security entry point.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="leave-stdin-stdout-untouched"&gt;
&lt;h3&gt;Leave stdin/stdout untouched&lt;/h3&gt;
&lt;p&gt;In particular, this would allow &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;pdb.set_trace()&lt;/span&gt;&lt;/code&gt; to “just work”
without any further action (assuming it is only invoked from a single
thread).  Although there is no specific concern, having stdin
available leaves an additional potential attack vector into the
privileged context.  Since pdb already has reasonable support for
using a different channel for interaction, the choice to close these
file descriptors (and reopen on /dev/null) seemed an acceptable
security/convenience tradeoff.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="author-s"&gt;
&lt;h3&gt;Author(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary author:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;gus&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="milestones"&gt;
&lt;h3&gt;Milestones&lt;/h3&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Move existing prototype code into oslo.privsep&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Introduce privsep alternatives of large bodies of rootwrap code&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update documentation mentioning rootwrap config/filters&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Phase out alternative rootwrap code&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;p&gt;A working prototype already exists in
&lt;a class="reference external" href="https://review.openstack.org/#/c/155631/"&gt;https://review.openstack.org/#/c/155631/&lt;/a&gt;, although the proposed API
has evolved with this spec.&lt;/p&gt;
&lt;p&gt;Most of the remaining work involves moving the core mechanism to a new
oslo.privsep project, and rebasing the prototype Neutron change onto
that common core.  From the Neutron experience, the largest piece of
migrating a new project to this mechanism will be integrating into the
unittest mocked environment and will vary by project.&lt;/p&gt;
&lt;p&gt;In the current prototype implementation, the communication channel can
only have one outstanding operation at a time and the privileged
process is single-threaded.  These limitations will be addressed as
the code is moved into oslo by adding unique message IDs and using a
small thread worker pool on the privileged side.&lt;/p&gt;
&lt;p&gt;Once the bulk of the code exists in oslo.privsep we should encourage
wide review by the OpenStack Security Group and others.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="migration"&gt;
&lt;h3&gt;Migration&lt;/h3&gt;
&lt;p&gt;This mechanism may live alongside &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;rootwrap&lt;/span&gt;&lt;/code&gt; without interference.
The expected migration process is to create alternative privsep
versions of routines that require privileges and migrate callers
across to the new implementation.  Remaining “hard” cases that require
unusual permissions or true uid=0 may continue to use sudo/rootwrap
indefinitely, and this spec makes no suggestion that we should migrate
away from rootwrap entirely.&lt;/p&gt;
&lt;/section&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;Prototype Neutron implementation:
&lt;a class="reference external" href="https://review.openstack.org/#/c/155631/"&gt;https://review.openstack.org/#/c/155631/&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;rootwrap-daemon spec:
&lt;a class="reference external" href="http://specs.openstack.org/openstack/neutron-specs/specs/kilo/rootwrap-daemon-mode.html"&gt;http://specs.openstack.org/openstack/neutron-specs/specs/kilo/rootwrap-daemon-mode.html&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A somewhat similar mechanism in ssh, from which the name “privsep”
is borrowed: &lt;a class="reference external" href="http://www.citi.umich.edu/u/provos/ssh/privsep.html"&gt;http://www.citi.umich.edu/u/provos/ssh/privsep.html&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="revision-history"&gt;
&lt;h2&gt;Revision History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id2"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td/&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This work is licensed under a Creative Commons Attribution 3.0
Unported License.
&lt;a class="reference external" href="http://creativecommons.org/licenses/by/3.0/legalcode"&gt;http://creativecommons.org/licenses/by/3.0/legalcode&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
</description><pubDate>Fri, 29 Mar 2019 00:00:00 </pubDate></item><item><title>New RabbitMQ Pika driver implementation</title><link>https://specs.openstack.org/openstack/oslo-specs/specs/mitaka/rabbitmq-pika-driver.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/oslo.messaging/+spec/rabbit-pika"&gt;https://blueprints.launchpad.net/oslo.messaging/+spec/rabbit-pika&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This specification proposes a new RabbitMQ Pika driver implementation.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Current RabbitMQ oslo.messaging driver uses Kombu client library.
But new features support and bugfixes appear in Kombu more slower then in Pika.
Now we have problems with RabbitMQ stable work in HA mode. And when we asked
RabbitQM developers for help with bugfixing they said that it is possible but
first of all, please update your environment to recommended library stack.
It is main reason of developing this driver.&lt;/p&gt;
&lt;p&gt;Also Pika supports modern RabbitMQ features, like direct reply and heartbeats.
I guess It is preferred way to use this functionality instead developing it
ourselves.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;In this specification I propose to create fully new driver which:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;should be developed in optimal way regarding to all Pika client
library new features and best practices;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;should be fully compatible with current driver interface;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;may change internals and does not guarantee compatibility with
Kombu driver (means you can not use old Kombu driver for some set
of services and new Pika driver for another services)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;support only current actual features without any deprecated features.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;section id="features-and-it-s-design"&gt;
&lt;h3&gt;Features and it’s design&lt;/h3&gt;
&lt;p&gt;During oslo.messaging driver investigation I separated a few main
supported features:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;RPC - unreliable fast sending of the message to single remote server
defined using target and getting reply.
It has small timeout (a couple of seconds) therefore this
message should be received by server and processed in real time
(defined by timeout) or be skipped otherwise.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;CAST - unrelieble sending of the message to set of remote servers
defined by target. This message should be received by server in real time
(defined by timeout) or be skipped otherwise. If somehow service
does not listen the topic or some connectivity problem occurs
and we can not recover it fast - this server will never get the message.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;NOTIFY - reliable version of CAST - we can not loose the messages.
if you send notification and send_notification method returns without any
error - message should be stored and wait until remote server gets started
and gets conectivity to our RabbitMQ brocker.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
&lt;section id="eventlet-compatibility"&gt;
&lt;h3&gt;Eventlet compatibility&lt;/h3&gt;
&lt;p&gt;Pika has a few connection adapters For working with different frameworks.
It does not have special adapter for eventlet. But It is possible to use
‘BlockingConnection’ adapter and eventlet monkey patching. It works pretty
well. Only one problem I found - it tries to use ‘select.epull’ API which is
not patched by current eventlet implementation. So I added code which removes
‘pull’ and ‘epull’ attributes from ‘select’ module if eventlet is patched.
In this case Pika uses standard select api which is patched by eventlet
correctly.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="heartbeats"&gt;
&lt;h3&gt;Heartbeats&lt;/h3&gt;
&lt;p&gt;Pika has it’s own heartbeats mechanism. ‘BlockingConnection’ adapter has
method ‘process_data_events’ which listen in loop response from RabbitMQ.
It should be executed after sending request or when consumers are registered.
This method run loop:&lt;/p&gt;
&lt;p&gt;(code snippet from &lt;a class="reference external" href="https://github.com/pika/pika/blob/master/pika/adapters/blocking_connection.py#L410"&gt;https://github.com/pika/pika/blob/master/pika/adapters/blocking_connection.py#L410&lt;/a&gt;)&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;is_done&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_impl&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ioloop&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;poll&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_impl&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ioloop&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;process_timeouts&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;which sends heartbeats (inside process_timeout_method) according to configured
heartbeat_timeout. So we have heartbeats working for all listeners with defined
interval. For connections used for message publishing heartbeats will be sent
only when connection is active - when you are executing publish method.&lt;/p&gt;
&lt;/section&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;Use old driver;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Not develop fully new driver, try to just replace client library
and keep logic of current driver&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
&lt;section id="impact-on-existing-apis"&gt;
&lt;h3&gt;Impact on Existing APIs&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="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;Performance should become better because of more optimal implementation.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="configuration-impact"&gt;
&lt;h3&gt;Configuration Impact&lt;/h3&gt;
&lt;p&gt;Configuration options should be added to setup Pika client library.&lt;/p&gt;
&lt;p&gt;The next configuration possibilities are suggested:&lt;/p&gt;
&lt;section id="connection-options-represents-pika-functionality"&gt;
&lt;h4&gt;Connection options (represents Pika functionality):&lt;/h4&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;‘channel_max’ (default - 0) - Maximum number of channels to allow,&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;‘frame_max’ (default - 131072) - The maximum byte size for an AMQP frame,&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;‘heartbeat_interval’ (default - 0) - How often to send heartbeats,&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;‘ssl’ (default - False) - Enable SSL or not,&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;‘ssl_options’ (default - None) - SSL options if ssl is enabled,&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;‘socket_timeout’ (default - 0.25) - Socket timeout for Pika connections,&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="connection-pool-options"&gt;
&lt;h4&gt;Connection pool options:&lt;/h4&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;‘pool_max_size’ (default - 10) - Maximum number of connections to keep
queued,&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;‘pool_max_overflow’ (default - 10) - Maximum number of connections to create
above&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;‘pool_timeout’ (default - 30) - Number of seconds to wait for available
connection,&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;‘pool_recycle’ (default - None) - Lifetime of a connection (since creation)
in seconds or None for no recycling. Expired connections are closed on
acquire,&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;‘pool_stale’ (default - None) - Threshold at which inactive (since release)
connections are considered stale in seconds or None for no staleness. Stale
connections are closed on acquire&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="reconnection-policy-options"&gt;
&lt;h4&gt;Reconnection policy options:&lt;/h4&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;‘connection_retry_attempts’ (default - 3) - Reconnecting retry count in case
of connectivity problem,&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;‘connection_retry_delay’ (default - 0.1) - Reconnecting retry delay in case
of connectivity problem,&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;‘rejected_message_retry_attempts’ (default - 3) - Resend rejected messages
retry count,&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;‘rejected_message_retry_delay’ (default - 0.1) - Resend rejected messages
retry delay&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="rpc-options"&gt;
&lt;h4&gt;RPC options:&lt;/h4&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;‘rpc_queue_expiration’ (default - 60) - Time to live for rpc queues without
consumers in seconds,&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;‘default_rpc_exchange’ (default - “openstack_rpc”) - Exchange name for sending
RPC messages,&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;‘rpc_reply_exchange’ (default - “openstack_rpc_reply”) - Exchange name for
receiving RPC replies.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="notification-options"&gt;
&lt;h4&gt;Notification options:&lt;/h4&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;‘notification_persistence’ (default - False) - Persist notification messages,&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;‘default_notification_exchange’ (default - “openstack_notification”) -
Exchange name for sending notifications.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer Impact&lt;/h3&gt;
&lt;p&gt;Devstack should be adapted to be able to setup gate test environment with
new driver.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing-impact"&gt;
&lt;h3&gt;Testing Impact&lt;/h3&gt;
&lt;p&gt;Functional tests should be adapted (without changing test logic).&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="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;dukhlov, yosh-m&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;dukhlov&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="milestones"&gt;
&lt;h3&gt;Milestones&lt;/h3&gt;
&lt;p&gt;Target Milestone for completion: mitaka&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;Design and implement rpc functionality (send and listen driver methods)
based on Pika library functionality&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Design and implement notify functionality (send_notification and
listen_notifications driver methods)
based on Pika library functionality&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Adapt functional tests&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Adapt devstack to be able to setup environment with new Pika driver&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="incubation"&gt;
&lt;h2&gt;Incubation&lt;/h2&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;section id="adoption"&gt;
&lt;h3&gt;Adoption&lt;/h3&gt;
&lt;p&gt;Deployment guide may slightly differ because of some new config options added
(e.g. additional ports allocated for each pipeline).&lt;/p&gt;
&lt;p&gt;It worth noting that during stabilization period both drivers the old and the
new one will stay in repos. After stabilization is over the old driver will
be deprecated over a standard deprecation path.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="library"&gt;
&lt;h3&gt;Library&lt;/h3&gt;
&lt;p&gt;oslo.messaging&lt;/p&gt;
&lt;/section&gt;
&lt;section id="anticipated-api-stabilization"&gt;
&lt;h3&gt;Anticipated API Stabilization&lt;/h3&gt;
&lt;p&gt;The new driver should successfully run with adapted devstack.
Adapted oslo.messaging functional tests should successfully pass in
devstack-gate.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Detailed doc strings should be written&lt;/p&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;pika library&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="https://github.com/dukhlov/oslo.messaging/blob/master/oslo_messaging/_drivers/impl_pika.py"&gt;https://github.com/dukhlov/oslo.messaging/blob/master/oslo_messaging/_drivers/impl_pika.py&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/226348/"&gt;https://review.openstack.org/#/c/226348/&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This work is licensed under a Creative Commons Attribution 3.0
Unported License.
&lt;a class="reference external" href="http://creativecommons.org/licenses/by/3.0/legalcode"&gt;http://creativecommons.org/licenses/by/3.0/legalcode&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
</description><pubDate>Fri, 29 Mar 2019 00:00:00 </pubDate></item><item><title>External Policy Decision Point</title><link>https://specs.openstack.org/openstack/oslo-specs/specs/queens/external-pdp.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/oslo.policy/+spec/external-pdp-for-oslo-policy"&gt;bp external-pdp-for-keystone&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Keystone, together with Oslo_policy, provides a native authorization policy engine for OpenStack.
There are several defaults about the solution:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;based on a file: policy.yaml (or policy.json) owned by each OpenStack component (Nova, Glance, Neutron, …)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;hard to understand&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;not flexible to configure&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;based only on one authorization (access control) model&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As OpenStack may be deployed by different users with different requirements,
a generic yet flexible approach is needed through which users may define,
apply and manage their own authorization policy.
External PDP (Policy Decision Point) disables the default way and delegates authorization
to an external authorization policy engine.&lt;/p&gt;
&lt;p&gt;Existing works [&lt;a class="reference external" href="https://review.openstack.org/#/c/237521/"&gt;Fortress&lt;/a&gt;, &lt;a class="reference external" href="https://git.opnfv.org/cgit/moon/tree/keystone-moon"&gt;Moon&lt;/a&gt;] show the feasibility of this approach with the Fortress and Moon
policy engines.
This specification proposes a generic hook which will re-direct authorization requests to an
external PDP instead of using the native one.
Each policy engine stores and manages related information of their policy, grants or denies requests
based on these information and their own rules.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem Description&lt;/h2&gt;
&lt;p&gt;Currently, if a user wants to modify the authorization policy for his/her OpenStack platform,
he/she must update the policy.yaml file for each component (Nova, Glance, Neutron, …).&lt;/p&gt;
&lt;p&gt;The only authorization model allowed is based on a RBAC model (Role Based Access Control) and the
operator cannot modify this model.
But in some case, he/she may want to add new information like membership and authorize actions in
his/her platform based on his membership, e.g. MLS (Multi-Level Security) is widely used for
information flow access control.&lt;/p&gt;
&lt;p&gt;The policy modification must be done on all component with the risk of error appearing.
The policy modification is not centralized.&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 proposes to allow users to chose their PDP (Policy Decision Point).
User will be able to choose between:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;standard local policy.yaml file&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;external Fortress policy engine platform&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;external Moon policy engine platform&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;…&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The switch between those PDP can be configured and done through the modification of policy.json/yaml.
For each rule, a URL need to be set.
Thus every components that use Oslo_Policy can benefit from this improvement. For example in Glance
policy.json file:&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;"context_is_admin"&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;"default"&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="o"&gt;...&lt;/span&gt;
    &lt;span class="s2"&gt;"get_images"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"http://external_pdp_server:8080/&lt;/span&gt;&lt;span class="si"&gt;{name}&lt;/span&gt;&lt;span class="s2"&gt;s"&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;To be able to communicate with one of those PDP, the hook is based on HTTP_Check of Oslo_Policy.
This API can be as simple as:&lt;/p&gt;
&lt;div class="highlight-javascript notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="nx"&gt;POST&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;authz&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Where the body of POST includes:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;cite&gt;target&lt;/cite&gt; request-related information&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;cite&gt;credentials&lt;/cite&gt; user authentication information&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;cite&gt;rule&lt;/cite&gt; this is the new data that we need to add in HTTP_Check function which identify requested operation&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For example, here are some possible requests:&lt;/p&gt;
&lt;div class="highlight-javascript notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="nx"&gt;POST&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;authz&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The response can just be an HTTP Code return:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;200 when the request is authorized&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;403 when the request is not authorized&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 original spec &lt;a class="reference external" href="https://review.openstack.org/491565"&gt;https://review.openstack.org/491565&lt;/a&gt; was submitted to the keystone project. Due to
the scope responsability, a new spec (this one) is proposed here.&lt;/p&gt;
&lt;p&gt;Through this spec/feature, we could add configuration options to oslo.policy to tell it to bypass
its default rule evaluation system and use an external PDP system.
Doing that would simplify deployer configuration, because they would only need to specify the
location of the PDP system.
It would make the library implementation more complicated, though, so we are going to use this
simpler approach to start.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security Impact&lt;/h3&gt;
&lt;p&gt;As it deals with authorization process, such a change can be a risk for the security.
User data is not modify because data like user ID, object ID and so on are only used in reading mode.
But if the PDP is external, data could be listen or tampered by malicious network sniffers.
Those connections must be highly secured in order to assured that the response of the request
can be truly accepted.&lt;/p&gt;
&lt;p&gt;The only data which could be listened by malicious sniffers will be :&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;the Keystone project ID&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;the user ID&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;the object targeted by the action&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;the action of the user on the object&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Tokens, keys and other sensitive data will not be exposed.
No API change is required by this change.&lt;/p&gt;
&lt;p&gt;This change can lead to a denial of service attack. Specifically if the PDP is external.
If an attacker is able to send a lot of requests through the external interface of the PDP,
he can slow down the authorization computing in the PDP and then slow down the end user
because the end user depends on this authorization process.
To remediate this problem, the external PDP must be place in the network architecture
so that it cannot be accessed by the end user or by a malicious user.
Once OpenStack is configured to use the external PDP and the external PDP is down, no OpenStack
operations will be possible.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h3&gt;Notifications Impact&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;TODO&lt;/strong&gt;: None&lt;/p&gt;
&lt;p&gt;Please specify any changes to notifications. Be that an extra notification,
changes to an existing notification, or removing a notification.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other End User Impact&lt;/h3&gt;
&lt;p&gt;The end user will not interact with this change, on the other hand,
the operator will have to configure this.
In particular, he/she must select the internal/external PDP and select some configuration items including:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;URL of the external PDP&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;username to connect to the external PDP (if needed)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;password to connect to the external PDP (if needed)&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;Because the authorization process is called every time and because this authorization process
can request an external server, it may have performance impact.
Preliminary tests show that in the &lt;a class="reference external" href="https://git.opnfv.org/cgit/moon/tree/keystone-moon"&gt;Moon&lt;/a&gt; platform a authorization process can take up from 0.2 to 1 second.&lt;/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 forces to update the code of Oslo_Policy which is used by a lot of OpenStack component.
But the choice must always allow the operator to use the good old internal PDP (ie the policy.yaml file).
In that case, no change will be visible for him/her.
But if a deployer wants to use this new feature, one external PDP (like the Fortress or Moon
platform) must be ready.
He/she only needs to add the URL of his/her external PDP for the corresponding rules in policy.json
files.&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;Ruan He&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Thomas Duval&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;specify the configuration options needed to use an external PDP&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;modify the Oslo_Policy code by updating the HTTP_Check class to pass rule name being evaluated&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;test the solution, we only need to use the exsting tests for HTTP_Check.&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 make the external PDP understand POST data from the HTTP_Check function:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;a HTTP &lt;a class="reference external" href="https://git.opnfv.org/moon/commit/?id=eadfb789322a1a9887c8a4f23c8f125a39ebc8f4"&gt;proxy&lt;/a&gt; has been contributed to Moon for the interpretation work as a PoC&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;The specific configuration for external PDP must be documented.&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;OpenStack meeting on Keystone Policy: &lt;a class="reference external" href="https://etherpad.openstack.org/p/keystone-policy-meeting"&gt;https://etherpad.openstack.org/p/keystone-policy-meeting&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Keystone policies moving into code: &lt;a class="reference external" href="https://governance.openstack.org/tc/goals/queens/policy-in-code.html"&gt;https://governance.openstack.org/tc/goals/queens/policy-in-code.html&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Proposed modification of Oslo_Policy for the Apache fortress solution: &lt;a class="reference external" href="https://review.openstack.org/#/c/237521/"&gt;https://review.openstack.org/#/c/237521/&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Proposed modification of Oslo_Policy for adding information in the HTTPCheck: &lt;a class="reference external" href="https://review.openstack.org/#/c/498467/"&gt;https://review.openstack.org/#/c/498467/&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Moon implementation of the OPNFV project: &lt;a class="reference external" href="https://git.opnfv.org/cgit/moon/tree/keystone-moon"&gt;https://git.opnfv.org/cgit/moon/tree/keystone-moon&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
</description><pubDate>Fri, 29 Mar 2019 00:00:00 </pubDate></item><item><title>Kafka Driver Revisions for Messaging Notifications</title><link>https://specs.openstack.org/openstack/oslo-specs/specs/queens/update-kafka-support.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/oslo.messaging/+spec/update-kafka-support"&gt;https://blueprints.launchpad.net/oslo.messaging/+spec/update-kafka-support&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This specification proposes changes to the existing kafka driver
that allows notification message transport over the Apache Kafka
distributed streaming platform &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;. The blueprint for the original
driver implementation can be found here &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; and the spec for the
implementation can be found here &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;. The goal of the changes
described by this specification is to transition the driver from
‘experimental’ to ‘supported’ status in order to encourage driver
adoption. The driver will (continue to) only support notification
messaging as the use of the kafka server is non-optimal for RPC
messaging patterns. Thus, this kafka driver is intended for deployment
in hybrid messaging configurations where RPC messaging will be
provided by a separate messaging backend.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;The original kafka driver was introduced during the mitaka release
cycle. Adoption of the driver has been limited due to a number of
factors such as its ‘experimental’ designation and its intended use
for notification messaging only. Meanwhile, the kafka server has experienced
widespread adoption and is frequently included in application
architectures to provide accurate analytics in cloud monitoring
systems. This success and the progression of configuration frameworks
to easily enable hybrid messaging deployments in OpenStack is a
catalyst to revise this driver and provide active maintenance and
support going forward.&lt;/p&gt;
&lt;p&gt;Kafka hybrid oslo.messaging deployment:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;   &lt;span class="o"&gt;+------------+&lt;/span&gt;          &lt;span class="o"&gt;+----------+&lt;/span&gt;
   &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;RPC&lt;/span&gt; &lt;span class="n"&gt;Caller&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;          &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Notifier&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
   &lt;span class="o"&gt;+-----+------+&lt;/span&gt;          &lt;span class="o"&gt;+----+-----+&lt;/span&gt;
         &lt;span class="o"&gt;|&lt;/span&gt;                      &lt;span class="o"&gt;|&lt;/span&gt;
         &lt;span class="o"&gt;|&lt;/span&gt;                      &lt;span class="o"&gt;|&lt;/span&gt;
         &lt;span class="n"&gt;v&lt;/span&gt;                      &lt;span class="n"&gt;v&lt;/span&gt;
&lt;span class="o"&gt;+-------------------+&lt;/span&gt;  &lt;span class="o"&gt;+-------------------+&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;       &lt;span class="n"&gt;RPC&lt;/span&gt;         &lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt;    &lt;span class="n"&gt;Notification&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Messaging&lt;/span&gt; &lt;span class="n"&gt;Backend&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Messaging&lt;/span&gt; &lt;span class="n"&gt;Backend&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;amqp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt;     &lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt;    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kafka&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;     &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;    &lt;span class="n"&gt;rabbit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;     &lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt;                   &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;+--------+----------+&lt;/span&gt;  &lt;span class="o"&gt;+--------+----------+&lt;/span&gt;
         &lt;span class="o"&gt;|&lt;/span&gt;                      &lt;span class="o"&gt;|&lt;/span&gt;
         &lt;span class="o"&gt;|&lt;/span&gt;                      &lt;span class="o"&gt;|&lt;/span&gt;
         &lt;span class="n"&gt;v&lt;/span&gt;                      &lt;span class="n"&gt;v&lt;/span&gt;
   &lt;span class="o"&gt;+------------+&lt;/span&gt;        &lt;span class="o"&gt;+------+-------+&lt;/span&gt;
   &lt;span class="o"&gt;|&lt;/span&gt;    &lt;span class="n"&gt;RPC&lt;/span&gt;     &lt;span class="o"&gt;|&lt;/span&gt;        &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Notification&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
   &lt;span class="o"&gt;|&lt;/span&gt;   &lt;span class="n"&gt;Server&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt;        &lt;span class="o"&gt;|&lt;/span&gt;    &lt;span class="n"&gt;Server&lt;/span&gt;    &lt;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="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;The revision to the kafka driver is not a major rework. A number of
issues need to be resolved in order to support Notifications over a
kafka server messaging backend:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;release updates&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;virtual host (vhost) emulation&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;encryption and authentication&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;driver aspects&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;functional and integration testing&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;section id="release-updates"&gt;
&lt;h3&gt;Release Updates&lt;/h3&gt;
&lt;p&gt;The driver should be updated to support the latest kakfa server
software release. As of this writing, the latest versions are:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;scala version - 2.12&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;kafka version - 1.0.0&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;kafka-python version - 1.35&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="virtual-hosts-vhost-emulation"&gt;
&lt;h3&gt;Virtual Hosts (vhost) Emulation&lt;/h3&gt;
&lt;p&gt;Currently, only the rabbitmq messaging backend supports vhosts
contained in the transport url &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;. Since the kafka server
architecture does not natively support vhosts, the kafka driver
revision will emulate vhost support by adding the virtual host name to
the topic created on the kafka server. This will effectively
create a private topic per virtual host that is configured for use.&lt;/p&gt;
&lt;p&gt;Related to this change the devstack kafka plugin will
need to be updated so that the kafka backend does not fail.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="encryption-and-authentication"&gt;
&lt;h3&gt;Encryption and Authentication&lt;/h3&gt;
&lt;p&gt;The Apache Kafka allows clients to connect over SSL. By default, SSL
is disabled and the kafka driver will be updated to enable it via
configuration. This release will support server authentication and
client authentication will be planned for a future release and will
be dependent upon client library capabilties. The configuration for
SSL will be the same for both producer and consumer:&lt;/p&gt;
&lt;p&gt;In section [oslo_messaging_kafka]:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;ssl - attempt to connect via ssl&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;ssl_ca_file - file containing the trusted CA’s digital certificate&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;SASL may be used with PLAINTEXT or SSL as the transport layer when
there is a username and password present in the transport_url.  The
SASL configuration support is currently for PLAIN authentication
only. The following configuration options will be provided by the driver:&lt;/p&gt;
&lt;p&gt;In section [oslo_messaging_kafka]:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;sasl_mechanisms - space separated list of acceptable SASL mechanisms&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="driver-aspects"&gt;
&lt;h3&gt;Driver Aspects&lt;/h3&gt;
&lt;p&gt;The revision to the kafka driver will include updates to a number of
driver functional aspects to incorporate new features and to enhance
driver support-ability:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;config options - update the driver configuration options to include
new security options as well as remove deprecated options removed
from the oslo messaging library &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;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;logging - add additional info, warning, debug messages to the driver
to help operational and debugging tasks when deploying the driver&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;check python client - check for installed library dependencies&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;connection management - review and identify any simplification that
would benefit driver operation and support&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;ack/requeue message - investigate support of manual message commit
in order to support message requeue following notify message dispatch&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Presently, there are alternative oslo messaging drivers that can be used
for different messaging backends. With hybrid messaging support, there
is the flexibility to optimally align the messaging backend with the
RPC or Notification communication patterns provided by the oslo
messaging library. The objective to support and maintain the kafka
driver should enhance the overall value of oslo messaging by providing
users messaging backend alternatives that best suit their operational
objectives and needs.&lt;/p&gt;
&lt;p&gt;The alternative is to deprecate this driver and support a single
messaging backend for notifications (e.g. rabbit broker).&lt;/p&gt;
&lt;/section&gt;
&lt;section id="impact-on-existing-apis"&gt;
&lt;h3&gt;Impact on Existing APIs&lt;/h3&gt;
&lt;p&gt;The existing API should not require any changes. The changes to the
kafka driver will preserve compatibility with existing experimental
kafka deployments and will not affect other oslo.messaging drivers.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;With the additional support of authentication and encryption, there will
be an expansion of the security model provided by the driver through
its use of the python client library and its interactions with the
kafka server for message exchange.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;Any performance impact should be limited to the users of the kafka
driver for messaging notifications. Users of other drivers such as
rabbitmq and amqp 1.0 will not be affected. Any performance changes
realized in the kafka driver update may be due to:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;changes to the underlying kafka protocol in the new server version&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="configuration-impact"&gt;
&lt;h3&gt;Configuration Impact&lt;/h3&gt;
&lt;p&gt;New configuration items for authentication and security will be added
as detailed above. The default value for these options will be
determined as the driver is updated and revised.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer Impact&lt;/h3&gt;
&lt;p&gt;To be considered as supported, any new features added to
oslo.messaging that must be implemented via driver modification should
be implemented in the kafka driver as well. In the circumstance when a
new feature requires behaviors/capabilities that cannot be provided by
kafka, clients attempting to use the feature will cause a
NotImplementedError exception to be raised. Additionally, the absence
of supported functionality must be documented and included in the
release notes.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing-impact"&gt;
&lt;h3&gt;Testing Impact&lt;/h3&gt;
&lt;p&gt;The kafka server will be used as the messaging backend for
notifications in testing. An alternative backend such as rabbit or
amqp 1.0 should be used as the messaging backend for RPC.&lt;/p&gt;
&lt;p&gt;The kafka driver tests should be expanded as necessary for the new
features and capabilities in the update and the driver must pass all tests.&lt;/p&gt;
&lt;p&gt;The driver must pass the following gate checks with deployed in a
hybrid messaging configuration (e.g. when kafka is configured as the
notification backend):&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;oslo.messaging-tox-py27-func-kafka&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;oslo.messaging-tox-py35-func-kafka&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;oslo.messaging-src-dsvm-full&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;oslo.messaging-telemetry-dsvm-integration&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;oslo.messaging-tempest-neutron-dsvm-src&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The zookeeper, kafka, jdk and client will need to be avabilable in the
CI environment in order to fully test this driver.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;&lt;a class="reference external" href="mailto:ansmith%40redhat.com"&gt;ansmith&lt;span&gt;@&lt;/span&gt;redhat&lt;span&gt;.&lt;/span&gt;com&lt;/a&gt;  (ansmith on IRC)&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;&lt;a class="reference external" href="mailto:kgiusti%40gmail.com"&gt;kgiusti&lt;span&gt;@&lt;/span&gt;gmail&lt;span&gt;.&lt;/span&gt;com&lt;/a&gt;  (kgiusti on IRC)&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="milestones"&gt;
&lt;h3&gt;Milestones&lt;/h3&gt;
&lt;p&gt;Target Milestone for completion: queens&lt;/p&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Update environment for latest software release updates and dependencies&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Implement virtual hosts support&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Implement SSL and SASL integration&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Implement new configuration items&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;Functional test integration&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update devstack plugin&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Upstream CI integration&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Send announcement to openstack-discuss following release&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="incubation"&gt;
&lt;h2&gt;Incubation&lt;/h2&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;section id="adoption"&gt;
&lt;h3&gt;Adoption&lt;/h3&gt;
&lt;p&gt;The kafka driver is expected to be adopted in hybrid messaging deployments
as the notification messaging backend. Adoption is likely in environments
that already have kafka servers broadly deployed (e.g. operational
benefit) or where the characteristics of the kafka server best suit
the information analytics requirements.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="library"&gt;
&lt;h3&gt;Library&lt;/h3&gt;
&lt;p&gt;oslo.messaging&lt;/p&gt;
&lt;/section&gt;
&lt;section id="anticipated-api-stabilization"&gt;
&lt;h3&gt;Anticipated API Stabilization&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;The kafka driver documentation will be added to the libary. This
documentation will follow the style of documentation provided by the
other drivers and should include the following topics:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;theory of operation (overview) of the Apache Kafka messaging backend&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;pre-requisites&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;driver options overview&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;kafka server operations&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;devstack support&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;platforms and software&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;The driver revision will require no additional dependencies.&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://kafka.apache.org/"&gt;https://kafka.apache.org/&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://blueprints.launchpad.net/oslo.messaging/+spec/adding-kafka-support"&gt;https://blueprints.launchpad.net/oslo.messaging/+spec/adding-kafka-support&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id8" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id3"&gt;3&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://review.openstack.org/#/c/189003/6/specs/liberty/adding-kafka-support.rst"&gt;https://review.openstack.org/#/c/189003/6/specs/liberty/adding-kafka-support.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="#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://bugs.launchpad.net/oslo.messaging/+bug/1706987"&gt;https://bugs.launchpad.net/oslo.messaging/+bug/1706987&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://etherpad.openstack.org/p/oslo-queens-tasks"&gt;https://etherpad.openstack.org/p/oslo-queens-tasks&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;/aside&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This work is licensed under a Creative Commons Attribution 3.0
Unported License.
&lt;a class="reference external" href="http://creativecommons.org/licenses/by/3.0/legalcode"&gt;http://creativecommons.org/licenses/by/3.0/legalcode&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
</description><pubDate>Fri, 04 Jan 2019 00:00:00 </pubDate></item><item><title>Proposals for new libraries</title><link>https://specs.openstack.org/openstack/oslo-specs/specs/policy/new-libraries.html</link><description>

&lt;p&gt;Quite often Oslo (as a group and project) is requested to create (or adopt)
new libraries for various purposes (some relevant, some not) and it would be
good to (as a group) have a stance on new libraries and the process they need
to go through to either become a new library in Oslo (that the Oslo group will
&lt;em&gt;own&lt;/em&gt; and maintain going forward) or to become a new library that is
independently maintained on pypi (or some hybrid of both of these approaches).&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem Description&lt;/h2&gt;
&lt;p&gt;Assume developer &lt;em&gt;Bob&lt;/em&gt; wants to make a new library for project(s) in
OpenStack to consume.&lt;/p&gt;
&lt;p&gt;Bob at that point has a few options when building out this library:&lt;/p&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;&lt;p&gt;Keep the library independent from the Oslo project. Create library in
some repository site and produce a functional and useful artifact from
that library (typically a pypi release) and integrate it into the various
OpenStack projects once that artifact is created.&lt;/p&gt;
&lt;p&gt;Some &lt;strong&gt;advantages&lt;/strong&gt; of this are:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Bob can work, release, iterate at his own pace.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Wider python community adoption can start &lt;strong&gt;immediately&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Some &lt;strong&gt;disadvantages&lt;/strong&gt; of this are:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Hard to define/find purpose for a library when it is not initially
integrated into any project (typically to create a good library it
helps to have an active user of that library for feedback).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Gamble in that adoption (in the larger python community or in
general) may not occur.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;No direct ability to take advantage of expertise (reviews, experience…)
developed in the wider Oslo group (aka the creator is on
his/her own).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create library in some repository site and produce a functional and useful
artifact from that library (typically a pypi release) and integrate it
into the various OpenStack projects (either by oneself or with others
to help) and then propose that the library be moved into the Oslo group’s
ownership for some reasons like it’s not maintained by owner but it is
used across OpenStack projects.&lt;/p&gt;
&lt;p&gt;Some &lt;strong&gt;advantages&lt;/strong&gt; of this are (including prior option’s advantages):&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Continued maintenance (and reviews) of created library are now shared
among the oslo reviewers (and group).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Some &lt;strong&gt;disadvantages&lt;/strong&gt; of this are (including prior options disadvantages):&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Continued maintenance (and reviews) of created library are now shared
among the oslo reviewers (and group). The creator may lose of control.
must follow Oslo’s policies.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There are also a few misconceptions about this approach that should also
be cleared up (these conceptions may have been previously warranted but
due to changes in the community they no longer should be deemed so):&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Adoption in oslo does &lt;strong&gt;not&lt;/strong&gt; guarantee success of a library (it will
still be a large amount of convincing and hard and dirty work to
be successful).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The big tent makes it easier for a library to integrate into the
OpenStack ecosystems processes without having to join Oslo to also
benefit from that same ecosystems processes.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Example &lt;strong&gt;oslo&lt;/strong&gt; libraries that followed this workflow:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;automaton&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;futurist&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create library immediately having the Oslo group or subgroup (and by
default use the OpenStack ecosystem) help in its creation and produce a
functional and useful artifact from that library (typically a pypi
release) and integrate it into the various openstack projects.&lt;/p&gt;
&lt;p&gt;Some &lt;strong&gt;advantages&lt;/strong&gt; of this are (including prior options advantages):&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;The expertise (years of experience, smart people) the Oslo group has
can help guide the libraries success.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Continued maintenance (and reviews) of created library are now shared
among the Oslo reviewers (and group). The creator may lose of control,
since the project is now under Oslo’s purview they can approve specs
and changes that creator might not agree with.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Some &lt;strong&gt;disadvantages&lt;/strong&gt; of this are (including prior options disadvantages):&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Continued maintenance (and reviews) of created library are now shared
among the Oslo reviewers (and group).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Same misconceptions as stated in previous item.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Example &lt;strong&gt;oslo&lt;/strong&gt; libraries that followed this workflow:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;tooz&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;debtcollector&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;oslo.privsep&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create library inside of a project, prove it is useful to its host
project (without becoming so specific to that host project that it is not
useful to anyone else) &lt;em&gt;then&lt;/em&gt; extract that library to some repository site
and produce a useful artifact. Following this further maintenance at that
point will be via that repository site.&lt;/p&gt;
&lt;p&gt;Some &lt;strong&gt;advantages&lt;/strong&gt; of this are:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Usefulness/purpose of the library will be more well-known due to
integration with a host project.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Some &lt;strong&gt;disadvantages&lt;/strong&gt; of this are:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Usefulness/purpose can be &lt;em&gt;too&lt;/em&gt; specific to host project (and
further extraction/refactoring work will be needed to generalize).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Example &lt;strong&gt;oslo&lt;/strong&gt; libraries that followed this workflow:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;taskflow&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;oslo.versionedobjects&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create source code in a host project, at a point where another host
project would benefit from that same code then extract source code into
a common incubator. At that point iterate over versions in that incubator
and periodically sync incubator version into host consuming projects.
At some point when deemed &lt;em&gt;stable&lt;/em&gt; extract the incubators version into
a library and then produce a functional and useful artifact from that
library (typically a pypi release). Following this further maintenance at
that point will be via the new library repository site (and typically
versioning will be followed).&lt;/p&gt;
&lt;p&gt;Some &lt;strong&gt;advantages&lt;/strong&gt; of this are:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Usefulness/purpose of the library will be more well-known due to
integration with a &lt;em&gt;set&lt;/em&gt; of host projects.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Some &lt;strong&gt;disadvantages&lt;/strong&gt; of this are:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Typically a larger number of iterations required to extract a
isolated artifact.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Multiple rounds of non-versioned syncing and potential
API collisions/conflicts (due to incubator copy/paste routine) and
change iteration.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;No ability for wider python community adoption from the get go.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Harder to cleanup and track.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Implementations will likely diverge and the amount of person time
required to keep in sync.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Example &lt;strong&gt;oslo&lt;/strong&gt; libraries that followed this workflow:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;oslo.config&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;oslo.cache&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;oslo.concurrency&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;oslo.db&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;oslo.log&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;oslo.messaging&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;oslo.policy&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;oslo.serialization&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;…&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Bob will also have to pick which repository site he will use. For sake
of this document we will assume the majority will choose to use the OpenStack
ecosystems gerrit review system and git based hosting system (but Bob if
he desires can use something like github and pull requests if
he so chooses, as long as Bob takes into consideration that doing this
will be make it harder to get contributions from folks in the OpenStack
community).&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-policy"&gt;
&lt;h2&gt;Proposed Policy&lt;/h2&gt;
&lt;p&gt;In order to help Bob (or other author) make a &lt;em&gt;smart&lt;/em&gt; selection from the
options listed above in the problem statement we as a group (who has
made these decisions many times previously) would like to
help new libraries (and their authors) become successful by having
new library proposals go through a sort of &lt;em&gt;litmus test&lt;/em&gt; that we as a group
believe will help library creators figure out which of the above listed
options will be better suited for them (and be better suited for their own
library’s future success).&lt;/p&gt;
&lt;p&gt;To aid in this process we as a group believe that when Bob (or other author)
starts to figure out which of the options he (or she) will take it would
be best for that developer to fill out the template new-library-template.rst
and post it for review on the openstack-discuss mailing list with the [oslo] tag
in the subject. And then let the mailing list figure out which of the above
options will best work for the authors and the community as a whole). This
same information should also be proposed to the oslo-specs repository itself
(if/when the mailing list agrees that it should be a new oslo library).&lt;/p&gt;
&lt;p&gt;In order to make the new oslo library healthy and continuous development,
new core contributors for that adopted library are needed, it needs at least
two individuals from the community committed to triaging and fixing bugs, and
responding to test failures in a timely manner.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="alternatives-history"&gt;
&lt;h2&gt;Alternatives &amp;amp; History&lt;/h2&gt;
&lt;p&gt;The other options are more along the line of what the Oslo group has
already done which is to have a sort of impromptu and tribal knowledge
around the area of new libraries and the options available to developers
wanting (and/or willing) to make new libraries. This policy will aim to
solidify that knowledge into a document that can be easily referenced and
agreed upon.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="author-s"&gt;
&lt;h3&gt;Author(s)&lt;/h3&gt;
&lt;p&gt;Primary author: harlowja&lt;/p&gt;
&lt;p&gt;Other contributors: gcb&lt;/p&gt;
&lt;/section&gt;
&lt;section id="milestones"&gt;
&lt;h3&gt;Milestones&lt;/h3&gt;
&lt;p&gt;Pike&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;Draft policy&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Get feedback on policy&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Repeat&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Approve policy&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&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-oslo-maybe-new-libraries"&gt;https://etherpad.openstack.org/p/newton-oslo-maybe-new-libraries&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="revision-history"&gt;
&lt;h2&gt;Revision 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;Pike&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;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This work is licensed under a Creative Commons Attribution 3.0
Unported License.
&lt;a class="reference external" href="http://creativecommons.org/licenses/by/3.0/legalcode"&gt;http://creativecommons.org/licenses/by/3.0/legalcode&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
</description><pubDate>Tue, 04 Dec 2018 00:00:00 </pubDate></item><item><title>Contributing to: oslo-specs</title><link>https://specs.openstack.org/openstack/oslo-specs/contributing.html</link><description>

&lt;p&gt;If you would like to contribute to the development of OpenStack,
you must follow the steps in this page:&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;&lt;a class="reference external" href="https://docs.openstack.org/infra/manual/developers.html"&gt;https://docs.openstack.org/infra/manual/developers.html&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;Once those steps have been completed, changes to OpenStack
should be submitted for review via the Gerrit tool, following
the workflow documented at:&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;&lt;a class="reference external" href="https://docs.openstack.org/infra/manual/developers.html#development-workflow"&gt;https://docs.openstack.org/infra/manual/developers.html#development-workflow&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;Pull requests submitted through GitHub will be ignored.&lt;/p&gt;
&lt;p&gt;Bugs should be filed on Launchpad, not GitHub:&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;&lt;a class="reference external" href="https://bugs.launchpad.net/oslo"&gt;https://bugs.launchpad.net/oslo&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;&lt;/blockquote&gt;
</description><pubDate>Wed, 14 Nov 2018 00:00:00 </pubDate></item><item><title>oslo-specs</title><link>https://specs.openstack.org/openstack/oslo-specs/readme.html</link><description>

&lt;p&gt;OpenStack Common Libraries (Oslo) Specifications&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Free software: Apache license&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Documentation: &lt;a class="reference external" href="https://specs.openstack.org/openstack/oslo-specs"&gt;https://specs.openstack.org/openstack/oslo-specs&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;section id="features"&gt;
&lt;h2&gt;Features&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;TODO&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
</description><pubDate>Wed, 14 Nov 2018 00:00:00 </pubDate></item><item><title>(Placeholder Spec)</title><link>https://specs.openstack.org/openstack/oslo-specs/specs/train/placeholder.html</link><description>

&lt;p&gt;This file is just a placeholder for the specs directory.
It will be removed soon after some spec is merged.&lt;/p&gt;
&lt;p&gt;The latest spec template is found at &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;specs/template.rst&lt;/span&gt;&lt;/code&gt;
in the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo-specs&lt;/span&gt;&lt;/code&gt; repository.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem Description&lt;/h2&gt;
&lt;p&gt;Sphinx toctree complains if no file exists in a directory
specified in toctree glob.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed Change&lt;/h2&gt;
&lt;p&gt;Add this file.&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, 14 Nov 2018 00:00:00 </pubDate></item><item><title>Feature Freeze</title><link>https://specs.openstack.org/openstack/oslo-specs/specs/policy/feature-freeze.html</link><description>

&lt;p&gt;Because Oslo does releases on a different schedule from many of the rest of
the OpenStack projects, it is helpful to have some modified policies around
feature freeze as well.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem Description&lt;/h2&gt;
&lt;p&gt;Oslo wants to respect the feature freeze date that is set for the OpenStack
community as a whole, but due to the nature of libraries it can be
problematic for us to continue adding new features right up until the official
feature freeze.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-policy"&gt;
&lt;h2&gt;Proposed Policy&lt;/h2&gt;
&lt;p&gt;Projects in the Oslo program will observe their own feature freeze, which will
occur one week before the final non-client library release and continue until
all of the consuming OpenStack projects have made their releases for the
cycle.  This is a hard freeze, and as such only critical bug fixes should
merge during the freeze period.&lt;/p&gt;
&lt;p&gt;Freezing early will provide time to release any pending changes in the Oslo
libraries before the consuming projects enter feature freeze.&lt;/p&gt;
&lt;section id="exceptions"&gt;
&lt;h3&gt;Exceptions&lt;/h3&gt;
&lt;p&gt;This policy will not apply to libraries that have not yet been released.
Any in-progress work on those can continue through feature freeze as it will
not affect any frozen projects.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="alternatives-history"&gt;
&lt;h2&gt;Alternatives &amp;amp; History&lt;/h2&gt;
&lt;p&gt;We could simply observe the overall feature freeze date, but due to library
release cycles that may result in new features being released during feature
freeze.&lt;/p&gt;
&lt;p&gt;Another option would be to not observe feature freeze at all and rely on our
release-to-release compatibility requirements to handle any issues.  This
would not only make it more likely for us to release a buggy version of a lib
during feature freeze, but it should be unnecessary as our consumers would be
unable to implement any new features exposed in Oslo libraries during that
time anyway.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="author-s"&gt;
&lt;h3&gt;Author(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary author:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;bnemec&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;dhellmann&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="milestones"&gt;
&lt;h3&gt;Milestones&lt;/h3&gt;
&lt;p&gt;One week before final non-client library release&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;Make an announcement on the mailing list on the date of Oslo feature freeze&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="http://eavesdrop.openstack.org/meetings/oslo/2015/oslo.2015-01-26-16.00.log.html#l-180"&gt;http://eavesdrop.openstack.org/meetings/oslo/2015/oslo.2015-01-26-16.00.log.html#l-180&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Library stable branches: &lt;a class="reference external" href="https://review.openstack.org/#/c/155072/"&gt;https://review.openstack.org/#/c/155072/&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="revision-history"&gt;
&lt;h2&gt;Revision 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;Kilo&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Rocky&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Modified to better reflect current release landscape&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This work is licensed under a Creative Commons Attribution 3.0
Unported License.
&lt;a class="reference external" href="http://creativecommons.org/licenses/by/3.0/legalcode"&gt;http://creativecommons.org/licenses/by/3.0/legalcode&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
</description><pubDate>Tue, 05 Jun 2018 00:00:00 </pubDate></item><item><title>Run database tests within long-lived schemas and transactionalized containers</title><link>https://specs.openstack.org/openstack/oslo-specs/specs/kilo/long-lived-transactionalized-db-fixtures.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/oslo/+spec/long-lived-transactionalized-db-fixtures"&gt;https://blueprints.launchpad.net/oslo/+spec/long-lived-transactionalized-db-fixtures&lt;/a&gt;&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;OpenStack applications currently do not include a standard technique of
testing database-enabled code against any number of potential database
backends.  The techniques that are available themselves have issues
that keep them from being practical in a general sense.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;It is common that the test suite of a particular OpenStack component
is ultimately hardcoded to run on the SQLite backend.   SQLite is chosen
both for it’s simplicity and great speed of schema setup, but is not
the actual database used in OpenStack environments.  The system by which
this connectivity is established is often buried and spread across
multiple files, with no option to alter what database is used.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;There is no solution to the case of the component that wishes to run hundreds
of tests against a common schema, without requiring that the schema
in question is built and torn down for every test.  This makes it
infeasible for the test suite to be run against non-SQLite backends on
a regular basis, as the cost of this setup and teardown is too time
consuming.  A typical approach to
this problem is to run tests inside of transactions which are rolled
back at the end of the test, thereby allowing the schema to
remain present.  However, experiments with simplistic, single-database
versions of this approach have failed due to the use of parallel testing,
as well as being able to allow tests themselves to retain rudimental
“commit/rollback” functionality without impacting the isolation of the
fixture.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;While there is a system by which an application can run a suite of tests
against other backends, known as the “Opportunistic” test suite, currently
the “opportunistic” suite will fix those tests against a single, alternate
backend, such as MySQL or Postgresql.    While a “stub” suite can be added
for each desired backend so that the same tests run on each, this approach
does not accommodate attempting to run the suite against new backends
not anticipated by the application, and also places the responsibility
on the developer to ensure that all tests which apply to variable backends
include that these “stubs” are present in multitude.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The connection URL for “opportunistic” tests is also a fixed URL, with a
hardcoded username/password and the requirement that the database is on
localhost.   If such a URL is connectable, it is used.  This hardcoding
and “opportunistic” style makes it inconvenient to control how tests run;
for example, a workstation that has both MySQL and Postgresql servers running
with the hardcoded username/password available cannot control a test run to
only test against one or the other, or neither, of these databases; the suite
will always run applicable tests against both based on their presence.  It
is also not possible for the developer to point the test suite at a
server running on a host other than “localhost”.   The scheme used by
this system is also hardcoded to the notion of a user/password/hostname
based configuration; it can’t work for databases that connect using a
data source name or other symbolic name.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The system by which “opportunistic” tests create and drop databases does
not offer adequate extensibility for new backends.&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 proposed changes will in all cases ensure that total compatibility is
retained for all current test setup techniques.  The opportunistic system
will continue to work as it does now, but offer environmental options to
alter its behavior.&lt;/p&gt;
&lt;p&gt;The key component will be the oslo/db/sqlchemy/provision.py
module, as well as the oslo/db/sqlalchemy/test_base.py module.
This provision module currently contains logic which handles the creation
and dropping of anonymously named databases within the Postgresql and
MySQL backends.   When combined with the OpportunisticFixture, it
creates/drops an anonymously named database per test setup/teardown.
test_base includes the base test classes and fixtures which make
use of provision.py for connectivity.&lt;/p&gt;
&lt;p&gt;These modules will be enhanced to include several new constructs,
described in the following sections.&lt;/p&gt;
&lt;section id="backend"&gt;
&lt;h3&gt;Backend&lt;/h3&gt;
&lt;p&gt;This is an extensible “backend” system, based on a base class known as
the Backend and used by the provision module.  Backend will
encapsulate the tasks needed in order to run tests against a particular
backend, including:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;the ability to detect if a given database is available, either
“opportunistically” or through environmental settings&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;the ability to create, drop, and detect the presence of “anonymously”
named databases&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;the ability to produce a connection URL that will directly access this
database upon connect&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;the ability to drop individual all schema objects within
a database of this type.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Logic for these features can vary across backends.  For SQLite, which may be
using in-memory databases or file-based databases, the URL scheme
is SQLite-specific and needs to be generated from an anonymous schema
name in a special way.  For a Postgresql database, the backend will benefit
by including the feature of disconnecting all users from a target database
before dropping it, or being able to handle Postgresql’s ENUM
type that must be dropped explicitly when erasing the objects within
a database.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="opportunistic-urls"&gt;
&lt;h3&gt;Opportunistic URLs&lt;/h3&gt;
&lt;p&gt;The Backend system can report on whether or not a database of a particular
backend type (e.g. MySQL, SQlite, Postgresql, etc) is available based on
the “opportunistic” URL system.  This system defaults to searching for
a database given a fixed connectivity profile.   Suppose the system
includes a Backend implementation for each of: SQlite, Postgresql, and
MySQL.  Each of these backend implementations reports on a candidate
“opportunistic” URL; a URL such as
“postgresql://openstack_citest:openstack_citest@localhost” that can be tested
for connectivity.   Without any configuration, the system will attempt
to make available “opportunstic” URLs for each BackendImpl that is implemented.
In this way, the system works pretty much as it does today.&lt;/p&gt;
&lt;p&gt;However,  to make it configurable at runtime, we will enhance the role
of the OS_TEST_DBAPI_ADMIN_CONNECTION environment variable.  The
current system allows this variable to specify a single “override” URL
that is linked to the SQLite tests, but not the “opportunistic” ones.
In the new system, it will allow a list of URLs, separated by a
semicolon.  For example, a value that allows tests to run against a specific
SQLite database as well as a Postgresql database:&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;OS_TEST_DBAPI_ADMIN_CONNECTION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;\
       &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;sqlite&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;\
       &lt;span class="n"&gt;postgresql&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;psycopg2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="n"&gt;scott&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;tiger&lt;/span&gt;&lt;span class="nd"&gt;@localhost&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;openstack&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;When an explcit OS_TEST_DBAPI_ADMIN_CONNECTION is present, those URLs
determine the complete list of BackendImpls that will  report
themselves as available, and overrides the usually fixed
“opportunistic” URLs.  With this function, the list of database
backends as well as their full connectivity information can be
determined at runtime.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="provisioning"&gt;
&lt;h3&gt;Provisioning&lt;/h3&gt;
&lt;p&gt;The provision module will call upon Backend in order to produce a
“provisioning” system that works at three levels: database, schema,
and transaction.   The management of these three levels of resource will
be maintained over the span of any number of tests.&lt;/p&gt;
&lt;p&gt;A “database” will typically be maintained on a per-backend basis over
the span of all tests run within a single Python process.   By ensuring
that an anonymous database is created per process for a given backend,
the test suite can be safely run in parallel with no danger of concurrent
tests colliding with each other.  The current approach is that this database
is created and dropped per-test; allowing the same database to persist across
all tests in a run will reduce load and complexity.&lt;/p&gt;
&lt;p&gt;A “schema” consists of a set of tables and other schema constructs that
are created within a database.  The vast majority of OpenStack applications
run their tests within a single schema corresponding to their models.
Most of these tests only need to exercise data manipulation within these
schemas; a second class of test, the “migration” test, is less common and
requires that it actually create and drop components of these schemas.&lt;/p&gt;
&lt;p&gt;To support tests that exercise data manipulation within a fixed schema,
the provisioning system will call upon an app-specific “create schema” hook
when a newly created database is about to be used, within the scope of a
so-called “schema scope”.  This schema will then remain in place as long
as additional tests which also specify the same scope continue to be
invoked.  A “schema scope” is a string symbolic name
that any number of tests can refer to, to state that they all run within
the same schema.  For example, if four different test suites in Nova all
stated that their “SCHEMA_SCOPE” is “nova-cells”, and these suites all referred
to a “create schema” function that generated the nova model, the
“create schema” function would be invoked just once, and then all four test
suites would be run fully against the target database.   The cleanup of data
changes made by these tests is achieved using transaction rollbacks, rather
than by dropping the whole database.&lt;/p&gt;
&lt;p&gt;To support tests that are testing schema migrations and wish to create and
drop their own schema elements, those tests specify a “SCHEMA_SCOPE” of None;
the provisioning system will provide to these tests an empty database, and
upon release of the provision, a DROP will be performed for any schema objects
that still remain.&lt;/p&gt;
&lt;p&gt;A “transaction” is an optional unit that is built up and torn down on a
per-test basis.   This feature is used when the test base specifies that
it wishes to have “transactional” support, which is implied when a non-None
“SCHEMA_SCOPE” is specified.  This feature makes use of SQLAlchemy’s
Engine and Connection system in order to produce a mock “transaction”
environment transparently provided to the test.  Within this environment,
any calls to “commit” the transaction don’t actually commit for real.
Tests are given the ability to emit rollbacks that work by also wrapping
the environment within a SAVEPOINT.  This is based on a technique that
is commonly used with SQLAlchemy and is presented in various forms within
the documentation as well as in talks; in this case, the technique will be
enhanced to work not just at the ORM level but at the Core level as well,
so that even applications that use the Core directly can participate in
the transactionalized environment.&lt;/p&gt;
&lt;p&gt;The SQLite backend has long had issues with SAVEPOINT, however in support
of this feature, the backend is repaired in oslo.db using recent
hooks; see &lt;a class="reference external" href="https://review.openstack.org/#/c/113152/"&gt;https://review.openstack.org/#/c/113152/&lt;/a&gt; for the review.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="fixture-integration"&gt;
&lt;h3&gt;Fixture Integration&lt;/h3&gt;
&lt;p&gt;The provisioning system will be integrated into the test suite by taking
advantage of the &lt;a class="reference external" href="https://pypi.org/project/testresources"&gt;testresources&lt;/a&gt;
library, which provides a system of
allocating resources that may last across the span of multiple tests.
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;testresources&lt;/span&gt;&lt;/code&gt; works by maintaining the state of various resources
within a dependency tree, that is tracked as many tests proceed.   Only
when a given resource reports itself as “dirty” is it torn down
for the next test, and the final teardown only occurs once that resource
is no longer needed.&lt;/p&gt;
&lt;p&gt;Tests that use testresources by default will function normally, however
the resources that they require will be fully created and dropped on a
per-test basis, unless additional steps are taken which are specific
to the testtools package.  The tests therefore
will remain compatible with any style of test runner, however the optimization
or resources require the use of the testr or testtools runner, or with
some extra work, the standard Python unittest runner.&lt;/p&gt;
&lt;p&gt;In order to optimise resources among multiple tests, the tests must
be assembled into the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;OptimisingTestSuite&lt;/span&gt;&lt;/code&gt; object provided by
testresources.  Integration of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;OptimisingTestSuite&lt;/span&gt;&lt;/code&gt; typically
requires that the unittest-supported
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;load_tests()&lt;/span&gt;&lt;/code&gt; directive be stated either within an individual test module,
or at the package level (e.g. &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;__init__.py&lt;/span&gt;&lt;/code&gt;), which will replace the usual
system of test discovery with one which assembles the tests into a master
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;OptimisingTestSuite&lt;/span&gt;&lt;/code&gt;.    It is assumed that we will be able to provide
a single oslo.db directive that can be dropped into the top-level
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;__init__.py&lt;/span&gt;&lt;/code&gt; file of a test suite as a whole in order to provide this
effect.&lt;/p&gt;
&lt;p&gt;In order to integrate with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;testresources&lt;/span&gt;&lt;/code&gt;, the concepts of “database”,
“schema”, and “transaction” will be implemented as individual test resource
object types.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="scenarios"&gt;
&lt;h3&gt;Scenarios&lt;/h3&gt;
&lt;p&gt;Scenarios refers to the use of a tool like  &lt;a class="reference external" href="https://pypi.org/project/testscenarios/"&gt;testscenarios&lt;/a&gt;, so that individual
tests can be run multiple times against different backends.  The
existing Opportunistic fixture system will be enhanced such that the
“DRIVER” attribute, which refers right now to a single type of
database backend, can refer to a set of types.  Each test will then be
run against those drivers that are deemed to be available by the
Backend system.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="usage-within-actual-tests"&gt;
&lt;h3&gt;Usage within Actual Tests&lt;/h3&gt;
&lt;p&gt;Real world tests take advantage of the system by using
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo.db.sqlalchemy.DbTestCase&lt;/span&gt;&lt;/code&gt;.   This test case superclass acts much
like it always has, providing &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;self.session&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;self.engine&lt;/span&gt;&lt;/code&gt; members to
use for database connectivity.   However, the class can now mark via
class-level annotations which databases it is appropriate towards, and what
schema.  For example, Nova can suggest a test suite against the Nova schema
and to run against SQLite, Postgresql, and MySQL 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="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SomeNovatest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DbTestCase&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;

    &lt;span class="n"&gt;SCHEMA_SCOPE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"nova-cells"&lt;/span&gt;
    &lt;span class="n"&gt;DRIVER&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'sqlite'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'postgresql'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'mysql'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;generate_schema&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;engine&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="sd"&gt;"""Generate schema objects to be used within a test."""&lt;/span&gt;

        &lt;span class="n"&gt;nova&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;create_all_tables&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;engine&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_something&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="c1"&gt;# do an actual test&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The above class specifies how schemas are to be generated within the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;generate_schema()&lt;/span&gt;&lt;/code&gt; method, which is called upon by the provisioning system
to produce a schema corresponding to the “nova-cells” schema scope.
As many test suites may use the same &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;generate_schema()&lt;/span&gt;&lt;/code&gt; method, it is
probably best to link &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;generate_schema()&lt;/span&gt;&lt;/code&gt; with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;SCHEMA_SCOPE="nova-cells"&lt;/span&gt;&lt;/code&gt;
on a common mixin.&lt;/p&gt;
&lt;p&gt;In order to integrate with testresources, the above set of directives will
be used to compute the full set of test resource manager objects to
be delivered via the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;.resources&lt;/span&gt;&lt;/code&gt; hook; this is an attribute that’s bound
to the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;DbTestCase&lt;/span&gt;&lt;/code&gt; class itself which testresources looks for in order
to determine what kinds of resource objects are needed for the specific test.
The implementation uses a Python descriptor for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;.resources&lt;/span&gt;&lt;/code&gt; so that its
value is dynamically determined on a per-test basis.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;The decision to use testresources is made against two other variants
that don’t use it.  All three variants are discussed here.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The testresources library provides a means of spanning resources across
tests that integrates with the mechanics of the standard Python
unittest.TestSuite object, as well as the load_tests() hook which is used
to estalibish TestSuite objects into a single OptimisingTestSuite.
These mechanics are not fully or at all available in other commonly used
test runners, including nose and py.test.&lt;/p&gt;
&lt;p&gt;Advantages to testresources include that it is the standard system that
goes along with the other use of testtools, and provides a sophisticated
system of organizing tests to make the best use of resources declared by
each.   It’s test manager API sets up a clear system of declaration and
dependency between the various types of resource proposed in the
provisioning system.&lt;/p&gt;
&lt;p&gt;Disadvantages are that the optimising behavior is only available
with a testtools-style run, or with a unittest-style run if additional
steps are taken to integrate OptimisingTestSuite, as unittest itself
does not appear to honor a package-level load_tests() hook.&lt;/p&gt;
&lt;p&gt;Still to be resolved are some remaining issues with the load_tests() hook
as implemented in the top-level &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;__init__.py&lt;/span&gt;&lt;/code&gt; file when the “start”
directory is that directory itself; it seems that the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;load_tests()&lt;/span&gt;&lt;/code&gt;
hook is skipped in this case, and may require that oslo.db’s own tests
are reorganized such that all tests can be loaded from named packages.
However note that this issue is not a blocker; the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;load_tests()&lt;/span&gt;&lt;/code&gt; hook
works fine as placed within specific test modules or within &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;__init__.py&lt;/span&gt;&lt;/code&gt;
files that are loaded as packages, which is the case for the vast majority
of openstack tests suites.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Maintain awareness of test suite start/end per process using the Testr
“instance provision” hooks.   These hooks allow a set of fixed database
names to be generated before tests run, to provide this name to the
provisioning system within each subprocess, and finally after all
test suites are finished, to emit a DROP for each database name on all
available backends.   The system can create databases lazily and only
drop those which actually got created.&lt;/p&gt;
&lt;p&gt;The configuration looks like this:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;instance_provision=${PYTHON:-python} -m oslo.db.sqlalchemy.provision echo $INSTANCE_COUNT
instance_execute=OSLO_SCHEMA_TOKEN=$INSTANCE_ID $COMMAND
instance_dispose=${PYTHON:-python} -m oslo.db.sqlalchemy.provision drop --conditional $INSTANCE_IDS
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The “instance provision” hook does not actually create any databases; only
string names of databases that will be used if a database of a particular
backend is requested during the test run.  The “instance dispose” hook
then delivers these names to the “drop” command, which will drop the
named database on all possible backends if it is shown to exist; else the
name is skipped.&lt;/p&gt;
&lt;p&gt;This system runs mostly as efficiently as the testresources system,
and still degrades gracefully when using other test runners.&lt;/p&gt;
&lt;p&gt;The advantage to this system is that it is independent of the mechanics
of unittest, and has only very simplistic hooks within testr which can
easily be made to work with other test runners as well.  It also does not
require any package- or module-level load_tests() hooks and does not involve
any changes to the ordering of tests.&lt;/p&gt;
&lt;p&gt;Disadvantages include that it is more of a “homegrown” approach that
reinvents a lot of what testresources already does.   It may be more
advantageous to look into enhancing testresources itself to be more
easily integrated with other kinds of test runners.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Maintain awareness of test suite start/end process by ensuring that the
suite always runs within a special shell script that essentially runs
the same commands and environmental settings as the testr hook.&lt;/p&gt;
&lt;p&gt;This system is similar to that of using testr hooks, and both systems
can coexist.&lt;/p&gt;
&lt;p&gt;The disadvantages include not just those of the testr approach but also
that shell scripts are complicated and ad-hoc, so in that sense there’s
even more code being reinvented here.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="impact-on-existing-apis"&gt;
&lt;h3&gt;Impact on Existing APIs&lt;/h3&gt;
&lt;p&gt;Test suites which wish to take advantage of this system will need to base
themselves on the new mechanics of DbTestCase, and to rework any existing
systems they have of setting up connections or schemas to work within
the new system.   They will also need some kind of module- or package-level
load_tests() directive in order to load up the OptimisingTestSuite system.&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="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;A key deliverable of this blueprint is to significantly improve performance
for test suites that wish to run many tests against a common schema on
heterogeneous database backends.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="configuration-impact"&gt;
&lt;h3&gt;Configuration Impact&lt;/h3&gt;
&lt;p&gt;The configuration of the test runner may be impacted based on integration
approach.   The changes should be deliverable to gate runs without any
direct changes to gates.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer Impact&lt;/h3&gt;
&lt;p&gt;Developers should be aware of the DbTestCase base fixture, its
implications, and will want to use it for tests that work against
the database in a serious way.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing-impact"&gt;
&lt;h3&gt;Testing Impact&lt;/h3&gt;
&lt;p&gt;The individual components of the system will have their own tests
within oslo.db, to ensure database setup/teardown as well as to ensure
that the transactional container works as expected.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="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;Mike Bayer has already prototyped everything except scenario support,
based on the use of testresources.&lt;/p&gt;
&lt;p&gt;Robert Collins is also contributing towards issues observed in ensuring
that testtools loads up all Python packages as packages, so that the
load_tests() hook runs in all cases.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="milestones"&gt;
&lt;h3&gt;Milestones&lt;/h3&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Build out provisioning system and backend system.   This is already
complete including the integration with testresources.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;build out the test scenarios integration - still a TODO&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;implement the means by which load_tests() will be integrated, this is
complete.&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="incubation"&gt;
&lt;h2&gt;Incubation&lt;/h2&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;section id="adoption"&gt;
&lt;h3&gt;Adoption&lt;/h3&gt;
&lt;p&gt;Nova, Neutron and Keystone might be good starts.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="library"&gt;
&lt;h3&gt;Library&lt;/h3&gt;
&lt;p&gt;oslo.db&lt;/p&gt;
&lt;/section&gt;
&lt;section id="anticipated-api-stabilization"&gt;
&lt;h3&gt;Anticipated API Stabilization&lt;/h3&gt;
&lt;p&gt;unknown&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Docstrings regarding DbTestCase.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;Testresources and testscenarios.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;Original bug: &lt;a class="reference external" href="https://bugs.launchpad.net/oslo/+bug/1339206"&gt;https://bugs.launchpad.net/oslo/+bug/1339206&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Current prototypes: &lt;a class="reference external" href="https://review.openstack.org/#/q/status:open+project:openstack/oslo.db+branch:master+topic:bug/1339206,n,z"&gt;https://review.openstack.org/#/q/status:open+project:openstack/oslo.db+branch:master+topic:bug/1339206,n,z&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 work is licensed under a Creative Commons Attribution 3.0
Unported License.
&lt;a class="reference external" href="http://creativecommons.org/licenses/by/3.0/legalcode"&gt;http://creativecommons.org/licenses/by/3.0/legalcode&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
</description><pubDate>Sun, 13 May 2018 00:00:00 </pubDate></item><item><title>Adding Kafka Driver for Notification Usage in oslo_messaging</title><link>https://specs.openstack.org/openstack/oslo-specs/specs/liberty/adding-kafka-support.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/oslo.messaging/+spec/adding-kafka-support"&gt;https://blueprints.launchpad.net/oslo.messaging/+spec/adding-kafka-support&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Apache Kafka is messaging broker which enables to establish nice log-centric communication bus in OpenStack.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Some OpenStack services like Ceilometer and Monasca have the collaboration part with
Apache Kafka, distributed messaging system, to publish and subscribe logs and metrics
data. Since Kafka is well-designed log-centric messaging broker, it will be expected
to appear the new Kafka related implementation in existing or future OpenStack projects.
This blueprint aims to implement kafka driver in oslo_messaging, which enable us to
reduce the wasting time to re-implement the same functionality, and since Kafka would
have multiple clients from separate projects, to use the same client to communicate
with Kafka will make the reduce of the implementation-dependent bugs and errors.&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 the cost of independently implementing kafka communication functionality,
let’s support for the kafka driver in oslo_messaging. Kafka driver enables us to publish
and subscribe messages similar to the other oslo_messaging drivers, but will not
support for the RPC methods since Kafka is not expected to be used as a RPC broker.
In the future, if there are some needs for Kafka RPC, it will be a new proposal.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;There are several messaging brokers currently not supported by oslo_messaging, for
example NATS, NSQ and etc. However, Kafka have already been used more than one OpenStack
projects, and also since Kafka is developed for handling high load logs, Kafka have
several features which are better for logging data. For example, Kafka queue retains the
messages for configured period of time. This means that when consumers of the queue lost
messages after subscribing, they can replay the same message. Also additional kafka brokers
and consumers are easily joined, because horizontal scaling of kafka is supported by
Zookeeper. Moreover, kafka can send the bunch of messages together, this can contribute
the performance and flexibility of messaging.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="impact-on-existing-apis"&gt;
&lt;h3&gt;Impact on Existing APIs&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;Current security support of Kafka are under implementation. Authentication of clients
and encrypting connections would be coming. More information can be found in the references.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;There would be no impact unless the kafka is selected for use.
The overall performance will depend on the server component which the broker
is setted up. The paper related to Kafka says that producers can publish about
50,000 messages/sec on the condition that message size is 200 byte and messages
are sent one by one. However, this number is affected by parameters such as
message size, the number of replication, batch size (kafka can send multiple
messages together), and environments. Roughly, RabbitMQ can publish about 10,000
messages/sec, it means kafka might not be the bottleneck of performance.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="configuration-impact"&gt;
&lt;h3&gt;Configuration 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="testing-impact"&gt;
&lt;h3&gt;Testing 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&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;&amp;lt;kshimamu&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;&amp;lt;yudupi&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;dedutta&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="milestones"&gt;
&lt;h3&gt;Milestones&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Target Milestone for completion:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;liberty&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;Integration test environment for Kafka driver
- Add the codes for integration test to OpenStack infrastructure&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Making Kafka driver for oslo_messaging
- Provide the communication path with Kafka&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Documentation for Kafka driver
- Change OpenStack developer documentation&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="incubation"&gt;
&lt;h2&gt;Incubation&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;section id="adoption"&gt;
&lt;h3&gt;Adoption&lt;/h3&gt;
&lt;p&gt;Currently Ceilometer and Monasca are using Kafka service. Ceilomter project have
Kafka publisher as a metrics publisher, and Monasca project is using kafka as
a part of their architecture. For more detail, see the References chapter.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="library"&gt;
&lt;h3&gt;Library&lt;/h3&gt;
&lt;p&gt;oslo_messaging&lt;/p&gt;
&lt;/section&gt;
&lt;section id="anticipated-api-stabilization"&gt;
&lt;h3&gt;Anticipated API Stabilization&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;OpenStack developer documentation for oslo_messaging library will have the
description for the behaviors and how to select kafka driver plugin.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;Kafka python package&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://pypi.org/project/kafka-python"&gt;https://pypi.org/project/kafka-python&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;Apache Kafka Project&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="http://kafka.apache.org/"&gt;http://kafka.apache.org/&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Kafka: a Distributed Messaging System for Log Processing&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="http://research.microsoft.com/en-us/um/people/srikanth/netdb11/netdb11papers/netdb11-final12.pdf"&gt;http://research.microsoft.com/en-us/um/people/srikanth/netdb11/netdb11papers/netdb11-final12.pdf&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Kafka Security&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://cwiki.apache.org/confluence/display/KAFKA/Security"&gt;https://cwiki.apache.org/confluence/display/KAFKA/Security&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;KAFKA 0.8 PRODUCER PERFORMANCE&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="http://blog.liveramp.com/2013/04/08/kafka-0-8-producer-performance-2/"&gt;http://blog.liveramp.com/2013/04/08/kafka-0-8-producer-performance-2/&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Performance of Kafka&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="http://kafka.apache.org/07/performance.html"&gt;http://kafka.apache.org/07/performance.html&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;RabbitMQ Performance Benchmarks&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="http://blogs.vmware.com/vfabric/2013/04/how-fast-is-a-rabbit-basic-rabbitmq-performance-benchmarks.html"&gt;http://blogs.vmware.com/vfabric/2013/04/how-fast-is-a-rabbit-basic-rabbitmq-performance-benchmarks.html&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Comparison of Messaging Queues&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="http://www.bravenewgeek.com/dissecting-message-queues/"&gt;http://www.bravenewgeek.com/dissecting-message-queues/&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This work is licensed under a Creative Commons Attribution 3.0
Unported License.
&lt;a class="reference external" href="http://creativecommons.org/licenses/by/3.0/legalcode"&gt;http://creativecommons.org/licenses/by/3.0/legalcode&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
</description><pubDate>Sun, 13 May 2018 00:00:00 </pubDate></item><item><title>Adopting futurist</title><link>https://specs.openstack.org/openstack/oslo-specs/specs/liberty/adopt-futurist.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/oslo.utils/+spec/adopt-futurist"&gt;https://blueprints.launchpad.net/oslo.utils/+spec/adopt-futurist&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The goal of this library would be to provide a well documented
&lt;a class="reference external" href="https://docs.python.org/dev/library/concurrent.futures.html"&gt;futures&lt;/a&gt; classes/utilities/additions that start of with the a basic set
and can expand into a larger set as time goes on. This library (and the
futures library/module in general) allows for providing a level of
transparency in how asynchronous work gets executed.&lt;/p&gt;
&lt;p&gt;This library currently adds on the following (going above and beyond
the built-in futures library in python 3.2 or newer and
the &lt;a class="reference external" href="https://pypi.org/project/futures"&gt;futures backport&lt;/a&gt; that is commonly used on python 2.6 or 2.7).&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Statistics gathering (number of futures ran, average failure rate, average
run time…)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;An eventlet executor (aka a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;GreenThreadPoolExecutor&lt;/span&gt;&lt;/code&gt;) that uses a
&lt;a class="reference external" href="http://eventlet.net/"&gt;eventlet&lt;/a&gt; greenpool and greenthreads (making the same futures/executor
interface work when running in an eventlet environment). This kind of
addition makes it eas(ier) to move from eventlet to another style of
executor (since the interface that is provided/used is the same as the
other executor types).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A synchronous executor (aka a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;SynchronousExecutor&lt;/span&gt;&lt;/code&gt;) that does &lt;strong&gt;not&lt;/strong&gt;
using any pools, threads, or processes but executes the submitted function
in the calling thread (or program) and returns a future with the result or
exception set. This allows for blocking usage where for whatever reason the
same executor/futures interface is desired but executing in
threads, processes (or other) is &lt;strong&gt;not&lt;/strong&gt; desired.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Some of the current/planned usages for it (that are being actively pursued):&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Internal usage in &lt;a class="reference external" href="http://docs.openstack.org/developer/taskflow/"&gt;taskflow&lt;/a&gt; (when no executor object is provided
by a user). Also used for &lt;em&gt;internal&lt;/em&gt; retry activation (that itself uses a
synchronous executor).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Internal usage in &lt;a class="reference external" href="https://pypi.org/project/oslo.messaging"&gt;oslo.messaging&lt;/a&gt; (replacing/augmenting/unifying the
executor interface inside that codebase).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The code for this library was/has been extracted from &lt;a class="reference external" href="http://docs.openstack.org/developer/taskflow/"&gt;taskflow&lt;/a&gt; and is
desired to be used by &lt;a class="reference external" href="https://pypi.org/project/oslo.messaging"&gt;oslo.messaging&lt;/a&gt; (and hopefully others)?&lt;/p&gt;
&lt;section id="library-name"&gt;
&lt;h2&gt;Library Name&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;futurist&lt;/em&gt;&lt;/p&gt;
&lt;/section&gt;
&lt;section id="contents"&gt;
&lt;h2&gt;Contents&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;futurist/__init__.py&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;futurist/futures.py&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;futurist/utils.py&lt;/span&gt;&lt;/code&gt; (internal usage only)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="early-adopters"&gt;
&lt;h2&gt;Early Adopters&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Taskflow&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Oslo.messaging&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Others?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="public-api"&gt;
&lt;h2&gt;Public API&lt;/h2&gt;
&lt;p&gt;Currently the &lt;em&gt;public&lt;/em&gt; API (in pseudo-code) is the following:&lt;/p&gt;
&lt;p&gt;Actual code can be found &lt;a class="reference external" href="https://github.com/harlowja/futurist"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;concurrent&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;futures&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;_futures&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;concurrent.futures&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;process&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;_process&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;concurrent.futures&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;thread&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;_thread&lt;/span&gt;

&lt;span class="n"&gt;ThreadPoolExecutor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_thread&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ThreadPoolExecutor&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="sd"&gt;"""&lt;/span&gt;
&lt;span class="sd"&gt;    Executor that uses a thread pool to execute calls asynchronously.&lt;/span&gt;
&lt;span class="sd"&gt;    It gathers statistics about the submissions executed for&lt;/span&gt;
&lt;span class="sd"&gt;    post-analysis...&lt;/span&gt;

&lt;span class="sd"&gt;    See: https://docs.python.org/dev/library/concurrent.futures.html&lt;/span&gt;
&lt;span class="sd"&gt;    """&lt;/span&gt;
    &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;statistics&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;only&lt;/span&gt; &lt;span class="nb"&gt;property&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;alive&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;only&lt;/span&gt; &lt;span class="nb"&gt;property&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;submit&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;same&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;parent&lt;/span&gt; &lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;shutdown&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;same&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;parent&lt;/span&gt; &lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;ProcessPoolExecutor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_process&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ProcessPoolExecutor&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="sd"&gt;"""&lt;/span&gt;
&lt;span class="sd"&gt;    Executor that uses a process pool to execute calls asynchronously.&lt;/span&gt;
&lt;span class="sd"&gt;    It gathers statistics about the submissions executed for&lt;/span&gt;
&lt;span class="sd"&gt;    post-analysis...&lt;/span&gt;

&lt;span class="sd"&gt;    See: https://docs.python.org/dev/library/concurrent.futures.html&lt;/span&gt;
&lt;span class="sd"&gt;    """&lt;/span&gt;
    &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;statistics&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;only&lt;/span&gt; &lt;span class="nb"&gt;property&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;alive&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;only&lt;/span&gt; &lt;span class="nb"&gt;property&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;submit&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;same&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;parent&lt;/span&gt; &lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;shutdown&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;same&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;parent&lt;/span&gt; &lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;SynchronousExecutor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_futures&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Executor&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="sd"&gt;"""Executor that uses the caller to execute calls synchronously.&lt;/span&gt;
&lt;span class="sd"&gt;    This provides an interface to a caller that looks like an executor but&lt;/span&gt;
&lt;span class="sd"&gt;    will execute the calls inside the caller thread instead of executing it&lt;/span&gt;
&lt;span class="sd"&gt;    in a external process/thread for when this type of functionality is&lt;/span&gt;
&lt;span class="sd"&gt;    useful to provide... It gathers statistics about the submissions&lt;/span&gt;
&lt;span class="sd"&gt;    executed for post-analysis...&lt;/span&gt;
&lt;span class="sd"&gt;    """&lt;/span&gt;
    &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;statistics&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;only&lt;/span&gt; &lt;span class="nb"&gt;property&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;alive&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;only&lt;/span&gt; &lt;span class="nb"&gt;property&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;submit&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;same&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;parent&lt;/span&gt; &lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;restart&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Restarts&lt;/span&gt; &lt;span class="n"&gt;this&lt;/span&gt; &lt;span class="n"&gt;executor&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;iff&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;shutoff&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;shutdown&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;shutdown&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;same&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;parent&lt;/span&gt; &lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;GreenFuture&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Future&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="sd"&gt;"""Future that ensures internal condition is a green(ed) condition."""&lt;/span&gt;

&lt;span class="n"&gt;GreenThreadPoolExecutor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_futures&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Executor&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="sd"&gt;"""Executor that uses a green thread pool to execute calls&lt;/span&gt;
&lt;span class="sd"&gt;    asynchronously.&lt;/span&gt;

&lt;span class="sd"&gt;    See: https://docs.python.org/dev/library/concurrent.futures.html&lt;/span&gt;
&lt;span class="sd"&gt;    and http://eventlet.net/doc/modules/greenpool.html for information on&lt;/span&gt;
&lt;span class="sd"&gt;    how this works.&lt;/span&gt;

&lt;span class="sd"&gt;    It gathers statistics about the submissions executed for&lt;/span&gt;
&lt;span class="sd"&gt;    post-analysis...&lt;/span&gt;
&lt;span class="sd"&gt;    """&lt;/span&gt;
    &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;statistics&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;only&lt;/span&gt; &lt;span class="nb"&gt;property&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;alive&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;only&lt;/span&gt; &lt;span class="nb"&gt;property&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;submit&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;same&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;parent&lt;/span&gt; &lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;shutdown&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;same&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;parent&lt;/span&gt; &lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;ExecutorStatistics&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;object&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="sd"&gt;"""Holds *immutable* information about a executors executions."""&lt;/span&gt;
    &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;failures&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;only&lt;/span&gt; &lt;span class="nb"&gt;property&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;executed&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;only&lt;/span&gt; &lt;span class="nb"&gt;property&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;runtime&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;only&lt;/span&gt; &lt;span class="nb"&gt;property&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;cancelled&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;only&lt;/span&gt; &lt;span class="nb"&gt;property&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;average_runtime&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;only&lt;/span&gt; &lt;span class="nb"&gt;property&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="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;Harlowja&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;Sileht&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="primary-maintainer"&gt;
&lt;h3&gt;Primary maintainer&lt;/h3&gt;
&lt;p&gt;Primary maintainer:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Harlowja&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;Sileht&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="security-contact"&gt;
&lt;h3&gt;Security Contact&lt;/h3&gt;
&lt;p&gt;Security Contact: harlowja&lt;/p&gt;
&lt;/section&gt;
&lt;section id="milestones"&gt;
&lt;h3&gt;Milestones&lt;/h3&gt;
&lt;p&gt;Target Milestone for completion: liberty-1&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 launchpad project&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Change owner of Launchpad project (make it part of the Oslo project group)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Give openstackci Owner permissions on PyPI&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create Initial Repository&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Make the library do something ✓&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update the README.rst&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Publish git repo&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Oslo team review new repository&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Infra project configuration&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update Gerrit Groups and ACLs&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;openstack-infra/devstack-gate adjustments&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;openstack/requirements projects.txt adjustments&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update project list on docs.openstack.org&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Tag a release&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Profit!&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="adoption-notes"&gt;
&lt;h2&gt;Adoption Notes&lt;/h2&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;section id="requirements"&gt;
&lt;h3&gt;Requirements&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;python 2.6 –&amp;gt; 3.4 (and beyond!)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://pypi.org/project/futures"&gt;futures backport&lt;/a&gt; (only needed on python &amp;lt; 3.2)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="http://docs.openstack.org/developer/pbr/"&gt;pbr&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/oslo.utils"&gt;oslo.utils&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/six"&gt;six&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="http://eventlet.net/"&gt;eventlet&lt;/a&gt; (&lt;strong&gt;optionally&lt;/strong&gt; required for green futures/executors)&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;All of the currently planned dependencies are in the requirements repository.&lt;/p&gt;
&lt;/div&gt;
&lt;/section&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;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This work is licensed under a Creative Commons Attribution 3.0
Unported License.
&lt;a class="reference external" href="http://creativecommons.org/licenses/by/3.0/legalcode"&gt;http://creativecommons.org/licenses/by/3.0/legalcode&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
</description><pubDate>Sun, 13 May 2018 00:00:00 </pubDate></item><item><title>Unifying and cleaning up failure remoting</title><link>https://specs.openstack.org/openstack/oslo-specs/specs/ocata/failure-remoting.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/oslo.messaging/+spec/failure-remoting"&gt;https://blueprints.launchpad.net/oslo.messaging/+spec/failure-remoting&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;We currently have a couple ways of remoting failures (exceptions +
traceback information) that occur on remote systems back to their
source. These different ways have differences that make each solution
valid and applicable to its problem area. To encourage unification, this
spec will work on a proposal that can take the best aspects of both
implementations and leave the weaknesses of both behind to make a
best of breed implementation.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;There is a repeated desire to be able to serialize an exception, an
exception type, and as much information about the exceptions cause (ie
its traceback) when a creator on a remote system fails to some
other system (typically transmitted over some RPC or REST or other
non-local interface). For brevity sake let us call the tuple
of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;(exception_type,&lt;/span&gt; &lt;span class="pre"&gt;value,&lt;/span&gt; &lt;span class="pre"&gt;traceback)&lt;/span&gt;&lt;/code&gt; (typically created from some
call to &lt;a class="reference external" href="https://docs.python.org/2/library/sys.html#sys.exc_info"&gt;sys.exc_info&lt;/a&gt;) a &lt;strong&gt;failure&lt;/strong&gt; object. When on a local machine
and the failure is created inside its own process the exception, its class
and its traceback are natively supported and can be examined, output,
logged (typically using the &lt;a class="reference external" href="https://docs.python.org/2/library/traceback.html"&gt;traceback&lt;/a&gt; module), handled (via &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;try/catch&lt;/span&gt;&lt;/code&gt;
blocks) and analyzed; but when that exception is remotely created and
sent to a receiver the recreation of that failure becomes that much more
complicated for a few reasons:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Serialization of a traceback object (which typically contains references
to local stack frames) into some serializable format typically means that
the reconstructed traceback will not be as &lt;em&gt;rich&lt;/em&gt; as it was when created
on the local process due to the fact that those local stack frames
will &lt;em&gt;not&lt;/em&gt; exist in the receivers process. This implies that traceback
serialization/deserialization is a lossy process and by side-effect
this means that for remote exceptions the &lt;a class="reference external" href="https://docs.python.org/2/library/traceback.html"&gt;traceback&lt;/a&gt; module
can &lt;em&gt;not&lt;/em&gt; be used and/or that the information it produces may
not be accurate.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Input validation must now be performed, ensuring that the serialized format
created by the sender is actually valid (this excludes using &lt;a class="reference external" href="https://docs.python.org/2/library/pickle.html"&gt;pickle&lt;/a&gt;
for serialization/deserialization due to its widely known security
vulnerabilities).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The receiver of the failure, if it desires to &lt;em&gt;try&lt;/em&gt; to recreate an
exception object from the serialized version &lt;strong&gt;must&lt;/strong&gt; have access to the
same exception type/class that was used to create the original
exception; this may not always be possible (depending on modules and classes
accessible from the receivers &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;sys.path&lt;/span&gt;&lt;/code&gt;).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Any contained exception value (typically a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;string&lt;/span&gt;&lt;/code&gt;, but not limited to)
will need to be reconstructed (this may not always be possible, for
example if the originating exception value references some local file
handle or other non-serializable object, such as a local threading lock).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="what-exists"&gt;
&lt;h2&gt;What exists&lt;/h2&gt;
&lt;p&gt;There are a few known implementations of failure capturing, serialization
and deserialization/reconstruction. Let us dive into how each one works and
analyze the benefits and drawbacks of each approach.&lt;/p&gt;
&lt;section id="oslo-privsep"&gt;
&lt;h3&gt;Oslo.privsep&lt;/h3&gt;
&lt;p&gt;Source:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://github.com/openstack/oslo.privsep/blob/1.13.0/oslo_privsep/daemon.py#L181-L187"&gt;https://github.com/openstack/oslo.privsep/blob/1.13.0/oslo_privsep/daemon.py#L181-L187&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/oslo.privsep/blob/1.13.0/oslo_privsep/daemon.py#L181-L187"&gt;https://github.com/openstack/oslo.privsep/blob/1.13.0/oslo_privsep/daemon.py#L181-L187&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;section id="commentary"&gt;
&lt;h4&gt;Commentary&lt;/h4&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Sends back class + module name across socket channel + exception arguments.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Drops traceback (logs it on priviliged side).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Recreates new class object with sent across arguments (and reraises)
on unpriviliged side (ideally nothing leaks across?).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="oslo-messaging"&gt;
&lt;h3&gt;Oslo.messaging&lt;/h3&gt;
&lt;p&gt;Source:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://github.com/openstack/oslo.messaging/blob/2.5.0/oslo_messaging/_drivers/common.py#L164"&gt;https://github.com/openstack/oslo.messaging/blob/2.5.0/oslo_messaging/_drivers/common.py#L164&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/oslo.messaging/blob/2.5.0/oslo_messaging/_drivers/common.py#L204"&gt;https://github.com/openstack/oslo.messaging/blob/2.5.0/oslo_messaging/_drivers/common.py#L204&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A similar (same?) copy seems to be in nova (for cells?):&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://github.com/openstack/nova/blob/stable/liberty/nova/cells/messaging.py#L1878"&gt;https://github.com/openstack/nova/blob/stable/liberty/nova/cells/messaging.py#L1878&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://github.com/openstack/nova/blob/stable/liberty/nova/cells/messaging.py#L1918"&gt;https://github.com/openstack/nova/blob/stable/liberty/nova/cells/messaging.py#L1918&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Docs: unknown&lt;/p&gt;
&lt;section id="id1"&gt;
&lt;h4&gt;Commentary&lt;/h4&gt;
&lt;p&gt;Serializes: yes (to json); keyword arguments of exception are extracted
from optional exception attribute &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;kwargs&lt;/span&gt;&lt;/code&gt;, class name and module name
of exception are captured with final data format being:&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;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s1"&gt;'class'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;cls_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'module'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;mod_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'message'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;six&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text_type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;exception&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="s1"&gt;'tb'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;tb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'args'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;exception&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'kwargs'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;kwargs&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Deserializes: yes; previous json data is loaded as a dictionary.&lt;/p&gt;
&lt;p&gt;Validates: No; &lt;a class="reference external" href="http://json-schema.org/"&gt;jsonschema&lt;/a&gt; validation is not currently performed.&lt;/p&gt;
&lt;p&gt;Reconstructs: yes (with limitations);  message of exception from
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;message&lt;/span&gt;&lt;/code&gt; in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;data&lt;/span&gt;&lt;/code&gt; is loaded and concated with traceback from &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tb&lt;/span&gt;&lt;/code&gt;
dictionary element, module received is then verified against a provided list
and if module received is not allowed a generic exception is raised which
attempts to encapsulate the received failure. This generic
exception (which does retain the traceback) is created via:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;oslo_messaging&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RemoteError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'class'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'message'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                           &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'tb'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Otherwise if the module is one of the allowed types the exception class
object is recreated by using:&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;klass&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;load&lt;/span&gt; &lt;span class="n"&gt;module&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;and&lt;/span&gt; &lt;span class="n"&gt;verify&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;is&lt;/span&gt; &lt;span class="n"&gt;an&lt;/span&gt; &lt;span class="n"&gt;exception&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="n"&gt;exception&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;klass&lt;/span&gt;&lt;span class="p"&gt;(&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;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'args'&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="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'kwargs'&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;Then if this works, to ensure the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;__str__&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;__unicode__&lt;/span&gt;&lt;/code&gt; methods
correctly return the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;message&lt;/span&gt;&lt;/code&gt; key in the previously mentioned &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;data&lt;/span&gt;&lt;/code&gt;
dictionary a dynamic exception type is created with a dynamically created
function that returns provided &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;message&lt;/span&gt;&lt;/code&gt;; then the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;exception&lt;/span&gt;&lt;/code&gt; created
above has its &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;__class__&lt;/span&gt;&lt;/code&gt; attribute replaced to be this new dynamic
exception type (woah!):&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;exc_type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;exception&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;str_override&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;
&lt;span class="n"&gt;new_ex_type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ex_type&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="vm"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;_REMOTE_POSTFIX&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ex_type&lt;/span&gt;&lt;span class="p"&gt;,),&lt;/span&gt;
                   &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;'__str__'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;str_override&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'__unicode__'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;str_override&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="n"&gt;new_ex_type&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="vm"&gt;__module__&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="si"&gt;%s%s&lt;/span&gt;&lt;span class="s1"&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;module&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_REMOTE_POSTFIX&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;exception&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="vm"&gt;__class__&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;new_ex_type&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;if this doesn’t work then &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;exception&lt;/span&gt;&lt;/code&gt; is returned
untouched and instead the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;exception.args&lt;/span&gt;&lt;/code&gt; list is replaced with a new
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;args&lt;/span&gt;&lt;/code&gt; list that has the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;message&lt;/span&gt;&lt;/code&gt; from the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;data&lt;/span&gt;&lt;/code&gt; dict as its first
entry (replacing the prior &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;args&lt;/span&gt;&lt;/code&gt; first entry with its own).&lt;/p&gt;
&lt;p&gt;Notes:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Appears to lose remote traceback info during above reconstruction
process (unless &lt;a class="reference external" href="http://docs.openstack.org/developer/ oslo.messaging/rpcclient.html#oslo_messaging.RemoteError"&gt;RemoteError&lt;/a&gt; is returned, which does not
lose the traceback, but does lose the original type + associated
information).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Does not capture &lt;a class="reference external" href="https://www.python.org/dev/peps/pep-3134/"&gt;chained&lt;/a&gt; exception information.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Copied (or some version of it) into nova cells (currently unknown what
version/sha the nova folks copied from).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="taskflow"&gt;
&lt;h3&gt;TaskFlow&lt;/h3&gt;
&lt;p&gt;Source:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://github.com/openstack/taskflow/blob/1.21.0/taskflow/types/failure.py"&gt;https://github.com/openstack/taskflow/blob/1.21.0/taskflow/types/failure.py&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Docs:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="http://docs.openstack.org/developer/taskflow/types.html#module-taskflow.types.failure"&gt;http://docs.openstack.org/developer/taskflow/types.html#module-taskflow.types.failure&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;section id="id2"&gt;
&lt;h4&gt;Commentary&lt;/h4&gt;
&lt;p&gt;Serializes: True; translates exception (or &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;sys.exc_info&lt;/span&gt;&lt;/code&gt; call) into
a dictionary using &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;to_dict&lt;/span&gt;&lt;/code&gt; method. 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="gp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;taskflow.types&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;failure&lt;/span&gt;
&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="gp"&gt;... &lt;/span&gt;   &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="ne"&gt;IOError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"I have broke"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="gp"&gt;... &lt;/span&gt;&lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="ne"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="gp"&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;failure&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Failure&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="gp"&gt;...&lt;/span&gt;
&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;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;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dumps&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;to_dict&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;indent&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sort_keys&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="go"&gt;{&lt;/span&gt;
&lt;span class="go"&gt;    "causes": [],&lt;/span&gt;
&lt;span class="go"&gt;    "exc_type_names": [&lt;/span&gt;
&lt;span class="go"&gt;        "IOError",&lt;/span&gt;
&lt;span class="go"&gt;        "EnvironmentError",&lt;/span&gt;
&lt;span class="go"&gt;        "StandardError",&lt;/span&gt;
&lt;span class="go"&gt;        "Exception"&lt;/span&gt;
&lt;span class="go"&gt;    ],&lt;/span&gt;
&lt;span class="go"&gt;    "exception_str": "I have broke",&lt;/span&gt;
&lt;span class="go"&gt;    "traceback_str": "  File \"&amp;lt;stdin&amp;gt;\", line 2, in &amp;lt;module&amp;gt;\n",&lt;/span&gt;
&lt;span class="go"&gt;    "version": 1&lt;/span&gt;
&lt;span class="go"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Deserializes: True; loads from json into dictionary.&lt;/p&gt;
&lt;p&gt;Validates: True; uses &lt;a class="reference external" href="http://json-schema.org/"&gt;jsonschema&lt;/a&gt; with 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;SCHEMA&lt;/span&gt; &lt;span class="o"&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/cause"&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;"cause"&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="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;'version'&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;"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="p"&gt;},&lt;/span&gt;
                &lt;span class="s1"&gt;'exception_str'&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="s1"&gt;'traceback_str'&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="s1"&gt;'exc_type_names'&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;"minItems"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="p"&gt;},&lt;/span&gt;
                &lt;span class="s1"&gt;'causes'&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;"$ref"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"#/definitions/cause"&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;"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;"exception_str"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s1"&gt;'traceback_str'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s1"&gt;'exc_type_names'&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="kc"&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;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Reconstructs: True when failure objects are raised locally (when serialization
is not used). False when serialized using &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;to_dict&lt;/span&gt;&lt;/code&gt;; Instead of going
through process like defined in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo.messaging&lt;/span&gt;&lt;/code&gt; above this object
instead wraps originating exception(s) in a new exception &lt;a class="reference external" href="http://docs.openstack.org/developer/ taskflow/exceptions.html#taskflow.exceptions.WrappedFailure"&gt;WrappedFailure&lt;/a&gt; and
exposes its type (string version of) information and its traceback in a
new exception and provides accessors and useful methods (defined on the
failure class) to contained information for introspection purposes.&lt;/p&gt;
&lt;p&gt;Notes:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Captures (and serializes and deserializes) &lt;a class="reference external" href="https://www.python.org/dev/peps/pep-3134/"&gt;chained&lt;/a&gt; exceptions (as
nested failure objects). Seen in above schema as &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;causes&lt;/span&gt;&lt;/code&gt; key (which
self-references the schema object).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="twisted"&gt;
&lt;h3&gt;Twisted&lt;/h3&gt;
&lt;p&gt;Source:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://github.com/twisted/twisted/blob/twisted-15.4.0/twisted/python/failure.py"&gt;https://github.com/twisted/twisted/blob/twisted-15.4.0/twisted/python/failure.py&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Docs:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="http://twistedmatrix.com/documents/current/api/twisted.python.failure.html"&gt;http://twistedmatrix.com/documents/current/api/twisted.python.failure.html&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;section id="id3"&gt;
&lt;h4&gt;Commentary&lt;/h4&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="gp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;twisted.python&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;failure&lt;/span&gt;
&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;pickle&lt;/span&gt;
&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;traceback&lt;/span&gt;
&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;blow_up&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
&lt;span class="gp"&gt;... &lt;/span&gt;   &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="ne"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"broken"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="gp"&gt;... &lt;/span&gt;   &lt;span class="n"&gt;blow_up&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="gp"&gt;... &lt;/span&gt;&lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="ne"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="gp"&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;failure&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Failure&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class="nb"&gt;print&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="go"&gt;[Failure instance: Traceback: &amp;lt;type 'exceptions.ValueError'&amp;gt;: broken&lt;/span&gt;
&lt;span class="go"&gt;--- &amp;lt;exception caught here&amp;gt; ---&lt;/span&gt;
&lt;span class="go"&gt;&amp;lt;stdin&amp;gt;:2:&amp;lt;module&amp;gt;&lt;/span&gt;
&lt;span class="go"&gt;&amp;lt;stdin&amp;gt;:2:blow_up&lt;/span&gt;
&lt;span class="go"&gt;]&lt;/span&gt;
&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;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;raiseException&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="gt"&gt;Traceback (most recent call last):&lt;/span&gt;
  File &lt;span class="nb"&gt;"&amp;lt;stdin&amp;gt;"&lt;/span&gt;, line &lt;span class="m"&gt;1&lt;/span&gt;, in &lt;span class="n"&gt;&amp;lt;module&amp;gt;&lt;/span&gt;
  File &lt;span class="nb"&gt;"&amp;lt;stdin&amp;gt;"&lt;/span&gt;, line &lt;span class="m"&gt;2&lt;/span&gt;, in &lt;span class="n"&gt;&amp;lt;module&amp;gt;&lt;/span&gt;
  File &lt;span class="nb"&gt;"&amp;lt;stdin&amp;gt;"&lt;/span&gt;, line &lt;span class="m"&gt;2&lt;/span&gt;, in &lt;span class="n"&gt;blow_up&lt;/span&gt;
&lt;span class="gr"&gt;ValueError&lt;/span&gt;: &lt;span class="n"&gt;broken&lt;/span&gt;
&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class="n"&gt;f_p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pickle&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dumps&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="gp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class="n"&gt;f_2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pickle&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f_p&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class="n"&gt;f_2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;raiseException&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="gt"&gt;Traceback (most recent call last):&lt;/span&gt;
  File &lt;span class="nb"&gt;"&amp;lt;stdin&amp;gt;"&lt;/span&gt;, line &lt;span class="m"&gt;1&lt;/span&gt;, in &lt;span class="n"&gt;&amp;lt;module&amp;gt;&lt;/span&gt;
  File &lt;span class="nb"&gt;"&amp;lt;string&amp;gt;"&lt;/span&gt;, line &lt;span class="m"&gt;2&lt;/span&gt;, in &lt;span class="n"&gt;raiseException&lt;/span&gt;
&lt;span class="gr"&gt;ValueError&lt;/span&gt;: &lt;span class="n"&gt;broken&lt;/span&gt;
&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;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;f_2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tb&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="go"&gt;None&lt;/span&gt;
&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class="n"&gt;traceback&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;print_tb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f_2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getTracebackObject&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
  File &lt;span class="nb"&gt;"&amp;lt;stdin&amp;gt;"&lt;/span&gt;, line &lt;span class="m"&gt;2&lt;/span&gt;, in &lt;span class="n"&gt;&amp;lt;module&amp;gt;&lt;/span&gt;
  File &lt;span class="nb"&gt;"&amp;lt;stdin&amp;gt;"&lt;/span&gt;, line &lt;span class="m"&gt;2&lt;/span&gt;, in &lt;span class="n"&gt;blow_up&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Serializes: &lt;a class="reference external" href="https://docs.python.org/2/library/pickle.html"&gt;pickle&lt;/a&gt; supported via &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;__getstate__&lt;/span&gt;&lt;/code&gt; method. Since
they have created a &lt;em&gt;mostly&lt;/em&gt; working replacement for the frame information
that a traceback stores it becomes possible to better integrate with
the &lt;a class="reference external" href="https://docs.python.org/2/library/traceback.html"&gt;traceback&lt;/a&gt; module (which accesses that frame information to try to
create useful traceback details).&lt;/p&gt;
&lt;p&gt;Deserializes: Yes, via &lt;a class="reference external" href="https://docs.python.org/2/library/pickle.html"&gt;pickle&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Validates: No (&lt;a class="reference external" href="https://docs.python.org/2/library/pickle.html"&gt;pickle&lt;/a&gt; is known to be vulnerable anyway to loading
arbitrary code).&lt;/p&gt;
&lt;p&gt;Reconstructs: Partially, a frame-like replica structure is created that
&lt;em&gt;mostly&lt;/em&gt; works like the original (except it can’t be re-raised, but it
can be passed to the &lt;a class="reference external" href="https://docs.python.org/2/library/traceback.html"&gt;traceback&lt;/a&gt; module to have its functions seemingly
work).&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Create a new library, &lt;a class="reference external" href="https://pypi.org/project/failure"&gt;https://pypi.org/project/failure&lt;/a&gt; (or other better
named library) that encompasses the combination of the 3-4 models described
above.&lt;/p&gt;
&lt;p&gt;It would primarily provide a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Failure&lt;/span&gt;&lt;/code&gt; object (like provided by
taskflow and twisted) as its main exposed API. That failure
class would have a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;__get_state__&lt;/span&gt;&lt;/code&gt; method so that it can be pickled (for
situations where this is desired) and a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;to_dict&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;from_dict&lt;/span&gt;&lt;/code&gt; that
can be used for json serialization and deserialization. It would also have
introspection APIs (similar to what is provided by twisted and taskflow) so
that the underlying exception information can be accessed in nice manner.&lt;/p&gt;
&lt;p&gt;Basic examples of these API(s) that would be great to have (and have
proven themselves useful):&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="nd"&gt;@classmethod&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;validate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="sd"&gt;"""Validate input data matches expected failure format."""&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;check&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;exc_classes&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="sd"&gt;"""Check if any of ``exc_classes`` caused the failure.&lt;/span&gt;

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

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

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;reraise&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="sd"&gt;"""Re-raise captured exception."""&lt;/span&gt;

&lt;span class="nd"&gt;@property&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;causes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="sd"&gt;"""Tuple of all *inner* failure *causes* of this failure.&lt;/span&gt;

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

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

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;pformat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;traceback&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="sd"&gt;"""Pretty formats the failure object into a string."""&lt;/span&gt;

&lt;span class="nd"&gt;@classmethod&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;from_dict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="sd"&gt;"""Converts this from a dictionary to a object."""&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;to_dict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="sd"&gt;"""Converts this object to a dictionary."""&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;copy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="sd"&gt;"""Copies this object."""&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;To take advantage of the re-raising capabilities in oslo.messaging this
class should also have a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;reraise&lt;/span&gt;&lt;/code&gt; method that can attempt to reraise the
given failure (if and only if it matches a given list of exception types). It
would &lt;strong&gt;not&lt;/strong&gt; attempt to dynamically create a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;__str__&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;__repr__&lt;/span&gt;&lt;/code&gt;
method (the class manipulation magic happening in oslo.messaging) to avoid
the peculiarities of this chunk of code. If the contained failure does
not match a known list of failures, then &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;reraise&lt;/span&gt;&lt;/code&gt; will return false and
it will not re-raise anything (leaving it up to the caller to decide what
to do in this situation, perhaps at this point a common  &lt;a class="reference external" href="http://docs.openstack.org/developer/ taskflow/exceptions.html#taskflow.exceptions.WrappedFailure"&gt;WrappedFailure&lt;/a&gt;
like exception should be raised?).&lt;/p&gt;
&lt;p&gt;The validation logic using &lt;a class="reference external" href="http://json-schema.org/"&gt;jsonschema&lt;/a&gt; would be taken from taskflow and
used when deserializing so that errors with &lt;em&gt;bad&lt;/em&gt; data can be found
earlier (at data load time) rather than later (at data access time).&lt;/p&gt;
&lt;p&gt;To provide the twisted like integration with the traceback module (by
turning the internal format of a traceback into a pure python object
representation) there has been discussed if the &lt;a class="reference external" href="https://pypi.org/project/traceback2/"&gt;traceback2&lt;/a&gt; module can
provide equivalent functionality, if it can then it should be used to
achieve similar integration (it would be even better if the integration
would also allow for re-raising this pure python trackback and frame
representation as an actual traceback, although this may not be a reasonable
expectation).&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Keep having multiple variations, each with their own weaknesses and
benefits, instead of unifying them under a single library.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="impact-on-existing-apis"&gt;
&lt;h3&gt;Impact on Existing APIs&lt;/h3&gt;
&lt;p&gt;Ideally none, as the users should still get the same functionality, but
if this is done correctly they will get more meaningful tracebacks, more
meaningful introspection on failure objects and overall better and more
consistent failures.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;section id="configuration-impact"&gt;
&lt;h3&gt;Configuration Impact&lt;/h3&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer Impact&lt;/h3&gt;
&lt;p&gt;This should make developers lives better.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing-impact"&gt;
&lt;h3&gt;Testing Impact&lt;/h3&gt;
&lt;p&gt;Having the failure code in its own library, allows it to be easily mocked
and tested (vs say having it deeply embedded in oslo.messaging where it is
not so easily testable/reviewable…); so overall this should improve
test coverage (and overall code quality).&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="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: harlowja&lt;/p&gt;
&lt;/section&gt;
&lt;section id="milestones"&gt;
&lt;h3&gt;Milestones&lt;/h3&gt;
&lt;p&gt;Target Milestone for completion: Mikita&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;Create skeleton library.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Get skeleton up on gerrit and integrated into oslo pipelines.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Start to move around code from oslo.messaging and taskflow
and refactor to start to form this new library; use concepts and
learning from twisted and bolt-ons (and others) to help make this
library the best it can be.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Review and code and repeat.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Release and integrate.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Delete older dead code.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Profit!&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="incubation"&gt;
&lt;h2&gt;Incubation&lt;/h2&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;N/A (all inline)&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This work is licensed under a Creative Commons Attribution 3.0
Unported License.
&lt;a class="reference external" href="http://creativecommons.org/licenses/by/3.0/legalcode"&gt;http://creativecommons.org/licenses/by/3.0/legalcode&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
</description><pubDate>Sun, 13 May 2018 00:00:00 </pubDate></item><item><title>oslo middleware healthcheck</title><link>https://specs.openstack.org/openstack/oslo-specs/specs/kilo/oslo-middleware-healthcheck.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/oslo.middleware/+spec/oslo-middleware-healthcheck"&gt;https://blueprints.launchpad.net/oslo.middleware/+spec/oslo-middleware-healthcheck&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;A generic and extendabled healthcheck middleware&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;They are no simple and common ways to ensure that an Openstack API endpoints
can handle requests.
But a deployer that use loadbalancers want to have easy way to known if a
API endpoint can handle request or not.&lt;/p&gt;
&lt;p&gt;For API endpoint that rely on a backend (like a database), checking that API
endpoint does not return a 50x errors on the root url of the endpoint is not
sufficient. An application like nova can return 200 on ‘/’ even the database
is unreachable.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;The idea is to create a wsgi middleware that all openstack components can use:&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;[filter:healthcheck]&lt;/span&gt;
&lt;span class="na"&gt;paste.filter_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:Healthcheck&lt;/span&gt;
&lt;span class="na"&gt;path&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;/healthcheck (default)&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;database,disable_by_file (optional, default: empty)&lt;/span&gt;
&lt;span class="c1"&gt;# used by the 'disable_by_file' backend&lt;/span&gt;
&lt;span class="na"&gt;disable_by_file_path&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/run/nova/healthcheck_disable (optional, default: empty)&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 extensions in the namespace “oslo.middleware.healthcheck”.&lt;/p&gt;
&lt;p&gt;oslo.middleware will also provide a base class for these extensions:&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;HealthcheckResult&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;namedtuple&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'HealthcheckResult'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'available'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'reason'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;verbose&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="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;HealthcheckBaseExtension&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;object&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;conf&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;conf&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;conf&lt;/span&gt;

    &lt;span class="nd"&gt;@abc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;abstractmethod&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;healthcheck&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="sd"&gt;"""method called by the healthcheck middleware&lt;/span&gt;

&lt;span class="sd"&gt;        return: HealthcheckResult object&lt;/span&gt;
&lt;span class="sd"&gt;        """&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyDBHealthcheck&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;HealthcheckBaseExtension&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;healthcheck&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="o"&gt;...&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;HealthcheckResult&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;available&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                 &lt;span class="n"&gt;reason&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"Fail to connect to the database"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;And so the setup.cfg will have entry_point like that:&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;[entry_points]&lt;/span&gt;
&lt;span class="na"&gt;healthcheck&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="na"&gt;database&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.db:DBHealthcheck&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="na"&gt;disable_by_file&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:DisableByFileHealthcheck&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The ‘DisableByFileHealthcheck’ extension will return if the ‘disable_by_file_path’
file is missing:&lt;/p&gt;
&lt;div class="highlight-python notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;HealthcheckResult&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;available&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;reason&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"DISABLED BY FILE"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;otherwise:&lt;/p&gt;
&lt;div class="highlight-python notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;HealthcheckResult&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;available&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;reason&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;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Also, but not part of this blueprint, oslo.db can provide a generic
implementation for database checks.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Some works on different project have already been proposed to do that but
never get merged:&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/12759/"&gt;https://review.openstack.org/#/c/12759/&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/120257/"&gt;https://review.openstack.org/#/c/120257/&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/105311/"&gt;https://review.openstack.org/#/c/105311/&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A deployer could prepare resources in their cloud and build a HTTP request to
query these resources to check that everything works, but this method is not
efficient, it need to prepare some resources, the HTTP request will have some
credentails that need to stored on the loadbalancer. So this method is a bit
heavy when we can just do a simple ‘select now();’ into a database to known if
a backend works.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="impact-on-existing-apis"&gt;
&lt;h3&gt;Impact on Existing APIs&lt;/h3&gt;
&lt;p&gt;Swift already have this kind of middleware, we must ensure we keep the same
behavior:&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://github.com/openstack/swift/blob/master/swift/common/middleware/healthcheck.py"&gt;https://github.com/openstack/swift/blob/master/swift/common/middleware/healthcheck.py&lt;/a&gt;&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;It’s recommanded to block this url or to randomize the url used for healthcheck,
because this feature it’s cleary dedicated for tools used by a deployer like load balancer.&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="configuration-impact"&gt;
&lt;h3&gt;Configuration Impact&lt;/h3&gt;
&lt;p&gt;The middleware will be configurable:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;path: url path of this middleware (default: /healthcheck)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;backends: list of stevedore extension to use&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And the DisablebyfileHealthcheck with:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;disable_by_file_path location of the file to administratively return 503 (optional)&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;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing-impact"&gt;
&lt;h3&gt;Testing Impact&lt;/h3&gt;
&lt;p&gt;Middleware will be covered by the unittest
And also have a tempest test for each services that have integrated it.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Mehdi Abaakouk (sileht)&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Julien Danjou (jdanjou)&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="milestones"&gt;
&lt;h3&gt;Milestones&lt;/h3&gt;
&lt;p&gt;Target Milestone for completion:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Kilo-1&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;Write the middleware&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update applications to use it&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="incubation"&gt;
&lt;h2&gt;Incubation&lt;/h2&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;N/A&lt;/p&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="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This work is licensed under a Creative Commons Attribution 3.0
Unported License.
&lt;a class="reference external" href="http://creativecommons.org/licenses/by/3.0/legalcode"&gt;http://creativecommons.org/licenses/by/3.0/legalcode&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
</description><pubDate>Mon, 23 Apr 2018 00:00:00 </pubDate></item><item><title>Proposed new library oslo.limit</title><link>https://specs.openstack.org/openstack/oslo-specs/specs/rocky/oslo-limit.html</link><description>

&lt;p&gt;This is a proposal to create a new library dedicated to enabling moreconsistent
quota and limit enforcement across OpenStack.&lt;/p&gt;
&lt;section id="proposed-library-mission"&gt;
&lt;h2&gt;Proposed library mission&lt;/h2&gt;
&lt;p&gt;Enforcing quotas and limits across OpenStack has traditionally been a tough
problem to solve. Determining enforcement requires quota knowledge from the
service along with information about the project owning the resource. Up until
the Queens release, quota calculation and enforcement has been left to the
services to implement, forcing them to understand complexities of keystone
project structure. During the Pike and Queens PTG, there were several
productive discussions towards redesigning the current approach to quota
enforcement.&lt;/p&gt;
&lt;p&gt;Because keystone is the authority of project structure, it makes sense to allow
keystone to hold the association between a resource limit and a project. This
means services still need to calculate quota and usage, but the problem should
be easier for services to implement since developers shouldn’t need to
re-implement possible hierarchies of projects and their associated limits.
Instead, we can offload some of that work to a common library for services to
consume that handles enforcing quota calculation based on limits associated to
projects in keystone. This proposal is to have a new library called oslo.limit
that fills that need.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="consuming-projects"&gt;
&lt;h2&gt;Consuming projects&lt;/h2&gt;
&lt;p&gt;The services consuming this work will be any service that currently implements
a quota system, or plans to implement one. Since keystone already supports
unified limits and association of limits to projects, the implementation for
consuming projects is easier. instead of having to re-write that
implementation, developers need to ensure quota calculation to passed to the
oslo.limit library somewhere in the API’s validation layer. The pattern
described here is very similar to the pattern currently used by services that
leverage oslo.policy for authorization decisions.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="alternatives-library"&gt;
&lt;h2&gt;Alternatives library&lt;/h2&gt;
&lt;p&gt;It looks like there was an existing library that attempted to solve some of
these problems, called &lt;a class="reference external" href="https://github.com/openstack/delimiter"&gt;delimiter&lt;/a&gt;.
It looks like delimiter could be used to talk to keystone about quota
enforcement, where as the existing approach with oslo.limit would be to use
keystone directly.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-adoption-model-plan"&gt;
&lt;h2&gt;Proposed adoption model/plan&lt;/h2&gt;
&lt;p&gt;The &lt;a class="reference external" href="https://docs.openstack.org/keystone/latest/admin/identity-unified-limits.html"&gt;unified limit API&lt;/a&gt;
in keystone is currently marked as experimental, but the keystone team is
actively collecting and addressing feedback that will result in stabilizing the
API. Stabilization changes that effect the oslo.limit library will also be
addressed before version 1.0.0 is released. From there, we can look to
incorporate the library into various services that either have an existing
quota implementation, or services that have a quota requirement but no
implementation.&lt;/p&gt;
&lt;p&gt;This should help us refine the interfaces between services and oslo.limit,
while providing a facade to handle complexities of project hierarchies. This
should enable adoption by simplifying the process and making it easier for
quota to be implemented in a consistent way across services.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="reviewer-activity"&gt;
&lt;h2&gt;Reviewer activity&lt;/h2&gt;
&lt;p&gt;At first thought, it makes sense to model the reviewer structure after the
oslo.policy library, where the core team consists of people not only interested
in limits and quota, but also people familiar with the keystone implementation
of the unified limits API.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="author-s"&gt;
&lt;h3&gt;Author(s)&lt;/h3&gt;
&lt;p&gt;Who is leading the proposal of the new library? Must have at least two
individuals from the community committed to triaging and fixing bugs, and
responding to test failures in a timely manner.&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary authors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Lance Bragstad (&lt;a class="reference external" href="mailto:lbragstad%40gmail.com"&gt;lbragstad&lt;span&gt;@&lt;/span&gt;gmail&lt;span&gt;.&lt;/span&gt;com&lt;/a&gt;) lbragstad
XiYuan Wang (&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;) wxy&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;Create a new library called oslo.limit&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create a core group for the project&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Define the minimum we need to enforce quota calculations in oslo.limit&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Propose an implementation that allows services to test out quota
enforcement via unified limits&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;Rocky PTG &lt;a class="reference external" href="https://etherpad.openstack.org/p/unified-limits-rocky-ptg"&gt;etherpad&lt;/a&gt; for unified
limits. This is where we discussed the interaction between services and
keystone, ultimately agreeing on the inclusion of a library to handle quota
enforcement.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="revision-history"&gt;
&lt;h2&gt;Revision History&lt;/h2&gt;
&lt;table class="docutils align-default" id="id1"&gt;
&lt;caption&gt;&lt;span class="caption-text"&gt;Revisions&lt;/span&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Release Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Description&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Rocky&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This work is licensed under a Creative Commons Attribution 3.0
Unported License.
&lt;a class="reference external" href="http://creativecommons.org/licenses/by/3.0/legalcode"&gt;http://creativecommons.org/licenses/by/3.0/legalcode&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
</description><pubDate>Wed, 14 Mar 2018 00:00:00 </pubDate></item><item><title>Backend Drivers for oslo.config</title><link>https://specs.openstack.org/openstack/oslo-specs/specs/queens/oslo-config-drivers.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/oslo.config/+spec/oslo-config-drivers"&gt;https://blueprints.launchpad.net/oslo.config/+spec/oslo-config-drivers&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Currently, oslo.config is tightly bound to the plain text
configuration files. This spec describes changes to allow deployers to
store configuration data in other places, such as secret stores
managed by castellan, by adding a driver layer to oslo.config.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Various regulations and best practices say that passwords and other
secret values should not be stored in plain text in configuration
files. There are “secret store” services to manage values that should
be kept secure. Castellan provides an abstraction API for accessing
those services. Castellan also depends on oslo.config, which means
oslo.config cannot use castellan directly.&lt;/p&gt;
&lt;p&gt;This spec describes a new driver API for oslo.config to allow us to
(separately) write a driver in castellan that can be used when it is
installed but will not cause errors when it is missing.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;oslo.config is updated so that multiple backends can be used and the
existing INI parser is turned into one driver.&lt;/p&gt;
&lt;p&gt;As part of initializing the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ConfigOpts&lt;/span&gt;&lt;/code&gt; instance and loading
settings, all known drivers will be interrogated to determine if they
can provide one or more “sources” of data. The driver is responsible
for defining its own configuration options and interpreting them to
define a data “source”.&lt;/p&gt;
&lt;p&gt;A new configuration option &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;DEFAULT.config_sources&lt;/span&gt;&lt;/code&gt; is added to
define sources other than those provided by &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;--config-file&lt;/span&gt;&lt;/code&gt; and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;--config-dir&lt;/span&gt;&lt;/code&gt; on the command line. The value for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;config_sources&lt;/span&gt;&lt;/code&gt;
is a list of source identifiers used to find configuration settings
for other sources. Each source identifier corresponds to a
configuration option group, which provides the details for a single
source of configuration data.&lt;/p&gt;
&lt;p&gt;When &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ConfigOpts&lt;/span&gt;&lt;/code&gt; looks for an option value, it goes through the
defined sources in the order they are provided, starting with the
command line, then any configuration files, and finally the sources
loaded from &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;config_sources&lt;/span&gt;&lt;/code&gt;. The first source that provides a
configured value for an option causes the search to end (sources are
not “merged” internally).&lt;/p&gt;
&lt;p&gt;An occurance of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;--config-dir&lt;/span&gt;&lt;/code&gt; will continue to be treated as a
single source, as it is now (all of the options are merged into one
namespace) using the INI file driver.&lt;/p&gt;
&lt;section id="implementation-details"&gt;
&lt;h3&gt;Implementation details&lt;/h3&gt;
&lt;p&gt;When &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ConfigOpts&lt;/span&gt;&lt;/code&gt; is done parsing the command line options and
loading configuration files, it will iterate over the items in
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;DEFAULT.config_sources&lt;/span&gt;&lt;/code&gt;. Each string in the list value will be
interpreted as the name of an option group that defines another
configuration source. The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;driver&lt;/span&gt;&lt;/code&gt; setting in each group will
specify which &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo.config&lt;/span&gt;&lt;/code&gt; driver to use to load a source from the
option group using &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;open_source_from_opt_group()&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;open_source_from_opt_group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;conf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;group_name&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="sd"&gt;"""Return an open option source.&lt;/span&gt;

&lt;span class="sd"&gt;    Use group_name to find the configuration settings for the new&lt;/span&gt;
&lt;span class="sd"&gt;    source then open the source and return it.&lt;/span&gt;

&lt;span class="sd"&gt;    If a source cannot be open, raise an appropriate exception.&lt;/span&gt;

&lt;span class="sd"&gt;    :param conf: The active configuration option handler from which&lt;/span&gt;
&lt;span class="sd"&gt;                 to seek configuration values.&lt;/span&gt;
&lt;span class="sd"&gt;    :type conf: ConfigOpts&lt;/span&gt;
&lt;span class="sd"&gt;    :param group_name: The configuration option group name where the&lt;/span&gt;
&lt;span class="sd"&gt;                       options for the source are stored.&lt;/span&gt;
&lt;span class="sd"&gt;    :type group_name: str&lt;/span&gt;
&lt;span class="sd"&gt;    :return: instance of subclass of ConfigurationSource&lt;/span&gt;
&lt;span class="sd"&gt;    """&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Each &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ConfigurationSource&lt;/span&gt;&lt;/code&gt; instance is expected to retain any
information it needs to maintain a connection. Whether the connection
is long-lived or opened each time a configuration value is needed is
up to the driver.&lt;/p&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ConfigurationSource&lt;/span&gt;&lt;/code&gt; is not explicitly closed. If a connection
is lost, it is the responsibility of the driver to re-open it, or emit
a hard failure exception.&lt;/p&gt;
&lt;p&gt;Each time &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ConfigOpts&lt;/span&gt;&lt;/code&gt; is asked for the value of an option, it will
iterate over the drivers and sources in the order they were registered
and call &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;get()&lt;/span&gt;&lt;/code&gt; on the source, always passing an explicit group
name and option name.&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;group_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;option_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;opt&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="sd"&gt;"""Return the value of the option from the group.&lt;/span&gt;

&lt;span class="sd"&gt;    :param group_name: Name of the group.&lt;/span&gt;
&lt;span class="sd"&gt;    :type group_name: str&lt;/span&gt;
&lt;span class="sd"&gt;    :param option_name: Name of the option.&lt;/span&gt;
&lt;span class="sd"&gt;    :type option_name: str&lt;/span&gt;
&lt;span class="sd"&gt;    :param opt: The option definition.&lt;/span&gt;
&lt;span class="sd"&gt;    :type opt: Opt&lt;/span&gt;
&lt;span class="sd"&gt;    :return: Option value or NoValue.&lt;/span&gt;
&lt;span class="sd"&gt;    """&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The source should return the value of the option, if it is present in
the data store being accessed. The return value should either match
the type for the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Opt&lt;/span&gt;&lt;/code&gt;, or another type such as a string that can be
coerced into the required type. The caller will perform the type
conversion in that case.&lt;/p&gt;
&lt;p&gt;Converting complex types such as lists and dictionaries for storage is
left up to the driver to specify, though if the values need to be
encoded it would be good if that happened either as JSON or using the
same syntax that the INI files use.&lt;/p&gt;
&lt;p&gt;If the value is not available in the data store, the source should
return &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo_config.drivers.NoValue&lt;/span&gt;&lt;/code&gt;. We cannot use &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;None&lt;/span&gt;&lt;/code&gt; as a
sentinel indicating a missing value because it may be a valid value or
default, so we use a custom singleton instead.&lt;/p&gt;
&lt;p&gt;The opt parameter is provided in case the driver needs to do advanced
coercion (such as mapping an integer value to a choice). It should not
be used for type coercion except in special circumstances.&lt;/p&gt;
&lt;p&gt;The driver is not responsible for handling deprecated option
names. The caller will look for a value using the current option name
then search again using the deprecated name(s) if no source has a
value under the current name.&lt;/p&gt;
&lt;p&gt;New error classes with more generic names need to be derived from
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ConfigFilesNotFoundError&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ConfigFilesPermissionDeniedError&lt;/span&gt;&lt;/code&gt;
to be used in similar situations by the drivers.&lt;/p&gt;
&lt;p&gt;All other errors raised from the drivers will be trapped by
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ConfigOpts&lt;/span&gt;&lt;/code&gt; and logged as warnings and the driver will be treated
as though it returned &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;NoValue&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Drivers will be implemented inside the oslo.config library, and loaded
through entry points managed by &lt;a class="reference external" href="https://docs.openstack.org/stevedore/latest/"&gt;stevedore&lt;/a&gt; using the namespace
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo.config.driver&lt;/span&gt;&lt;/code&gt;. This will allow us, for example, to add a
driver to the castellan library without introducing a circular
dependency between castellan and oslo.config.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="caching-and-mutable-option-handling"&gt;
&lt;h3&gt;Caching and Mutable Option Handling&lt;/h3&gt;
&lt;p&gt;The existing “mutate configuration” behavior, which allows a service
to tell oslo.config to reload the configuration file, is extended to
work with the new configuration sources.&lt;/p&gt;
&lt;p&gt;Values retrieved from a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ConfigurationSource&lt;/span&gt;&lt;/code&gt; may be cached by the
ConfigOpts instance to avoid repeated calls to a remote service (they
should &lt;em&gt;not&lt;/em&gt; be cached by the driver).  When the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ConfigOpts&lt;/span&gt;&lt;/code&gt; class
is told to mutate its options, it discards any cached values it holds,
as well as any open &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ConfigurationSource&lt;/span&gt;&lt;/code&gt; instances. It will then
load its configuration sources again, from scratch. This avoids the
need for a cache-flushing API in the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ConfigurationSource&lt;/span&gt;&lt;/code&gt; class,
keeping the drivers simple.&lt;/p&gt;
&lt;p&gt;The existing behavior for detecting changes to options not configured
as mutable is retained, as is the existing callback system for
notifying applications that options have been reloaded.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;An earlier version of this spec focused on an etcd driver for
container use cases. That problem has been solved using a different
approach.&lt;/p&gt;
&lt;p&gt;Other backends, such as castellan, consul, zookeeper, MySQL, and etcd,
can be implemented separately without writing additional specs, unless
implementing them will require modifying the API defined for the
drivers.&lt;/p&gt;
&lt;p&gt;There is &lt;a class="reference external" href="https://review.openstack.org/130047"&gt;another proposal&lt;/a&gt;
that introduces a proxy interface to configuration options. However,
it does not provide any mechanism to make it configurable.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="impact-on-existing-apis"&gt;
&lt;h3&gt;Impact on Existing APIs&lt;/h3&gt;
&lt;p&gt;There are no changes to the existing public API for oslo.config.&lt;/p&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ConfigurationSource&lt;/span&gt;&lt;/code&gt; class and the new exceptions will be added
to the API.&lt;/p&gt;
&lt;p&gt;The behavior when oslo.config is told to “mutate” its configuration
will change, but the call to perform the mutation is the same.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;We assume that any remote access would occur over an encrypted
connection.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;Because configuration options can be registered by a service at any
time during operation, it may not always be possible for a driver
initialized early in the process start up to load “all” of the
settings in one call. Therefore some configuration accesses may be
slower than when reading just from an INI file. We can use caching in
the top layer in oslo.config to mitigate this impact. Drivers are free
to implement their own optimizations internally (such as fetching all
of the keys in a namespace or all of the rows from a table), but the
ability to do so is not assumed in the driver API.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="configuration-impact"&gt;
&lt;h3&gt;Configuration Impact&lt;/h3&gt;
&lt;p&gt;Deployers using a secret store will need to load configuration values
into their database using a native tool. The scheme for each backend
service must be documented in order for them to be able to do this.&lt;/p&gt;
&lt;p&gt;We may want to build a tool to read an INI file and publish it to a
remote system, but that is not part of this spec and would have to be
described separately before being implemented. Deployment tools such
as Tripleo may provide their mechanism for doing this, or contribute
to doing the work through oslo.config to be shared. It is expected
that drivers will need a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;set()&lt;/span&gt;&lt;/code&gt; method to support uploading
configuration settings.&lt;/p&gt;
&lt;p&gt;Below is an example using a configuration file and hypothetical secret
store set up via the config file.&lt;/p&gt;
&lt;p&gt;The program is started using the standard &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;--config-file&lt;/span&gt;&lt;/code&gt; option on
the command line.&lt;/p&gt;
&lt;div class="highlight-console notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="gp"&gt;$ &lt;/span&gt;app&lt;span class="w"&gt; &lt;/span&gt;--config-file&lt;span class="w"&gt; &lt;/span&gt;/path/to/file.conf
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;and the configuration file &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;file.conf&lt;/span&gt;&lt;/code&gt; contains:&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;config_sources&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;secret&lt;/span&gt;

&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;secret&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;driver&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;castellan&lt;/span&gt;
&lt;span class="n"&gt;mapping_file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;mapping&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ini&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;Developers will not notice any difference in their use of oslo.config.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing-impact"&gt;
&lt;h3&gt;Testing Impact&lt;/h3&gt;
&lt;p&gt;We will need unit tests for the priority resolution algorithm.&lt;/p&gt;
&lt;p&gt;We will need unit tests for the driver(s).&lt;/p&gt;
&lt;p&gt;We will need functional tests for the driver(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;p&gt;Primary assignee:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Samuel Pilla (spilla)&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;Doug Hellmann (dhellmann)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="milestones"&gt;
&lt;h3&gt;Milestones&lt;/h3&gt;
&lt;p&gt;queens-3 or rocky-2&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;Define the base class for a configuration driver.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Define the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ConfigurationSource&lt;/span&gt;&lt;/code&gt; base class.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Set up the namespace for entry points for drivers.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Define a new driver for loading configuration from simple URLs to be
used as a test case.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Extend &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ConfigOpts&lt;/span&gt;&lt;/code&gt; to load and use the drivers, as described
above. This will add URL handling without changing the way file
loading works.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ConfigOpts&lt;/span&gt;&lt;/code&gt; to use the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ConfigurationSource&lt;/span&gt;&lt;/code&gt; search
algorithm described above in addition to its current search
algorithm.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Ensure that &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ConfigOpts&lt;/span&gt;&lt;/code&gt; only caches non-mutable values.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Change &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;mutate_config_files()&lt;/span&gt;&lt;/code&gt; to discard all of the existing data
and reload it, without performing any validation. Fix tests and
erase dead code left by rewriting that feature.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="incubation"&gt;
&lt;h2&gt;Incubation&lt;/h2&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;section id="adoption"&gt;
&lt;h3&gt;Adoption&lt;/h3&gt;
&lt;p&gt;TBD&lt;/p&gt;
&lt;/section&gt;
&lt;section id="library"&gt;
&lt;h3&gt;Library&lt;/h3&gt;
&lt;p&gt;oslo.config&lt;/p&gt;
&lt;/section&gt;
&lt;section id="anticipated-api-stabilization"&gt;
&lt;h3&gt;Anticipated API Stabilization&lt;/h3&gt;
&lt;p&gt;TBD&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;TBD&lt;/p&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="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/oslo.config_etcd_backend"&gt;https://etherpad.openstack.org/p/oslo.config_etcd_backend&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/tripleo-etcd-transition"&gt;https://etherpad.openstack.org/p/tripleo-etcd-transition&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/oslo-config-pluggable-cmdb"&gt;https://etherpad.openstack.org/p/oslo-config-pluggable-cmdb&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A &lt;a class="reference external" href="https://review.openstack.org/#/c/243114/"&gt;related spec&lt;/a&gt; by Vladimir Eremin &amp;lt;&lt;a class="reference external" href="mailto:veremin%40mirantis.com"&gt;veremin&lt;span&gt;@&lt;/span&gt;mirantis&lt;span&gt;.&lt;/span&gt;com&lt;/a&gt;&amp;gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This work is licensed under a &lt;a class="reference external" href="http://creativecommons.org/licenses/by/3.0/legalcode"&gt;Creative Commons Attribution 3.0
Unported License&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
</description><pubDate>Tue, 27 Feb 2018 00:00:00 </pubDate></item><item><title>Graduating Reports</title><link>https://specs.openstack.org/openstack/oslo-specs/specs/liberty/graduate-oslo-reports.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/oslo-incubator/+spec/graduate-oslo-reports"&gt;https://blueprints.launchpad.net/oslo-incubator/+spec/graduate-oslo-reports&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The &lt;cite&gt;reports&lt;/cite&gt; module currently provides a convenient way to assemble
“Guru Meditation Reports” about the current state a of a given OpenStack
process.  The basic report includes thread (both normal and green) state
and stack traces, as well as configuration and version information.  The
reports are customizable and may be extended with additional sections on
a per-process or per-project basis.  A mechanism is also included to set
up the reports to dump to stdout (or a file) on SIGUSR1, and may be
serialized as text (default), as well as XML and JSON.&lt;/p&gt;
&lt;section id="library-name"&gt;
&lt;h2&gt;Library Name&lt;/h2&gt;
&lt;p&gt;The library will be called “oslo.reports”.  The current name in the
incubator is “openstack.common.report”, but pluralizing the name seems more
natural.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="contents"&gt;
&lt;h2&gt;Contents&lt;/h2&gt;
&lt;p&gt;openstack/common/report/report.py
openstack/common/report/utils.py
openstack/common/report/guru_meditation_report.py
openstack/common/report/__init__.py
openstack/common/report/views/__init__.py
openstack/common/report/views/text/__init__.py
openstack/common/report/views/text/generic.py
openstack/common/report/views/text/threading.py
openstack/common/report/views/text/header.py
openstack/common/report/views/xml/__init__.py
openstack/common/report/views/xml/generic.py
openstack/common/report/views/jinja_view.py
openstack/common/report/views/json/__init__.py
openstack/common/report/views/json/generic.py
openstack/common/report/generators/conf.py
openstack/common/report/generators/__init__.py
openstack/common/report/generators/version.py
openstack/common/report/generators/threading.py
openstack/common/report/models/base.py
openstack/common/report/models/conf.py
openstack/common/report/models/__init__.py
openstack/common/report/models/version.py
openstack/common/report/models/with_default_views.py
openstack/common/report/models/threading.py&lt;/p&gt;
&lt;p&gt;tests/unit/reports/test_base_report.py
tests/unit/reports/test_guru_meditation_report.py
tests/unit/reports/test_openstack_generators.py
tests/unit/reports/test_views.py&lt;/p&gt;
&lt;/section&gt;
&lt;section id="early-adopters"&gt;
&lt;h2&gt;Early Adopters&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="public-api"&gt;
&lt;h2&gt;Public API&lt;/h2&gt;
&lt;p&gt;The &lt;cite&gt;reports&lt;/cite&gt; module contains several public submodules:&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;&lt;cite&gt;reports.guru_meditation_report&lt;/cite&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Contains the code revolving around setting up the signal handler and
registering persistent custom sections&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;cite&gt;reports.report&lt;/cite&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Contains the basic classes for the reports themselves, including a class
for the whole report, a class for each section, and a subclass specifically
for reports serialized as text&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;cite&gt;reports.generators&lt;/cite&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Contains the submodules containing generator code: &lt;cite&gt;conf&lt;/cite&gt;, &lt;cite&gt;threading&lt;/cite&gt;,
&lt;cite&gt;version&lt;/cite&gt; (not that there is no &lt;cite&gt;base&lt;/cite&gt; module here since generators are
just callables)&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;cite&gt;reports.models&lt;/cite&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Contains the submodules containing the base model classes (&lt;cite&gt;base&lt;/cite&gt; and
&lt;cite&gt;with_default_views&lt;/cite&gt;) as well as the implementation model classes
(&lt;cite&gt;threading&lt;/cite&gt;, &lt;cite&gt;version&lt;/cite&gt;, and &lt;cite&gt;conf&lt;/cite&gt;)&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;cite&gt;report.views&lt;/cite&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Contains the submodule containing the basic Jinja-based view (&lt;cite&gt;jinja_view&lt;/cite&gt;),
as well as the JSON, XML, and text views (&lt;cite&gt;json&lt;/cite&gt;, &lt;cite&gt;xml&lt;/cite&gt;, and &lt;cite&gt;text&lt;/cite&gt;,
respectively).  Note that each of the serialization-formatting submodules
contains a &lt;cite&gt;generic&lt;/cite&gt; submodule containing generic classes, and the
&lt;cite&gt;text&lt;/cite&gt; submodule additionally contains the &lt;cite&gt;header&lt;/cite&gt; submodule
(as well as the &lt;cite&gt;threading&lt;/cite&gt; submodule, which may be made private).&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;The following submodules do not necessarily need to be public:&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;&lt;cite&gt;reports.utils&lt;/cite&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Contains a utility class for attaching attributes to strings, as well as
a function for finding all objects of a particular class using the garbage
collector functionality.  Neither of these need to be exposed as public,
and the object-finding function can be moved into the file of the generator
which uses it (&lt;cite&gt;StringWithAttrs&lt;/cite&gt; is used by both &lt;cite&gt;reports.views.xml.generic&lt;/cite&gt;
and &lt;cite&gt;reports.views.json.generic&lt;/cite&gt;), so it needs to stay in its own file.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;cite&gt;reports.views.text.threading&lt;/cite&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;This contains several views specific to certain models (which already have
them set as the default text view), so it does not need to be public.&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;sross-7&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="primary-maintainer"&gt;
&lt;h3&gt;Primary Maintainer&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary Maintainer:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;sross-7&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="security-contact"&gt;
&lt;h3&gt;Security Contact&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Security Contact:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;sross-7&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="milestones"&gt;
&lt;h3&gt;Milestones&lt;/h3&gt;
&lt;p&gt;Target Milestone for completion: Uknown&lt;/p&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;p&gt;The graduation checklist should be completed.&lt;/p&gt;
&lt;p&gt;Additionally, there are a few places where &lt;cite&gt;reports&lt;/cite&gt; currently uses
&lt;cite&gt;str&lt;/cite&gt; and should be using &lt;cite&gt;six.text_type&lt;/cite&gt; instead.  These should be
fixed before graduation is complete.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="adoption-notes"&gt;
&lt;h2&gt;Adoption Notes&lt;/h2&gt;
&lt;p&gt;None&lt;/p&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.utils&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;oslo.serialization&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;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This work is licensed under a Creative Commons Attribution 3.0
Unported License.
&lt;a class="reference external" href="http://creativecommons.org/licenses/by/3.0/legalcode"&gt;http://creativecommons.org/licenses/by/3.0/legalcode&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
</description><pubDate>Thu, 08 Feb 2018 00:00:00 </pubDate></item><item><title>Configuration change handling over releases</title><link>https://specs.openstack.org/openstack/oslo-specs/specs/rocky/handle-config-changes.html</link><description>

&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description:&lt;/h2&gt;
&lt;p&gt;When users perform upgrade their OpenStack system to new release, normally
they are required to update configuration files for adapting changes from old
release to new release. Basically, at that time they must read release notes
or change logs or even track source code changes for doing this.&lt;/p&gt;
&lt;p&gt;But unfortunately, there could be some misunderstanding, lack of information
in release notes that cause users confuse. There should be some helper in
oslo.config for automatically adopt new changes and help users manage their
configuration files easily.&lt;/p&gt;
&lt;p&gt;Scenario:&lt;/p&gt;
&lt;p&gt;Below is the proposed workflow that users can perform on old system to generate
new configuration for preparing upgrading to new release:&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;Old&lt;/span&gt; &lt;span class="n"&gt;configuration&lt;/span&gt;  &lt;span class="o"&gt;+--------&amp;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;N&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="n"&gt;release&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;              &lt;span class="o"&gt;|&lt;/span&gt;     &lt;span class="n"&gt;Oslo&lt;/span&gt;     &lt;span class="o"&gt;|&lt;/span&gt;
                            &lt;span class="o"&gt;|&lt;/span&gt;    &lt;span class="n"&gt;Config&lt;/span&gt;    &lt;span class="o"&gt;+-------&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;New&lt;/span&gt; &lt;span class="n"&gt;configuration&lt;/span&gt;
      &lt;span class="n"&gt;Namespaces&lt;/span&gt;   &lt;span class="o"&gt;+--------&amp;gt;&lt;/span&gt;   &lt;span class="n"&gt;Migrator&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt;            &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;N&lt;/span&gt; &lt;span class="n"&gt;release&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                            &lt;span class="o"&gt;|&lt;/span&gt;              &lt;span class="o"&gt;|&lt;/span&gt;
                            &lt;span class="o"&gt;+--------------+&lt;/span&gt;

                      &lt;span class="n"&gt;Running&lt;/span&gt; &lt;span class="n"&gt;on&lt;/span&gt; &lt;span class="n"&gt;new&lt;/span&gt; &lt;span class="n"&gt;environment&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;We had a method to generate data structure of machine readable sample config for
any projects, so we could base on this method to get a ConfigOpts instance
(CONF object) with full list of options from not only main project but also
other projects which are listed in namespaces.&lt;/p&gt;
&lt;p&gt;Base on the CONF object then we can get the information of options about
whether &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;deprecated_name&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;deprecated_group&lt;/span&gt;&lt;/code&gt; or not. If yes, then it
is possible to implement a function to update from old configuration to new
configuration, so we call this case is “Mapping 1:1 without changing value.
In fact, not only this case but also other cases including:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Case 1&lt;/strong&gt;: Mapping 1:1 without changing value.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Case 2&lt;/strong&gt;: Mapping 1:1 with changing value.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Case 3&lt;/strong&gt;: Mapping N:1. It means one option can replace a group of options.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Case 4&lt;/strong&gt;: Mapping M*N:1. Meaning that one option can replace a super
group of options.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Case 5&lt;/strong&gt;: Dynamic section.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Case 6&lt;/strong&gt;: Dynamic option.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;By using &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;deprecated_name&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;deprecated_group&lt;/span&gt;&lt;/code&gt;, we are able to solve
&lt;strong&gt;Case 1&lt;/strong&gt;.  The examples of &lt;strong&gt;Case 1&lt;/strong&gt; are as follows:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Change the key of option:&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight-ini notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="k"&gt;[keystone_authtoken]&lt;/span&gt;
&lt;span class="na"&gt;auth_uri&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;http://192.168.122.250:5000&lt;/span&gt;
&lt;span class="na"&gt;--&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;[keystone_authtoken]&lt;/span&gt;
&lt;span class="na"&gt;www_authenticate_uri&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;http://192.168.122.250:5000&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;ol class="arabic simple" start="2"&gt;
&lt;li&gt;&lt;p&gt;Change section of option:&lt;/p&gt;&lt;/li&gt;
&lt;/ol&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;api_paste_config&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;api-paste.ini&lt;/span&gt;
&lt;span class="na"&gt;--&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;[wsgi]&lt;/span&gt;
&lt;span class="na"&gt;api_paste_config&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;api-paste.ini&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;ol class="arabic simple" start="3"&gt;
&lt;li&gt;&lt;p&gt;Change section and key of option:&lt;/p&gt;&lt;/li&gt;
&lt;/ol&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;notification_driver&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;messaging&lt;/span&gt;
&lt;span class="na"&gt;--&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;[oslo_messaging_notifications]&lt;/span&gt;
&lt;span class="na"&gt;driver&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;messaging&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;In order to solve &lt;strong&gt;Case 2&lt;/strong&gt; then it is necessary to adding a parameter to Opt
class. It is called “convert_on_upgrade”. It will be a function that is to map
from old value to new value.&lt;/p&gt;
&lt;p&gt;For example:&lt;/p&gt;
&lt;div class="highlight-python notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StrOpt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'choices_opt'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;choices&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'a_new'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'b_new'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'c_new'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="n"&gt;convert_on_upgrade&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;choice_opt_converter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;help&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'a choice opt'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;choice_opt_converter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;opt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="s1"&gt;'a'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'a_new'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'b'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'b_new'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'c'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'c_new'&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="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&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="problems"&gt;
&lt;h2&gt;Problems:&lt;/h2&gt;
&lt;p&gt;With this proposal, we have just solved only 2 basic cases (case 1 and case 2).
For the more complicated cases, we have not yet to resolve them. Here are
remaining cases that need to be achieved for this feature.&lt;/p&gt;
&lt;section id="case-3-mapping-n-options-to-1-option"&gt;
&lt;h3&gt;Case 3: Mapping N options to 1 option:&lt;/h3&gt;
&lt;p&gt;For example:&lt;/p&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;identify_uri&lt;/span&gt;&lt;/code&gt; can replace 3 options: &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;auth_host&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;auth_port&lt;/span&gt;&lt;/code&gt;
and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;auth_protocol&lt;/span&gt;&lt;/code&gt;.&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;[keystone_authtoken]&lt;/span&gt;
&lt;span class="na"&gt;auth_protocol&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;http&lt;/span&gt;
&lt;span class="na"&gt;auth_host&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;controller&lt;/span&gt;
&lt;span class="na"&gt;auth_port&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;35357&lt;/span&gt;
&lt;span class="na"&gt;--&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;[keystone_authtoken]&lt;/span&gt;
&lt;span class="na"&gt;identity_uri&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;http://controller:35357&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="case-4-mapping-m-n-options-to-1-option"&gt;
&lt;h3&gt;Case 4: Mapping M*N options to 1 option:&lt;/h3&gt;
&lt;p&gt;Currently, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;transport_url&lt;/span&gt;&lt;/code&gt; is a big example for this case. With M is the
number of options in a driver for message queue, N is the number of drivers
(N&amp;gt;1).&lt;/p&gt;
&lt;p&gt;For example:&lt;/p&gt;
&lt;p&gt;If RabbitMQ is used as backend for message queue then &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;transport_url&lt;/span&gt;&lt;/code&gt; can
replace four options such as &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;rabbit_host&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;rabbit_port&lt;/span&gt;&lt;/code&gt;,
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;rabbit_userid&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;rabbit_password&lt;/span&gt;&lt;/code&gt; (M=4) by using a template like this:
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;rabbit://rabbit_userid:rabbit_password@rabbit_host:rabbit_port&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;If Kafka is backend for message queue then &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;transport_url&lt;/span&gt;&lt;/code&gt; can replace
two options including &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;kafka_default_host&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;kafka_default_port&lt;/span&gt;&lt;/code&gt;
(M=2) by using  a template like this:
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;kafka://kafka_default_host:kafka_default_port&lt;/span&gt;&lt;/code&gt;.&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;rpc_backend&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;rabbit&lt;/span&gt;
&lt;span class="c1"&gt;#rpc_backend = kafka&lt;/span&gt;

&lt;span class="k"&gt;[oslo_messaging_rabbit]&lt;/span&gt;
&lt;span class="na"&gt;rabbit_host&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;controller&lt;/span&gt;
&lt;span class="na"&gt;rabbit_userid&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;openstack&lt;/span&gt;
&lt;span class="na"&gt;rabbit_password&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;RABBIT_PASS&lt;/span&gt;
&lt;span class="na"&gt;rabbit_port&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;5672&lt;/span&gt;

&lt;span class="k"&gt;[oslo_messaging_kafka]&lt;/span&gt;
&lt;span class="c1"&gt;#kafka_default_host = controller&lt;/span&gt;
&lt;span class="c1"&gt;#kafka_default_port = 9092&lt;/span&gt;
&lt;span class="na"&gt;--&amp;gt;&lt;/span&gt;

&lt;span class="k"&gt;[DEFAULT]&lt;/span&gt;
&lt;span class="na"&gt;transport_url&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;rabbit://openstack:RABBIT_PASS@controller:5672&lt;/span&gt;
&lt;span class="c1"&gt;#transport_url = kafka//openstack:9092&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="case-5-dynamic-section"&gt;
&lt;h3&gt;Case 5: Dynamic section&lt;/h3&gt;
&lt;p&gt;One important thing that there is a dynamic section. For example, Cinder has
a option named &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;enabled_backends&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;, if this option is declared like
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;enabled_backends&lt;/span&gt; &lt;span class="pre"&gt;=&lt;/span&gt; &lt;span class="pre"&gt;lvm&lt;/span&gt;&lt;/code&gt;, then there will be a new section &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[lvm]&lt;/span&gt;&lt;/code&gt; declared
in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cinder.conf&lt;/span&gt;&lt;/code&gt; like 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;[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;lvm&lt;/span&gt;

&lt;span class="k"&gt;[lvm]&lt;/span&gt;
&lt;span class="c1"&gt;# ...&lt;/span&gt;
&lt;span class="na"&gt;volume_driver&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;cinder.volume.drivers.lvm.LVMVolumeDriver&lt;/span&gt;
&lt;span class="na"&gt;volume_group&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;cinder-volumes&lt;/span&gt;
&lt;span class="na"&gt;iscsi_protocol&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;iscsi&lt;/span&gt;
&lt;span class="na"&gt;iscsi_helper&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;tgtadm&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;but if &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;enabled_backends&lt;/span&gt; &lt;span class="pre"&gt;=&lt;/span&gt; &lt;span class="pre"&gt;ceph&lt;/span&gt;&lt;/code&gt; then new section &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[ceph]&lt;/span&gt;&lt;/code&gt; shoud be
declared.&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="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;ceph&lt;/span&gt;

&lt;span class="k"&gt;[ceph]&lt;/span&gt;
&lt;span class="c1"&gt;# ...&lt;/span&gt;
&lt;span class="na"&gt;volume_driver&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;cinder.volume.drivers.rbd.RBDDriver&lt;/span&gt;
&lt;span class="na"&gt;rbd_pool&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;volumes&lt;/span&gt;
&lt;span class="na"&gt;rbd_ceph_conf&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/etc/ceph/ceph.conf&lt;/span&gt;
&lt;span class="na"&gt;rbd_store_chunk_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;4&lt;/span&gt;
&lt;span class="na"&gt;rados_connect_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;-1&lt;/span&gt;
&lt;span class="na"&gt;rbd_secret_uuid&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;457eb676-33da-42ec-9a8c-9293d545c337&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Both sections &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[lvm]&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[ceph]&lt;/span&gt;&lt;/code&gt; are not registered in codebase, the
options in these sections are actually registered in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[backend_defaults]&lt;/span&gt;&lt;/code&gt;
section and are belonging to cinder namespace.&lt;/p&gt;
&lt;p&gt;So how can we understand all values in dynamic section? This can be done via
dynamic groups or driver groups &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; but we don’t have any projects using
them, so each project should migrate to use those things instead of their
special ways to read dynamic sections.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="case-6-dynamic-option"&gt;
&lt;h3&gt;Case 6: Dynamic option&lt;/h3&gt;
&lt;p&gt;The options like &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;user_domain_id&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;project_name&lt;/span&gt;&lt;/code&gt; in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[keystone_authtoken]&lt;/span&gt;&lt;/code&gt;
are registered dynamically when start service based on which &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;auth_type&lt;/span&gt;&lt;/code&gt;
(password, token…) the service using &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;. They don’t belong to any
namespace. How can we understand these options?&lt;/p&gt;
&lt;div class="highlight-ini notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="k"&gt;[keystone_authtoken]&lt;/span&gt;
&lt;span class="na"&gt;...&lt;/span&gt;
&lt;span class="na"&gt;auth_uri&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;http://controller:5000&lt;/span&gt;
&lt;span class="na"&gt;auth_url&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;http://controller:5000&lt;/span&gt;
&lt;span class="na"&gt;memcached_servers&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;controller:11211&lt;/span&gt;
&lt;span class="na"&gt;auth_type&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;password&lt;/span&gt;
&lt;span class="na"&gt;project_domain_id&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;default&lt;/span&gt;
&lt;span class="na"&gt;user_domain_id&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;default&lt;/span&gt;
&lt;span class="na"&gt;project_name&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;service&lt;/span&gt;
&lt;span class="na"&gt;username&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;cinder&lt;/span&gt;
&lt;span class="na"&gt;password&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;cinder&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h2&gt;Work Items:&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Implement one attribute: mapping_value.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Implement a new function to render new configuration files based on codebase
and old configuration files.&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 have two documentations:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Having a docs to guide projects to update source-code if they want to have
this feature.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Having a docs for Operators about step by step to use this feature.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="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;Phuong Hung Nguyen &amp;lt;&lt;a class="reference external" href="mailto:phuongnh%40vn.fujitsu.com"&gt;phuongnh&lt;span&gt;@&lt;/span&gt;vn&lt;span&gt;.&lt;/span&gt;fujitsu&lt;span&gt;.&lt;/span&gt;com&lt;/a&gt;&amp;gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Duc Nguyen Van &amp;lt;&lt;a class="reference external" href="mailto:ducnv%40vn.fujitsu.com"&gt;ducnv&lt;span&gt;@&lt;/span&gt;vn&lt;span&gt;.&lt;/span&gt;fujitsu&lt;span&gt;.&lt;/span&gt;com&lt;/a&gt;&amp;gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References:&lt;/h2&gt;
&lt;aside class="footnote-list brackets"&gt;
&lt;aside class="footnote brackets" id="id4" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id1"&gt;1&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://github.com/openstack/cinder/blob/66b3a52794f9c2aa6652b28c0a8e67792e2f993b/cinder/common/config.py#L160"&gt;https://github.com/openstack/cinder/blob/66b3a52794f9c2aa6652b28c0a8e67792e2f993b/cinder/common/config.py#L160&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id5" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id2"&gt;2&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://docs.openstack.org/oslo.config/latest/reference/cfg.html#dynamic-groups"&gt;https://docs.openstack.org/oslo.config/latest/reference/cfg.html#dynamic-groups&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://eavesdrop.openstack.org/irclogs/%23openstack-keystone/%23openstack-keystone.2018-08-28.log.html#t2018-08-28T12:06:55"&gt;http://eavesdrop.openstack.org/irclogs/%23openstack-keystone/%23openstack-keystone.2018-08-28.log.html#t2018-08-28T12:06:55&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;/aside&gt;
&lt;/section&gt;
</description><pubDate>Wed, 15 Nov 2017 00:00:00 </pubDate></item><item><title>Provide a set of examples for oslo libraries</title><link>https://specs.openstack.org/openstack/oslo-specs/specs/liberty/oslo-examples.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/oslo.messaging/+spec/oslo-examples"&gt;https://blueprints.launchpad.net/oslo.messaging/+spec/oslo-examples&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;For each oslo library provide a set of examples to illustrate
a use case of a specific library API.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;For now we have no any example (except tests) of how to use each
oslo library. Functional tests are close to be, but they are
more abstract and serve to check the functionality, not to illustrate
the way how it can be used in the application.&lt;/p&gt;
&lt;p&gt;It is desirable to have some expressive examples which could serve
as documentation for the code.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;In each oslo library repository create an examples folder, where put
some examples for the library API.&lt;/p&gt;
&lt;p&gt;It is preferrable that example be like a mini application, and built
in terms of some application domain, not as “ClientA calls ServerB with
request1”.&lt;/p&gt;
&lt;p&gt;We can implement a set of examples for oslo.messaging in the same manner as
in taskflow:&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://github.com/openstack/taskflow/tree/master/taskflow/examples"&gt;https://github.com/openstack/taskflow/tree/master/taskflow/examples&lt;/a&gt;
The examples all get tested during unit test runs to ensure they work as expected.&lt;/p&gt;
&lt;p&gt;They are also should be part of the documentation, and be built as docs.
There will be a separate file in the docs folder that includes the code
in the examples folder.&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://raw.githubusercontent.com/openstack/taskflow/master/doc/source/examples.rst"&gt;https://raw.githubusercontent.com/openstack/taskflow/master/doc/source/examples.rst&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;An example may look like the following:&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;bobMessenger&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;messenger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Bob'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;aliceMessenger&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;messenger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Alice'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;messenger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Server&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;bobMessenger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;aliceMessenger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run&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;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# wait for all participants discover each other&lt;/span&gt;

&lt;span class="n"&gt;assertEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;clientsList&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
             &lt;span class="n"&gt;bobMessenger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;clientsList&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
             &lt;span class="n"&gt;aliceMessenger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;clientsList&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;bobMessenger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sendMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Alice'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Hi, there!'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;assertEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bobMessenger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;history&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'Alice'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
             &lt;span class="n"&gt;aliceMessenger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;history&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'Bob'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Or for the request-reply pattern:&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;fibServer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fibonacci&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Server&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;fibClient&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fibonacci&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;fibServer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fibClient&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getFibonacci&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="n"&gt;assertEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6765&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;Functional tests built on top of some real-world application which uses
oslo libraries for its implementation. A kind of indirect testing
which may show the way how the library could be improved or optimised.
Such testing also serves as an example of usage, because we test the application
which uses the library and therefore demonstrates how to use the API.&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/oslo.messaging/+spec/oslo-functional-testing-apps"&gt;https://blueprints.launchpad.net/oslo.messaging/+spec/oslo-functional-testing-apps&lt;/a&gt;&lt;/p&gt;
&lt;/section&gt;
&lt;section id="impact-on-existing-apis"&gt;
&lt;h3&gt;Impact on Existing APIs&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="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="configuration-impact"&gt;
&lt;h3&gt;Configuration 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;Any future changes to oslo.* API should be reflected in the examples.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing-impact"&gt;
&lt;h3&gt;Testing Impact&lt;/h3&gt;
&lt;p&gt;All examples should run with unit tests.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;&lt;a class="reference external" href="mailto:ozamiatin%40mirantis.com"&gt;ozamiatin&lt;span&gt;@&lt;/span&gt;mirantis&lt;span&gt;.&lt;/span&gt;com&lt;/a&gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;&lt;a class="reference external" href="mailto:dmakogon%40mirantis.com"&gt;dmakogon&lt;span&gt;@&lt;/span&gt;mirantis&lt;span&gt;.&lt;/span&gt;com&lt;/a&gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="milestones"&gt;
&lt;h3&gt;Milestones&lt;/h3&gt;
&lt;p&gt;Target Milestone for completion:
* liberty-3&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;Develop examples for each oslo library&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;taskflow - got as a pattern&lt;/p&gt;
&lt;p&gt;We are going to start with oslo.messaging and oslo.concurrency
and move on to the other libraries when the work is done.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="incubation"&gt;
&lt;h2&gt;Incubation&lt;/h2&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Example apps should be published in the documentation.&lt;/p&gt;
&lt;p&gt;See how it is done in taskflow:&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://raw.githubusercontent.com/openstack/taskflow/master/doc/source/examples.rst"&gt;https://raw.githubusercontent.com/openstack/taskflow/master/doc/source/examples.rst&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This gets converted into:&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="http://docs.openstack.org/developer/taskflow/examples.html"&gt;http://docs.openstack.org/developer/taskflow/examples.html&lt;/a&gt;&lt;/p&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;oslo.*&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, 11 Sep 2017 00:00:00 </pubDate></item><item><title>Add Scope to Policy</title><link>https://specs.openstack.org/openstack/oslo-specs/specs/queens/include-scope-in-policy.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/oslo?searchtext=add-scope-to-policy"&gt;https://blueprints.launchpad.net/oslo?searchtext=add-scope-to-policy&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This specification details the benefits and outlines the work required to
extend oslo.policy to include a scope attribute.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;There are several initiatives underway to make consuming and understanding role
based access control (RBAC) easier for developers and deployers.&lt;/p&gt;
&lt;p&gt;The first is a community-wide &lt;a class="reference external" href="https://governance.openstack.org/tc/goals/queens/policy-in-code.html"&gt;goal&lt;/a&gt; to
register all policies into code and treat them like we we treat configuration.
This has numerous benefits for deployers and eases maintenance, especially
upgrades.&lt;/p&gt;
&lt;p&gt;The second is the ability to introduce a scope that fits naturally with
system-level policies or operations. The main idea here is that today
OpenStack’s Identity service allows users to get authorization on the domain
and project levels.  This makes a lot of sense when dealing with APIs that act
on resources owned by projects or domains. When dealing with operations above
project scope (e.g. modifying endpoints or listing hypervisors), it gets
harder to repurpose project or even domain scope for these actions. This
usually leads to end-user and deployer confusion. In addition to confusion, it
makes it really hard for operators to properly isolate project operations from
system operations (see &lt;a class="reference external" href="https://bugs.launchpad.net/keystone/+bug/968696"&gt;bug 968696&lt;/a&gt;).
As a result, there is work to introduce elevated scopes in OpenStack that make
the solution to the problem a little easier to understand and implement. For
more information on the actual approach, please see the related Identity
specifications:&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/462733/"&gt;A roadmap for improving security through policy&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/464763/"&gt;Specification for system-level scope&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If the above approaches are accepted, documenting the scope of each operation
in a project will be required. We can leverage the oslo.policy library to do
this since the community already leans on the library to document and register
default policies in code.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;As an operator, I need to understand at which level an operation is applied.&lt;/p&gt;
&lt;p&gt;As a developer, I want to enforce the scope for a specific operation through
code.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;The oslo.policy library currently has a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;DocumentedRuleDefault&lt;/span&gt;&lt;/code&gt; object that
is used to register policy in code and document it. We can extend this object
to support an additional attribute that denotes the scope of the operation.
Consider the following two examples:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;oslo_policy&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;policy&lt;/span&gt;

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

&lt;span class="n"&gt;policy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DocumentedRuleDefault&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;SERVERS&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="s1"&gt;'create'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;check_str&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;RULE_ADMIN_OR_OWNER&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'Create a server.'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;operations&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;'method'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'POST'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
         &lt;span class="s1"&gt;'path'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'/servers'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

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


&lt;span class="n"&gt;policy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DocumentedRuleDefault&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;base&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="s1"&gt;'create_user'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;check_str&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RULE_ADMIN_REQUIRED&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'Create a user.'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;operations&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;'method'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'POST'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
         &lt;span class="s1"&gt;'path'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'/v3/users'&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;Both rules are descriptive in what they do, but they don’t include the scope at
which they are intended to operate. Instances must belong to a project and user
can exist globally or within a specific domain. The following representations
are better because they are easier to understand and they help enforce
necessary scope during policy enforcement:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;oslo_policy&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;policy&lt;/span&gt;

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

&lt;span class="n"&gt;policy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DocumentedRuleDefault&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;SERVERS&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="s1"&gt;'create'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;scope_type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'project'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="n"&gt;check_str&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;RULE_ADMIN_OR_OWNER&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'Create a server.'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;operations&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;'method'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'POST'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
         &lt;span class="s1"&gt;'path'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'/servers'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

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


&lt;span class="n"&gt;policy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DocumentedRuleDefault&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;base&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="s1"&gt;'create_user'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;scope_type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'system'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'project'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="n"&gt;check_str&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RULE_ADMIN_REQUIRED&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'Create a user.'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;operations&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;'method'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'POST'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
         &lt;span class="s1"&gt;'path'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'/v3/users'&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 &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;scope_type&lt;/span&gt;&lt;/code&gt; attribute of policy can then be generated in sample policy
files with the existing &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;description&lt;/span&gt;&lt;/code&gt; making it even more helpful for
deployers that need to understand policy. It can also be available during the
policy enforcement of an operation at runtime. This makes it easier for
oslo.policy enforcement to ensure the operation being performed matches the
scope of the authorization context of the token. For example, comparing the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;scope_type&lt;/span&gt;&lt;/code&gt; of the policy operation against the role on the token’s scope
should help solve &lt;a class="reference external" href="https://bugs.launchpad.net/keystone/+bug/968696"&gt;admin-ness issues&lt;/a&gt;
across OpenStack.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;We can document the scope of operations outside of the project, but doing it
in-code with policy registration makes the approach less error-prone.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="impact-on-existing-apis"&gt;
&lt;h3&gt;Impact on Existing APIs&lt;/h3&gt;
&lt;p&gt;This will make the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;DocumentedRuleDefault&lt;/span&gt;&lt;/code&gt; object more useful in documenting
and evaluating policy. The changes described here are additive only and should
not impact existing functionality of the object.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;Directly, there are no security implications of this. Down the road, after
projects start using the attribute to evaluate policy, security will improve.
See the previously linked &lt;a class="reference external" href="https://review.openstack.org/#/c/462733/"&gt;Identity specification&lt;/a&gt; for details.&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="configuration-impact"&gt;
&lt;h3&gt;Configuration 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="testing-impact"&gt;
&lt;h3&gt;Testing Impact&lt;/h3&gt;
&lt;p&gt;We should test that scope is actually advertised and set on policies. We should
also loop-in the &lt;a class="reference external" href="https://docs.openstack.org/patrole/latest/"&gt;Patrole team&lt;/a&gt;
to see how this can improve testing of RBAC across 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;Lance Bragstad &amp;lt;&lt;a class="reference external" href="mailto:lbragstad%40gmail.com"&gt;lbragstad&lt;span&gt;@&lt;/span&gt;gmail&lt;span&gt;.&lt;/span&gt;com&lt;/a&gt;&amp;gt; lbragstad&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="milestones"&gt;
&lt;h3&gt;Milestones&lt;/h3&gt;
&lt;p&gt;Target Milestone for completion: queens-1&lt;/p&gt;
&lt;p&gt;Making this available early in the Queens release will allow projects to supply
scope documentation through automated docs.&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;Extend the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;DocumentedRuleDefault&lt;/span&gt;&lt;/code&gt; object to support a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;scope&lt;/span&gt;&lt;/code&gt; attribute&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;This functionality will need extensive documentation and usage guides
describing how it improves policy documentation and evaluation.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;Projects must move policy into code and document it before associating scope to
specific policies. Keystone will also need to provide a way for users to get
system-scoped tokens. After that, projects can start enforcing policy scope by
comparing it to the token scope, but most of that will be handled automatically
by oslo.policy’s &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Enforcer&lt;/span&gt;&lt;/code&gt; object.&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;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This work is licensed under a Creative Commons Attribution 3.0
Unported License.
&lt;a class="reference external" href="http://creativecommons.org/licenses/by/3.0/legalcode"&gt;http://creativecommons.org/licenses/by/3.0/legalcode&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
</description><pubDate>Fri, 01 Sep 2017 00:00:00 </pubDate></item><item><title>Policy Deprecation</title><link>https://specs.openstack.org/openstack/oslo-specs/specs/queens/policy-deprecation.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/oslo?searchtext=policy-deprecation"&gt;https://blueprints.launchpad.net/oslo?searchtext=policy-deprecation&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Several OpenStack projects have moved their policies into code and treat them
like configuration. This has numerous benefits for both developers and
operators. Moving policy into code and documenting it is targeted as a
community-wide &lt;a class="reference external" href="https://governance.openstack.org/tc/goals/queens/policy-in-code.html"&gt;goal&lt;/a&gt; for
the Queens release.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Policy management in OpenStack has always been a source of operator and
developer pain. It’s hard for operators to know what policies were changed or
added across releases without manually diffing policy files. Developers are
unable to programmatically communicate changes to policy files for their users.&lt;/p&gt;
&lt;p&gt;Now that projects will be moving policies into code, we have the opportunity to
use oslo.policy to advertise deprecations and future removal of policies. This
gives developers a programmatic way to make much needed changes to policy and
communicate those changes to operators in a way they already know how to
consume. This is consistent with how we deprecate other things in OpenStack,
like configuration options.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;The following list describes the cases that need to be covered by the
deprecation functionality in oslo.policy:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Changing the semantics of a policy in a backwards incompatible way&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Renaming a policy&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Removal of a policy in a backwards incompatible way but with a transition
plan&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These can be explained further in actual use cases and examples:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;As a developer, I need to be able to change the default role or rule for a
policy using oslo.policy&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As a developer, I need to be able to rename a policy using oslo.policy&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As an operator, I need to know if a policy’s default role or rule is
changing so I can either copy-paste the old policy into my policy file or
create the role required by the new default&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As an operator, I need to know if a policy that I’m overriding is going to
be renamed or removed so that APIs in my deployment aren’t accidentally
unprotected or exposed in an insecure way&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;section id="example-1"&gt;
&lt;h4&gt;Example 1&lt;/h4&gt;
&lt;p&gt;The policy, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;"foo:create_bar":&lt;/span&gt; &lt;span class="pre"&gt;"role:fizz"&lt;/span&gt;&lt;/code&gt;, needs to change its policy value
to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;"role:bang"&lt;/span&gt;&lt;/code&gt;. An operator can do one of two things when upgrading. The
first option is to copy-paste the original policy into the policy file and
override the new default for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;foo:create_bar&lt;/span&gt;&lt;/code&gt;. The second option is for the
operator to create role &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;bang&lt;/span&gt;&lt;/code&gt; in their deployment so that the new default is
useable after the upgrade. The same process can be applied to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;rule&lt;/span&gt;&lt;/code&gt;
evaluations in-place of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;role&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="example-2"&gt;
&lt;h4&gt;Example 2&lt;/h4&gt;
&lt;p&gt;The policy, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;"foo:post_bar":&lt;/span&gt; &lt;span class="pre"&gt;"role:fizz"&lt;/span&gt;&lt;/code&gt;, should be replaced with
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;"foo:create_bar":&lt;/span&gt; &lt;span class="pre"&gt;"role:fizz"&lt;/span&gt;&lt;/code&gt; to be consistent with other policies used by
the service. So long as the role or rule check remains consistent there should
be no operator impact to operators using the default. The newer version of the
service will start using &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;create_bar&lt;/span&gt;&lt;/code&gt; for policy enforcement, phasing out the
usage of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;post_bar&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;If an operator is overriding the policy for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;post_bar&lt;/span&gt;&lt;/code&gt;, a message should be
logged saying that &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;post_bar&lt;/span&gt;&lt;/code&gt; is no longer going to be an enforcible policy
and that &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;create_bar&lt;/span&gt;&lt;/code&gt; should be used instead. This will give operators a
chance to fix their policy before &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;post_bar&lt;/span&gt;&lt;/code&gt; goes away completely. This
ensures that operators don’t accidentally expose &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;create_bar&lt;/span&gt;&lt;/code&gt; if they are
using a custom policy to protect it.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="example-3"&gt;
&lt;h4&gt;Example 3&lt;/h4&gt;
&lt;p&gt;The policy, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;"foo:bar":&lt;/span&gt; &lt;span class="pre"&gt;"role:bazz"&lt;/span&gt;&lt;/code&gt;, should be broken into:&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;"foo:get_bar":&lt;/span&gt; &lt;span class="pre"&gt;"role:bazz"&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;"foo:list_bars":&lt;/span&gt; &lt;span class="pre"&gt;"role:bazz"&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;"foo:create_bar":&lt;/span&gt; &lt;span class="pre"&gt;"role:bazz"&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;"foo:update_bar":&lt;/span&gt; &lt;span class="pre"&gt;"role:bazz"&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;"foo:delete_bar":&lt;/span&gt; &lt;span class="pre"&gt;"role:bazz"&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This gives developers or operators the ability to associate different roles to
different operations of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;bar&lt;/span&gt;&lt;/code&gt; instances, instead of all operations on &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;bar&lt;/span&gt;&lt;/code&gt;
requiring the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;bazz&lt;/span&gt;&lt;/code&gt; role.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;The oslo.policy library exposes a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;DocumentedRuleDefault&lt;/span&gt;&lt;/code&gt; object that
policies are registered as. We can extend this object to support an optional
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;deprecated&lt;/span&gt;&lt;/code&gt; attribute, or set of attributes that communicate information
about the deprecation. This won’t require projects to change their current
policy definitions or implementations. The following are the attributes that
would be useful to expose to projects so they can improve policy:&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;deprecated_for_removal&lt;/span&gt;&lt;/code&gt;: This is a boolean values that denotes if the
policy is deprecated or not&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;deprecated_reason&lt;/span&gt;&lt;/code&gt;: This is a string containing justification for the
removal or deprecation of the policy&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;deprecated_since&lt;/span&gt;&lt;/code&gt;: The release in which the policy was officially
deprecated&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These additional attributes should be very similar, if not the same as the
deprecated functionality of oslo.config. This change will likely be limited to
the oslo.policy library, specifically the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;DocumentedRuleDefault&lt;/span&gt;&lt;/code&gt; object.&lt;/p&gt;
&lt;p&gt;Policies that are flagged for deprecation will emit log warnings similar to
using a deprecated configuration option. Likewise, deprecated policies will be
marked as such in generated sample policy files.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Developers can continue to rely on release notes and mailing lists to
communicate policy changes to operators. This is considered suboptimal since it
is prone to human error, lacks consistency across projects, and isn’t
programmable. As a result, policies are rarely changed from their original
definitions, which is very problematic since policies never evolve with the
project.&lt;/p&gt;
&lt;p&gt;This is really the only alternative we have today, but since it doesn’t really
help improve policy it could be argued as not an alternative at all.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="impact-on-existing-apis"&gt;
&lt;h3&gt;Impact on Existing APIs&lt;/h3&gt;
&lt;p&gt;The API for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;DocumentedRuleDefault&lt;/span&gt;&lt;/code&gt; or &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;RuleDefault&lt;/span&gt;&lt;/code&gt; will be improved to
support communicating deprecated policies.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;Projects consuming this change can use it to improve security by offering more
secure default rules.&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="configuration-impact"&gt;
&lt;h3&gt;Configuration Impact&lt;/h3&gt;
&lt;p&gt;No new configuration options should be required to consume or leverage this
functionality. This should be available for projects to use once they have a
version of oslo.policy that supports deprecated information in
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;DocumentedRuleDefault&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer Impact&lt;/h3&gt;
&lt;p&gt;Developers will not be impacted unless they are looking to improve or modify
policies for their project. If that is the case, they can use the new
functionality to describe the reason for the deprecation, when it will be
removed, and what is replacing it.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing-impact"&gt;
&lt;h3&gt;Testing Impact&lt;/h3&gt;
&lt;p&gt;We need to ensure that deprecated policies emit some sort of warning when they
are invoked. This can likely be done in oslo.policy’s tests, but it can also be
done in project consuming the tests as well. One thing to discuss might be
adding a criteria that requires a unit test for deprecating a policy.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Lance Bragstad &amp;lt;&lt;a class="reference external" href="mailto:lbragstad%40gmail.com"&gt;lbragstad&lt;span&gt;@&lt;/span&gt;gmail&lt;span&gt;.&lt;/span&gt;com&lt;/a&gt;&amp;gt; lbragstad&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="milestones"&gt;
&lt;h3&gt;Milestones&lt;/h3&gt;
&lt;p&gt;Target Milestone for completion: queens-1&lt;/p&gt;
&lt;p&gt;Making this available early in the Queens release will allow projects to
deprecate policies before Queens is released.&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 deprecated functionality in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;RuleDefault&lt;/span&gt;&lt;/code&gt; or
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;DocumentedRuleDefault&lt;/span&gt;&lt;/code&gt; objects&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;It is likely that many projects will use this functionality to deprecate and
improve their existing policies. The usage of these deprecated flags should be
well documented.&lt;/p&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="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This work is licensed under a Creative Commons Attribution 3.0
Unported License.
&lt;a class="reference external" href="http://creativecommons.org/licenses/by/3.0/legalcode"&gt;http://creativecommons.org/licenses/by/3.0/legalcode&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
</description><pubDate>Fri, 01 Sep 2017 00:00:00 </pubDate></item><item><title>Protecting Plaintext Secrets</title><link>https://specs.openstack.org/openstack/oslo-specs/specs/stein/secret-management-store.html</link><description>

&lt;p&gt;bp protecting plaintext password &lt;a class="reference external" href="https://blueprints.launchpad.net/oslo.config/+spec/protect-plaintext-passwords"&gt;https://blueprints.launchpad.net/oslo.config/+spec/protect-plaintext-passwords&lt;/a&gt;&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Current OpenStack services require plaintext passwords and credentials for
various access, e.g. database, keystoneauth, etc.&lt;/p&gt;
&lt;p&gt;Even with proper file permissions set on these files, often time during
troubleshooting sessions, these configuration files are sent via emails
without the passwords properly redacted.&lt;/p&gt;
&lt;p&gt;Also, the ability to change passwords across multiple nodes are
heavily relying on the deployment tools of choice (ansible, fuel, etc.)&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, in order to properly secure the secrets in those configuration
files, we should implement an oslo.config driver as described in the oslo spec
&lt;a class="reference external" href="http://specs.openstack.org/openstack/oslo-specs/specs/queens/oslo-config-drivers.html"&gt;http://specs.openstack.org/openstack/oslo-specs/specs/queens/oslo-config-drivers.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Phase 0:&lt;/p&gt;
&lt;p&gt;Using HTTP and HTTPS urls as a reference to secrets:&lt;/p&gt;
&lt;p&gt;As a basic but useful solution, we proposed using an external URL pointing to
an HTTP or HTTPS url to access those secrets.&lt;/p&gt;
&lt;p&gt;Note: This Phase 0 was merged on oslo.config in the Rocky release.&lt;/p&gt;
&lt;p&gt;Phase 1:&lt;/p&gt;
&lt;p&gt;Currently, on OpenStack, we have a Generic Key Manager interface called
Castellan, which means that Castellan works on the principle of providing an
abstracted key manager based on your configuration. In this manner, several
different management services can be supported through a single interface.
To integrate Castellan with oslo.config will have a Castellan implementation
to oslo.config driver defined before.&lt;/p&gt;
&lt;p&gt;After that, we will be able to use a Castellan reference for those secrets
and store it using a proper key store backend. Currently, Castellan supports
Barbican and also Hashicorp Vault as backends options. For this scenario,
we will be looking for using Vault as a chosen solution, since we can point
to an external Vault server with no internal dependencies to other OpenStack
services, also for authentication and validation methods, since Barbican needs
Keystone tokens as authentication method also we need to store the Barbican
and Keystone secrets present in their configuration files.&lt;/p&gt;
&lt;p&gt;Phase 2:&lt;/p&gt;
&lt;p&gt;Finally, we should use some deployment tool like Ansible to create those
secrets and store them properly on Vault following the Castellan interface and
inject those secrets in the configuration files. So, later, we will be able to
restore it properly in the configuration files, with any necessary manual
steps.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="consuming-projects"&gt;
&lt;h2&gt;Consuming projects&lt;/h2&gt;
&lt;p&gt;Any OpenStack service which have some secrets in their configuration files,
such as Glance, Nova, Keystone, Mistral and so on.&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;Encrypt the configuration files:&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Which requires decryption keys and makes difficult to update configurations&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Configuration Management DB (CMDB):&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Need to secure database connection credentials&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Other types of providers can be included as a key store solution since those
providers implements the Castellan interface, such as Vault or a KMIP device&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;This change wants to make OpenStack services passwords and credentials
management more secure, removing the plaintext passwords in the OpenStack
services configuration files by using a secure and encrypted alternative
following the Castellan interface for secrets management.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="configuration-impact"&gt;
&lt;h3&gt;Configuration Impact&lt;/h3&gt;
&lt;p&gt;For the first phase of this work, the operator can update their configuration
files to point to the password reference and no more using plaintext
passwords. Although, after the second phase with the Puppet and/or Ansible
that change will be made automatically by those tools.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;raildo&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;dhellmann
moguimar
spilla&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="milestones"&gt;
&lt;h3&gt;Milestones&lt;/h3&gt;
&lt;p&gt;We are targetting the Phase 0 for Rocky-3 and Phase 1 and Phase 2 for Stein.&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 oslo.config driver for URI&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Implement oslo.config driver for Castellan&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="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;We should document how to update the OpenStack Services
configuration file to use the proper password references
instead of the plaintext passwords.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;Oslo PTG discussion: &lt;a class="reference external" href="https://etherpad.openstack.org/p/oslo-ptg-queens"&gt;https://etherpad.openstack.org/p/oslo-ptg-queens&lt;/a&gt;
Meetings logs: &lt;a class="reference external" href="https://etherpad.openstack.org/p/oslo-config-plaintext-secrets"&gt;https://etherpad.openstack.org/p/oslo-config-plaintext-secrets&lt;/a&gt;
Phase 0 on Rocky Release: &lt;a class="reference external" href="https://docs.openstack.org/oslo.config/latest/reference/drivers.html"&gt;https://docs.openstack.org/oslo.config/latest/reference/drivers.html&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 work is licensed under a Creative Commons Attribution 3.0
Unported License.
&lt;a class="reference external" href="http://creativecommons.org/licenses/by/3.0/legalcode"&gt;http://creativecommons.org/licenses/by/3.0/legalcode&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
</description><pubDate>Wed, 14 Jun 2017 00:00:00 </pubDate></item><item><title>Global Request IDs</title><link>https://specs.openstack.org/openstack/oslo-specs/specs/pike/global-req-id.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/oslo?searchtext=global-req-id"&gt;https://blueprints.launchpad.net/oslo?searchtext=global-req-id&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Building a complex resource, like a boot instance, requires not only
touching a number of Nova processes, but also other services such as
Neutron, Glance, and possibly Cinder. When we make those service jumps
we currently generate a new request-id, which makes tracing those
flows quite manual.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;When a user creates a resource, such as a server, they are given a
request-id back. This is generated very early in the paste pipeline of
most services. It is eventually embedded into the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;context&lt;/span&gt;&lt;/code&gt;, which
is then used implicitly for logging all activities related to the
request. This works well for tracing requests inside of a single
service as it passes through its workers, but breaks down when an
operation spans multiple services. A common example of this is a
server build, which requires Nova to call out multiple times to
Neutron and Glance (and possibly other services) to create a server on
the network.&lt;/p&gt;
&lt;p&gt;It is extremely common for clouds to have an ELK (Elastic Search,
Logstash, Kibana) infrastructure that is consuming their logs. The
only way to query these flows is if there is a common identifier
across all relevant messages. A global request-id immediately makes
existing deployed tooling better for managing OpenStack.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;The high level solution is as follows (details on specific points
later):&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;accept an inbound X-OpenStack-Request-ID header on requests. Require
that it looks like a uuid to prevent injection issues. Set this to
the value of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;global_request_id&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Keep the auto generated existing request_id&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;update oslo.log to default also log &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;global_request_id&lt;/span&gt;&lt;/code&gt; when it is
in a context logging mode.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;section id="paste-pipelines"&gt;
&lt;h3&gt;Paste pipelines&lt;/h3&gt;
&lt;p&gt;The processing of incoming requests happens piecemeal through the set
of paste pipelines. These are mostly common between projects, but
there are enough local variation to highlight what this looks like for
the base IaaS services, which will be the initial targets of this spec.&lt;/p&gt;
&lt;section id="neutron"&gt;
&lt;h4&gt;Neutron &lt;a class="footnote-reference brackets" href="#f1" 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;/h4&gt;
&lt;div class="highlight-ini notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="k"&gt;[composite:neutronapi_v2_0]&lt;/span&gt;
&lt;span class="na"&gt;use&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;call:neutron.auth:pipeline_factory&lt;/span&gt;
&lt;span class="na"&gt;noauth&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;cors http_proxy_to_wsgi request_id catch_errors extensions neutronapiapp_v2_0&lt;/span&gt;
&lt;span class="na"&gt;keystone&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;cors http_proxy_to_wsgi request_id catch_errors authtoken keystonecontext extensions neutronapiapp_v2_0&lt;/span&gt;
&lt;span class="c1"&gt;#                                  ^                                 ^&lt;/span&gt;
&lt;span class="c1"&gt;# request_id generated here -------+                                 |&lt;/span&gt;
&lt;span class="c1"&gt;# context built here ------------------------------------------------+&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="glance"&gt;
&lt;h4&gt;Glance &lt;a class="footnote-reference brackets" href="#f2" 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;/h4&gt;
&lt;div class="highlight-ini notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="c1"&gt;# Use this pipeline for keystone auth&lt;/span&gt;
&lt;span class="k"&gt;[pipeline:glance-api-keystone]&lt;/span&gt;
&lt;span class="na"&gt;pipeline&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;cors healthcheck http_proxy_to_wsgi versionnegotiation osprofiler authtoken context  rootapp&lt;/span&gt;
&lt;span class="c1"&gt;#                                                                                      ^&lt;/span&gt;
&lt;span class="c1"&gt;# request_id &amp;amp; context built here -----------------------------------------------------+&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="cinder"&gt;
&lt;h4&gt;Cinder &lt;a class="footnote-reference brackets" href="#f3" 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;/h4&gt;
&lt;div class="highlight-ini notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="k"&gt;[composite:openstack_volume_api_v3]&lt;/span&gt;
&lt;span class="na"&gt;use&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;call:cinder.api.middleware.auth:pipeline_factory&lt;/span&gt;
&lt;span class="na"&gt;noauth&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;cors http_proxy_to_wsgi request_id faultwrap sizelimit osprofiler noauth apiv3&lt;/span&gt;
&lt;span class="na"&gt;keystone&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;cors http_proxy_to_wsgi request_id faultwrap sizelimit osprofiler authtoken keystonecontext apiv3&lt;/span&gt;
&lt;span class="c1"&gt;#                                  ^                                                   ^&lt;/span&gt;
&lt;span class="c1"&gt;# request_id generated here -------+                                                   |&lt;/span&gt;
&lt;span class="c1"&gt;# context built here ------------------------------------------------------------------+&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="nova"&gt;
&lt;h4&gt;Nova &lt;a class="footnote-reference brackets" href="#f4" 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;/h4&gt;
&lt;div class="highlight-ini notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="k"&gt;[composite:openstack_compute_api_v21]&lt;/span&gt;
&lt;span class="na"&gt;use&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;call:nova.api.auth:pipeline_factory_v21&lt;/span&gt;
&lt;span class="na"&gt;noauth2&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;cors http_proxy_to_wsgi compute_req_id faultwrap sizelimit osprofiler noauth2 osapi_compute_app_v21&lt;/span&gt;
&lt;span class="na"&gt;keystone&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;cors http_proxy_to_wsgi compute_req_id faultwrap sizelimit osprofiler authtoken keystonecontext osapi_compute_app_v21&lt;/span&gt;
&lt;span class="c1"&gt;#                                  ^                                                       ^&lt;/span&gt;
&lt;span class="c1"&gt;# request_id generated here -------+                                                       |&lt;/span&gt;
&lt;span class="c1"&gt;# context built here ----------------------------------------------------------------------+&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="oslo-middleware-request-id"&gt;
&lt;h3&gt;oslo.middleware.request_id&lt;/h3&gt;
&lt;p&gt;In nearly all services the request_id generation happens very early,
well before any local logic. The middleware sets an
X-OpenStack-Request-ID response header, as well as variables in the
environment that are later consumed by oslo.context.&lt;/p&gt;
&lt;p&gt;We would accept an inbound X-OpenStack-Request-ID, and validate that
it looked like &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;req-$UUID&lt;/span&gt;&lt;/code&gt; before accepting it as the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;global_request_id&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The returned X-OpenStack-Request-ID would be the existing
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;request_id&lt;/span&gt;&lt;/code&gt;. This is like the parent process getting the child
process id on a fork() call.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="oslo-context-from-environ"&gt;
&lt;h3&gt;oslo.context from_environ&lt;/h3&gt;
&lt;p&gt;Fortunately for us most projects now use the oslo.context
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;from_environ&lt;/span&gt;&lt;/code&gt; constructor. This means that we can add content to
the context, or adjust the context, without needing to change every
project. For instance in Glance the context constructor looks like
&lt;a class="footnote-reference brackets" href="#f5" id="id5" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;5&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;div class="highlight-python notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="s1"&gt;'owner_is_tenant'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;CONF&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;owner_is_tenant&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="s1"&gt;'service_catalog'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;service_catalog&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="s1"&gt;'policy_enforcer'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;policy_enforcer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="s1"&gt;'request_id'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;request_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;ctxt&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;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RequestContext&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;from_environ&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&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;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;As all logging happens &lt;em&gt;after&lt;/em&gt; the context is built. All required
parts of the context will be there before logging starts.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="oslo-log"&gt;
&lt;h3&gt;oslo.log&lt;/h3&gt;
&lt;p&gt;oslo.log defaults should include &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;global_request_id&lt;/span&gt;&lt;/code&gt; during context
logging. This is something which can be done late, as users can always
override there context logging string format.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="projects-and-clients"&gt;
&lt;h3&gt;projects and clients&lt;/h3&gt;
&lt;p&gt;With the infrastructure above implemented it will be a small change to
python clients to save and emit the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;global_request_id&lt;/span&gt;&lt;/code&gt; when
created. For instance, Nova calling Neutron, during the get_client
call &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;context.request_id&lt;/span&gt;&lt;/code&gt; would be stored in the client. &lt;a class="footnote-reference brackets" href="#f6" 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;div class="highlight-python notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;_get_available_networks&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;project_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                            &lt;span class="n"&gt;net_ids&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;neutron&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                            &lt;span class="n"&gt;auto_allocate&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="sd"&gt;"""Return a network list available for the tenant.&lt;/span&gt;
&lt;span class="sd"&gt;    The list contains networks owned by the tenant and public networks.&lt;/span&gt;
&lt;span class="sd"&gt;    If net_ids specified, it searches networks with requested IDs only.&lt;/span&gt;
&lt;span class="sd"&gt;    """&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;neutron&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;neutron&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;get_client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;net_ids&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# If user has specified to attach instance only to specific&lt;/span&gt;
        &lt;span class="c1"&gt;# networks then only add these to **search_opts. This search will&lt;/span&gt;
        &lt;span class="c1"&gt;# also include 'shared' networks.&lt;/span&gt;
        &lt;span class="n"&gt;search_opts&lt;/span&gt; &lt;span class="o"&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="n"&gt;net_ids&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;nets&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;neutron&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;list_networks&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;search_opts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'networks'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[])&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# (1) Retrieve non-public network list owned by the tenant.&lt;/span&gt;
        &lt;span class="n"&gt;search_opts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;'tenant_id'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;project_id&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="kc"&gt;False&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;auto_allocate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="c1"&gt;# The auto-allocated-topology extension may create complex&lt;/span&gt;
            &lt;span class="c1"&gt;# network topologies and it does so in a non-transactional&lt;/span&gt;
            &lt;span class="c1"&gt;# fashion. Therefore API users may be exposed to resources that&lt;/span&gt;
            &lt;span class="c1"&gt;# are transient or partially built. A client should use&lt;/span&gt;
            &lt;span class="c1"&gt;# resources that are meant to be ready and this can be done by&lt;/span&gt;
            &lt;span class="c1"&gt;# checking their admin_state_up flag.&lt;/span&gt;
            &lt;span class="n"&gt;search_opts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'admin_state_up'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt;
        &lt;span class="n"&gt;nets&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;neutron&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;list_networks&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;search_opts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'networks'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[])&lt;/span&gt;
        &lt;span class="c1"&gt;# (2) Retrieve public network list.&lt;/span&gt;
        &lt;span class="n"&gt;search_opts&lt;/span&gt; &lt;span class="o"&gt;=&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="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;nets&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;neutron&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;list_networks&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;search_opts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'networks'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[])&lt;/span&gt;

    &lt;span class="n"&gt;_ensure_requested_network_ordering&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;x&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="n"&gt;nets&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;net_ids&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;nets&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;There are some usage patterns where a client is built and kept for
long running operations. In these cases we’d want to change the
model to assume that clients are ephemeral, and should be discarded
at the end of their flows.&lt;/p&gt;
&lt;p&gt;This will also help tracking non user initiated tasks such as
periodic jobs that touch other services for information refresh.&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;section id="log-in-the-caller"&gt;
&lt;h4&gt;Log in the Caller&lt;/h4&gt;
&lt;p&gt;There was a previous OpenStack cross project spec to completely handle
this in the caller - &lt;a class="reference external" href="https://review.openstack.org/#/c/156508/"&gt;https://review.openstack.org/#/c/156508/&lt;/a&gt;. That
was merged over 2 years ago, but has yet to gain traction.&lt;/p&gt;
&lt;p&gt;It had a number of disadvantages. It turns out the client code is far
less standardized here, so fixing every client was substantial
work.&lt;/p&gt;
&lt;p&gt;It also requires some standard convention for writing these things out
to logs on the caller side that is consistent between all services.&lt;/p&gt;
&lt;p&gt;It also &lt;strong&gt;does not&lt;/strong&gt; allow people to use Elastic Search to trace their
logs (which all large sites have running). A custom piece of analysis
tooling would need to be built.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="verify-trust-in-callers"&gt;
&lt;h4&gt;Verify trust in callers&lt;/h4&gt;
&lt;p&gt;A long time ago, in a galaxy far far away, in a summit room I was not
in, I was told there was a concern about clients flooding this
field. There has been no documented attack that seems feasable here if
we strictly validate the inbound data.&lt;/p&gt;
&lt;p&gt;There is a way we could use Service roles to validate trust here, but
without a compelling case for why that is needed, we should do the
simpler thing.&lt;/p&gt;
&lt;p&gt;For reference Glance already accepts a user provided request-id of 64
characters or less. This has existed there for a long time, with no
reports as to yet for abuse. We could consider dropping the last
constraint and not doing role validation.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="swift-multipart-transaction-id"&gt;
&lt;h4&gt;Swift multipart transaction id&lt;/h4&gt;
&lt;p&gt;Swift has a related approach where their transaction id, which is a
multipart id that includes a piece generated by the server on inbound
request, a timestamp piece, a fixed server piece (for tracking
multiple clusters), and a user provided piece. Swift is not currently
using any of the above oslo infrastructure, and targets syslog as
their primary logging mechanism.&lt;/p&gt;
&lt;p&gt;While there are interesting bits in this approach, it’s a less
straight forward chunk of work to transition to, given the oslo
components. Also, oslo.log has many structured log back ends (like
json stream, fluentd, and systemd journal) where we really would want
the global and local as separate fields so there is no heuristic
parsing required.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="impact-on-existing-apis"&gt;
&lt;h3&gt;Impact on Existing APIs&lt;/h3&gt;
&lt;p&gt;oslo.middleware request_id contract will change so that it accepts an
inbound header, and sets a second env variable. Both are backwards
compatible.&lt;/p&gt;
&lt;p&gt;oslo.context will accept a new local_request_id. This requires
plumbing local_request_id into all calls that take request_id. This
looks fully backwards compatible.&lt;/p&gt;
&lt;p&gt;oslo.log will need to be adjusted to support logging both
request_ids. It should probably be enabled to do that by default,
though log_context string is a user configured variable, so they can
set whatever site local format works for them. An upgrade release note
would be appropriate when this happens.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;There previously was a concern about trusting request ids from the
user. It is an inbound piece of user data, so care should be taken.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Ensure it is not allowed to be so big as to create a DOS vector
(size validation)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Ensure that it is not a possible code injection vector (strict
validation)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These items can be handled with strict validation of the content that
it looks like a valid uuid.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;Minimal. This is a few extra lines of instruction in existing through
paths. No expensive activity is done in this new code.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="configuration-impact"&gt;
&lt;h3&gt;Configuration Impact&lt;/h3&gt;
&lt;p&gt;The only configuration impact will be on the oslo.log context string.&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 now have much easier tracing of build requests in
their devstack environments!&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing-impact"&gt;
&lt;h3&gt;Testing Impact&lt;/h3&gt;
&lt;p&gt;Unit tests provided with various oslo components.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;sdague&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;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;Could definitely use help to get this through the gauntlet, there
are lots of little patches here to get right.&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="milestones"&gt;
&lt;h3&gt;Milestones&lt;/h3&gt;
&lt;p&gt;Target Milestone for completion: TBD&lt;/p&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;p&gt;TBD&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;TBD - but presumably some updates to operators guide on tracing across
services.&lt;/p&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="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;aside class="footnote-list brackets"&gt;
&lt;aside class="footnote brackets" id="f1" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id1"&gt;1&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://github.com/openstack/neutron/blob/5691f29e8fd1212bb22b1a48d32dbbddf7e0587d/etc/api-paste.ini#L6-L9"&gt;https://github.com/openstack/neutron/blob/5691f29e8fd1212bb22b1a48d32dbbddf7e0587d/etc/api-paste.ini#L6-L9&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="f2" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id2"&gt;2&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://github.com/openstack/glance/blob/5caf1c739e190338e87be8bcd880cb88b0920299/etc/glance-api-paste.ini#L13-L15"&gt;https://github.com/openstack/glance/blob/5caf1c739e190338e87be8bcd880cb88b0920299/etc/glance-api-paste.ini#L13-L15&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="f3" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id3"&gt;3&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://github.com/openstack/cinder/blob/81ece6a9f2ac9b4ff3efe304bab847006f8b0aef/etc/cinder/api-paste.ini#L24-L28"&gt;https://github.com/openstack/cinder/blob/81ece6a9f2ac9b4ff3efe304bab847006f8b0aef/etc/cinder/api-paste.ini#L24-L28&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="f4" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id4"&gt;4&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://github.com/openstack/nova/blob/c2c6960e374351b3ce1b43a564b57e14b54c4877/etc/nova/api-paste.ini#L29-L32"&gt;https://github.com/openstack/nova/blob/c2c6960e374351b3ce1b43a564b57e14b54c4877/etc/nova/api-paste.ini#L29-L32&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="f5" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id5"&gt;5&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://github.com/openstack/glance/blob/70d51c7c5c09b070588041a65905eba789ae871b/glance/api/middleware/context.py#L179-L187"&gt;https://github.com/openstack/glance/blob/70d51c7c5c09b070588041a65905eba789ae871b/glance/api/middleware/context.py#L179-L187&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="f6" 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://github.com/openstack/nova/blob/c2c6960e374351b3ce1b43a564b57e14b54c4877/nova/network/neutronv2/api.py#L317-L354"&gt;https://github.com/openstack/nova/blob/c2c6960e374351b3ce1b43a564b57e14b54c4877/nova/network/neutronv2/api.py#L317-L354&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;/aside&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This work is licensed under a Creative Commons Attribution 3.0
Unported License.
&lt;a class="reference external" href="http://creativecommons.org/licenses/by/3.0/legalcode"&gt;http://creativecommons.org/licenses/by/3.0/legalcode&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
</description><pubDate>Mon, 15 May 2017 00:00:00 </pubDate></item><item><title>Improving Logging to Aid in Debugging</title><link>https://specs.openstack.org/openstack/oslo-specs/specs/pike/improving-logging-debugging.html</link><description>

&lt;p&gt;Operators have been asking for mnemonic identifiers for log messages
since the start of the Folsom cycle in 2012. This proposal tries to
provide the features of those identifiers, without having to update
every log message and string being passed through the logging modules.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Many commercial (closed-source) enterprise applications, and even some
open source projects, include unique identifiers for every user and
log message. The IDs are used as reference points in documentation and
bug reports, either instead of or in addition to the text of the log
message. Message IDs also mean that online searches can be language
independent, to some degree, although translating the results of a
search may still require someone to be able to read English if there
are no results in their primary language.&lt;/p&gt;
&lt;p&gt;As an open source project with a widely distributed contributor base
and multi-service architecture, adding message IDs to OpenStack
presents some unique challenges not faced in other environments.  A
central repository of unique IDs will be difficult to maintain.
Adding IDs to every log message in anticipation of documentation to be
written later will produce a lot of patches with little value,
triggering reviews, test jobs, and rebases of other patches.
Requiring IDs for each log call, or for only some log levels, will
require incompatible changes to our logging library APIs.  This
proposal tries to address all of those issues in a way that will allow
us to deliver the benefit of those message IDs without the expense of
introducing unique IDs to all logging calls.&lt;/p&gt;
&lt;p&gt;The benefits of unique IDs for log messages have been given as&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;A unique ID for an error can act as a mnemonic, when discussing the
error with another operator or when a user reports an error through
support channels.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A unique ID for a message helps locate that message in the source
for the program, making it easier to troubleshoot and debug by
being able to jump directly to the source code.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Although unique message IDs are useful, maintaining the list would
grow tedious. The new rules reviewers would need to learn in order to
manage a segmented ID value correctly would lead to frustration and
nit picking on reviews. Adding the IDs in the first place would take
manual work, and keeping them correctly organized over time would
increase our maintenance burden. The two primary features leading to
the request for message IDs are both available in other forms with
minimal source code changes, so this proposal describes how to achieve
the goals in the easiest way possible.&lt;/p&gt;
&lt;section id="message-locations"&gt;
&lt;h3&gt;Message Locations&lt;/h3&gt;
&lt;p&gt;The location of a message (filename and line number) can be exposed
today in any version of OpenStack by adding the relevant fields to the
logging format configuration option. No source code changes are needed
at all. There are 3 different ways to expose the location, depending
on how much detail is desired.&lt;/p&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;&lt;p&gt;The form in use today is the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;%(name)s&lt;/span&gt;&lt;/code&gt; field, which introduces
the “logger name” into the log line. The standard practice in
OpenStack is to use the Python module name, accessible via the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;__name__&lt;/span&gt;&lt;/code&gt; variable, to get a logger object for each
file. Therefore in most cases, the logger name and module name will
match. For example, in nova/api/auth.py the line:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;   LOG = logging.getLogger(__name__)

causes the logger to be called ``nova.api.auth``.
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;%(filename)s&lt;/span&gt;&lt;/code&gt; field inserts the last part of the full file
name into the log line. For example, nova/api/auth.py produces
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;auth.py&lt;/span&gt;&lt;/code&gt;.  OpenStack contains quite a few modules with the same
base file name, so this version is not likely to be very useful for
debugging.&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;%(pathname)s&lt;/span&gt;&lt;/code&gt; field inserts the full name of the file into
the log line. For example nova/api/auth.py produces something like
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;/usr/local/lib/python2.7/site-packages/nova/api/auth.py&lt;/span&gt;&lt;/code&gt; (the
actual value depends on how the software is packaged and
installed).  These paths can be quite long, but for a site where
that level of detail is desired it is available.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The file name is only one part of the necessary information for
finding a log message.  The other is the line number. The
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;%(lineno)s&lt;/span&gt;&lt;/code&gt; field will insert the line number of the location of
the logging call that introduces a line to the log. For example, the
line:&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;LOG&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Neither X_USER_ID nor X_USER found in request"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;appears on line 102 of nova/api/auth.py, so &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;%(lineno)s&lt;/span&gt;&lt;/code&gt; would
insert &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;102&lt;/span&gt;&lt;/code&gt; into the log line.&lt;/p&gt;
&lt;p&gt;As stated above, the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;%(name)s&lt;/span&gt;&lt;/code&gt; field already appears in the default
format string set by oslo.log. The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;%(lineno)s&lt;/span&gt;&lt;/code&gt; field can be added
there easily.  This information can be added to the oslo.log
documentation to make it easier for users to find. Although this may
lead to operators running with non-default configurations, it is less
likely to break the logging pipelines in existing deployments. Over
time, as we see how useful the line numbers are, we can revisit this
approach.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="error-identifiers"&gt;
&lt;h3&gt;Error Identifiers&lt;/h3&gt;
&lt;p&gt;Most errors in Python programs are associated with an instance of a
class derived from Exception. These classes have message text,
frequently with the ability to insert dynamic values (such as the name
of a specific thing that has a problem). Python’s logging library
recognizes exception instances, and when a log message is emitted
while there is an active exception the exception can be included in
the output, producing a traceback.&lt;/p&gt;
&lt;p&gt;Exceptions are logged by calling the exception() method of the logger,
or by passing exception information to another method such as error()
or warning(). In all cases, the logging formatter is responsible for
taking the arguments given and producing the appropriate log output
line.&lt;/p&gt;
&lt;p&gt;Given the example logging call:&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;LOG&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exception&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'the exception log msg'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Today when an exception is logged, the output produced looks 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="mi"&gt;2017&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;24&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;54.823&lt;/span&gt; &lt;span class="mi"&gt;1108&lt;/span&gt; &lt;span class="n"&gt;ERROR&lt;/span&gt; &lt;span class="n"&gt;oslo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tester&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;24&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;the&lt;/span&gt; &lt;span class="n"&gt;exception&lt;/span&gt; &lt;span class="n"&gt;log&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;
&lt;span class="mi"&gt;2017&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;24&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;54.823&lt;/span&gt; &lt;span class="mi"&gt;1108&lt;/span&gt; &lt;span class="n"&gt;ERROR&lt;/span&gt; &lt;span class="n"&gt;oslo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tester&lt;/span&gt; &lt;span class="n"&gt;Traceback&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;most&lt;/span&gt; &lt;span class="n"&gt;recent&lt;/span&gt; &lt;span class="n"&gt;call&lt;/span&gt; &lt;span class="n"&gt;last&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="mi"&gt;2017&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;24&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;54.823&lt;/span&gt; &lt;span class="mi"&gt;1108&lt;/span&gt; &lt;span class="n"&gt;ERROR&lt;/span&gt; &lt;span class="n"&gt;oslo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tester&lt;/span&gt;   &lt;span class="n"&gt;File&lt;/span&gt; &lt;span class="s2"&gt;"./tester.py"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="mi"&gt;21&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;module&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="mi"&gt;2017&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;24&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;54.823&lt;/span&gt; &lt;span class="mi"&gt;1108&lt;/span&gt; &lt;span class="n"&gt;ERROR&lt;/span&gt; &lt;span class="n"&gt;oslo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tester&lt;/span&gt;     &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="ne"&gt;RuntimeError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'the error text'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mi"&gt;2017&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;24&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;54.823&lt;/span&gt; &lt;span class="mi"&gt;1108&lt;/span&gt; &lt;span class="n"&gt;ERROR&lt;/span&gt; &lt;span class="n"&gt;oslo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tester&lt;/span&gt; &lt;span class="ne"&gt;RuntimeError&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;error&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;
&lt;span class="mi"&gt;2017&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;24&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;54.823&lt;/span&gt; &lt;span class="mi"&gt;1108&lt;/span&gt; &lt;span class="n"&gt;ERROR&lt;/span&gt; &lt;span class="n"&gt;oslo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tester&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Note that the exception name (&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;RuntimeError&lt;/span&gt;&lt;/code&gt;) and error text appear
several lines removed from the first error line, which contains the
string passed to the exception() method.&lt;/p&gt;
&lt;p&gt;The log formatter used by oslo.log can be modified to insert the
summary of the exception into the first log line, along with the local
message. The results would 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="mi"&gt;2017&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;24&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;54.823&lt;/span&gt; &lt;span class="mi"&gt;1108&lt;/span&gt; &lt;span class="n"&gt;ERROR&lt;/span&gt; &lt;span class="n"&gt;oslo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tester&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;24&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;the&lt;/span&gt; &lt;span class="n"&gt;exception&lt;/span&gt; &lt;span class="n"&gt;log&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="ne"&gt;RuntimeError&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;error&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;
&lt;span class="mi"&gt;2017&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;24&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;54.823&lt;/span&gt; &lt;span class="mi"&gt;1108&lt;/span&gt; &lt;span class="n"&gt;ERROR&lt;/span&gt; &lt;span class="n"&gt;oslo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tester&lt;/span&gt; &lt;span class="n"&gt;Traceback&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;most&lt;/span&gt; &lt;span class="n"&gt;recent&lt;/span&gt; &lt;span class="n"&gt;call&lt;/span&gt; &lt;span class="n"&gt;last&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="mi"&gt;2017&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;24&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;54.823&lt;/span&gt; &lt;span class="mi"&gt;1108&lt;/span&gt; &lt;span class="n"&gt;ERROR&lt;/span&gt; &lt;span class="n"&gt;oslo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tester&lt;/span&gt;   &lt;span class="n"&gt;File&lt;/span&gt; &lt;span class="s2"&gt;"./tester.py"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="mi"&gt;21&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;module&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="mi"&gt;2017&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;24&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;54.823&lt;/span&gt; &lt;span class="mi"&gt;1108&lt;/span&gt; &lt;span class="n"&gt;ERROR&lt;/span&gt; &lt;span class="n"&gt;oslo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tester&lt;/span&gt;     &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="ne"&gt;RuntimeError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'the error text'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mi"&gt;2017&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;24&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;54.823&lt;/span&gt; &lt;span class="mi"&gt;1108&lt;/span&gt; &lt;span class="n"&gt;ERROR&lt;/span&gt; &lt;span class="n"&gt;oslo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tester&lt;/span&gt; &lt;span class="ne"&gt;RuntimeError&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;error&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;
&lt;span class="mi"&gt;2017&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;24&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;54.823&lt;/span&gt; &lt;span class="mi"&gt;1108&lt;/span&gt; &lt;span class="n"&gt;ERROR&lt;/span&gt; &lt;span class="n"&gt;oslo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tester&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;We can actually do this no matter the log level, so that if a log
message is emitted in the context of handling an exception, that error
is included in the output even if the level for the log message is
INFO or DEBUG.&lt;/p&gt;
&lt;p&gt;See &lt;a class="reference external" href="https://review.openstack.org/#/c/459424/"&gt;https://review.openstack.org/#/c/459424/&lt;/a&gt; for an example
change. The other log formatters provided by oslo.log will also need
to be updated.&lt;/p&gt;
&lt;p&gt;This change works with any Python library, not just OpenStack modules,
so errors produced by upstream dependencies are treated the same way.&lt;/p&gt;
&lt;p&gt;We can simultaneously allow operators to add the error summary to
their default format, so if they want to place it earlier in the line
they can. If the default error summary value is “&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;-&lt;/span&gt;&lt;/code&gt;”, the field
will be present, making log line parsing easier. For example, the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;logging_context_format_string&lt;/span&gt;&lt;/code&gt; value can be set to&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="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;asctime&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.%&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msecs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="mi"&gt;03&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;process&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;levelname&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;%&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;s&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;lineno&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;s&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;request_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_identity&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;s&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="n"&gt;error_summary&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;s&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;instance&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&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;to produce a line like the following (when there is an error)&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="mi"&gt;2017&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;24&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;54.823&lt;/span&gt; &lt;span class="mi"&gt;1108&lt;/span&gt; &lt;span class="n"&gt;INFO&lt;/span&gt; &lt;span class="n"&gt;oslo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tester&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;24&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="ne"&gt;RuntimeError&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;error&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;regular&lt;/span&gt; &lt;span class="n"&gt;log&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="n"&gt;goes&lt;/span&gt; &lt;span class="n"&gt;here&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;or like the following (when there is not an error)&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="mi"&gt;2017&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;24&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;54.823&lt;/span&gt; &lt;span class="mi"&gt;1108&lt;/span&gt; &lt;span class="n"&gt;INFO&lt;/span&gt; &lt;span class="n"&gt;oslo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tester&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;24&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="o"&gt;-&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;regular&lt;/span&gt; &lt;span class="n"&gt;log&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="n"&gt;goes&lt;/span&gt; &lt;span class="n"&gt;here&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;see &lt;a class="reference external" href="https://review.openstack.org/461506"&gt;https://review.openstack.org/461506&lt;/a&gt; for an example implementation
of this additional flexibility.&lt;/p&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;The first public specification related to this topic was posted in glance-specs
under the title “Glance Error Codes”: &lt;a class="reference external" href="https://review.openstack.org/#/c/127482"&gt;https://review.openstack.org/#/c/127482&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The Glance spec was eventually moved to the cross-project specs repo with
the title “OpenStack wide Error Codes for Log Messages”:
&lt;a class="reference external" href="https://review.openstack.org/#/c/172552"&gt;https://review.openstack.org/#/c/172552&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We could, once and for all, declare that this is not a feature we are going
to add to OpenStack.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We could adopt the “situation ID” proposal in the cross-project
spec proposed as &lt;a class="reference external" href="https://review.openstack.org/460110"&gt;https://review.openstack.org/460110&lt;/a&gt;, or one of the
variations described in the alternatives section of that document.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We could add the directives to the default logging format string to
add the line numbers automatically. This would likely break the log
management pipelines in existing deployments, since the line format
would change.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h3&gt;References&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://docs.python.org/2/library/logging.html#logrecord-attributes"&gt;Python logging module documentation about log record attributes&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://doughellmann.com/blog/2017/04/20/lessons-learned-from-working-on-large-scale-cross-project-initiatives-in-openstack/"&gt;Lessons learned from working on large scale, cross-project
initiatives in OpenStack&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://www.openstack.org/summit/boston-2017/summit-schedule/events/18778/enhancing-log-message-headers-for-rt-debug-and-traceability"&gt;Boston Forum session to discuss logging proposals&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://www.openstack.org/summit/boston-2017/summit-schedule/events/18507/logging-working-group-working-session"&gt;Boston Forum Logging Working Group Work session&lt;/a&gt;&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:&lt;/p&gt;
&lt;p&gt;oslo.log work: dhellmann&lt;/p&gt;
&lt;p&gt;documenting exceptions in more detail: TBD&lt;/p&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Add documentation about how to include line numbers in the log
messages.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Make the oslo.log context formatter add exception summary when
logging an exception (&lt;a class="reference external" href="https://review.openstack.org/#/c/459424/"&gt;https://review.openstack.org/#/c/459424/&lt;/a&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Make the other oslo.log formatters add the exception summary, where
appropriate. (JSON, journald, etc.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Make the other oslo.log formatters and handlers include the line
number, where appropriate. (JSON, journald, etc.)&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="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;Pike&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;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This work is licensed under a Creative Commons Attribution 3.0 Unported License.
&lt;a class="reference external" href="http://creativecommons.org/licenses/by/3.0/legalcode"&gt;http://creativecommons.org/licenses/by/3.0/legalcode&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
</description><pubDate>Wed, 26 Apr 2017 00:00:00 </pubDate></item><item><title>Machine Readable Sample Config</title><link>https://specs.openstack.org/openstack/oslo-specs/specs/pike/machine-readable-sample-config.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/oslo?searchtext=machine-readable-sample-config"&gt;https://blueprints.launchpad.net/oslo?searchtext=machine-readable-sample-config&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Currently the sample configs generated by oslo.config are targeted for
consumption by humans.  However, many deployment tools would benefit from a
sample config that is machine readable.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;All deployment tools have to solve a similar problem: how to generate the
config files for each service at deployment time.  There are various approaches
to this today, including manually updated templates, semi-automatically
generated templates, and using an ini file tool to update the existing sample
config for each project.&lt;/p&gt;
&lt;p&gt;These approaches all have various drawbacks.  Template approaches generally
require some level of tedious human editing to template all of the values
the deployment tool needs to set.  Ini file tools are not aware of the sample
config format and thus are only able to set values in the correct section,
which usually separates them from the sample config documentation of the
option.  None of these approaches make it easy for a deployment tool to
provide a user-friendly interface to the config options.&lt;/p&gt;
&lt;p&gt;The problem with the current ini format sample config in this case is that it
is not easily machine-readable.  The content is all written in commented
blocks which would have to be parsed by a deployment tool.  Since that
comment format is not guaranteed to remain the same, it would require ongoing
maintenance by each deployment tool using this approach.&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 write machine-readable sample config files that output the
same data as the existing ini files, but in a YAML or JSON format that can be
more easily consumed by deployment tools.&lt;/p&gt;
&lt;p&gt;Example of proposed output:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;generator_options&lt;/span&gt;&lt;span class="p"&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;config&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;etc&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;nova&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;nova&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;generator&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;output_file&lt;/span&gt;&lt;span class="p"&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;nova&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;nova&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;conf&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;yaml&lt;/span&gt;
    &lt;span class="n"&gt;wrap_width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;
    &lt;span class="n"&gt;namespace&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;nova&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;conf&lt;/span&gt;
        &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;oslo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;log&lt;/span&gt;
        &lt;span class="o"&gt;...&lt;/span&gt;
    &lt;span class="n"&gt;summarize&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;False&lt;/span&gt;
    &lt;span class="c1"&gt;# minimal intentionally omitted as I don't think it makes sense in&lt;/span&gt;
    &lt;span class="c1"&gt;# this context&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;more&lt;/span&gt; &lt;span class="n"&gt;generator&lt;/span&gt; &lt;span class="n"&gt;details&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;added&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;desired&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;options&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;image_service&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="c1"&gt;# The list of parameters is for example only.  The actual output&lt;/span&gt;
            &lt;span class="c1"&gt;# can include anything deployment tools would find useful.&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;nova&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;glance&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GlanceImageService&lt;/span&gt;
            &lt;span class="n"&gt;documentation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Service&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;search&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;retrieve&lt;/span&gt; &lt;span class="n"&gt;images&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
            &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt;
            &lt;span class="n"&gt;required&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt;
            &lt;span class="n"&gt;deprecated&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;False&lt;/span&gt;
            &lt;span class="n"&gt;deprecated_reason&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;blabla&lt;/span&gt;
            &lt;span class="n"&gt;deprecated_for_removal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;False&lt;/span&gt;
            &lt;span class="n"&gt;deprecated_since&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;XXX&lt;/span&gt;
            &lt;span class="n"&gt;deprecated_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;old_parameter&lt;/span&gt;
            &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;all&lt;/span&gt; &lt;span class="n"&gt;other&lt;/span&gt; &lt;span class="n"&gt;parameters&lt;/span&gt; &lt;span class="n"&gt;passed&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;opt&lt;/span&gt; &lt;span class="n"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="n"&gt;new_opt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;deprecated_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;old_opt&lt;/span&gt;
            &lt;span class="o"&gt;...&lt;/span&gt;
        &lt;span class="o"&gt;...&lt;/span&gt;
    &lt;span class="n"&gt;conductor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;workers&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="o"&gt;...&lt;/span&gt;
    &lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="n"&gt;deprecated_options&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;old_opt&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;foo&lt;/span&gt;
            &lt;span class="n"&gt;documentation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Example&lt;/span&gt; &lt;span class="n"&gt;deprecated&lt;/span&gt; &lt;span class="n"&gt;opt&lt;/span&gt;
            &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt;
            &lt;span class="n"&gt;replacement_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;new_opt&lt;/span&gt;
            &lt;span class="n"&gt;replacement_group&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;DEFAULT&lt;/span&gt;
            &lt;span class="o"&gt;...&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;This structure would contain all of the details needed to write a
well-formatted config file, and it would be easier to inject values in the
appropriate place because we would be starting from the actual opt data
instead of an ini file full of comments.  It should require little to no
manual maintenance because it would be generated from sample config data
already provided by each project.&lt;/p&gt;
&lt;p&gt;Another suggested change in this format from the existing generated sample
config is to write deprecated opts as first-class citizens rather than just
as a deprecated_name/group on the new opt.  This way the structure will still
align with the previous config, which should make it easier to transition
from release to release.  These opts would, of course, be marked deprecated so
it is clear that they should no longer be used.  An example of this is included
above.&lt;/p&gt;
&lt;p&gt;Note on the implementation: In order to easily support both YAML and JSON
formats, I think the generator should work with nested dicts that can simply
be output using the appropriate module.  Since YAML and JSON formatters
already exist we shouldn’t need to reinvent those wheels.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Some of the existing methods for doing this and their drawbacks are discussed
above in the problems section.  These methods work, but there is a lot of
duplication of effort across all deployment projects so it is not desirable
to continue this way.&lt;/p&gt;
&lt;p&gt;Each project could automate their config file generation, similar to the
OpenStack Helm tool in the References section, but there again we have a
duplication problem that oslo.config can solve.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="impact-on-existing-apis"&gt;
&lt;h3&gt;Impact on Existing APIs&lt;/h3&gt;
&lt;p&gt;We would need to add a –format parameter to the oslo-config-generator so
users can generate sample configs with the new format(s).  This would
default to the existing ini-style format for backwards compatibility.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;Should be none.  For the most part this is just a new format for data that
was already being generated.  One possible exception would be capturing the
parameters to the config generator, but I don’t see anything in there that
should be sensitive.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;Generating the new file formats will take additional time, but by default
only the existing format will be created so there should be no change.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="configuration-impact"&gt;
&lt;h3&gt;Configuration Impact&lt;/h3&gt;
&lt;p&gt;Outside of the –format CLI param, no new config opts are proposed.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer Impact&lt;/h3&gt;
&lt;p&gt;None.  Developers are already exposing config opts to the config generator,
and this is simply adding another use for that.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing-impact"&gt;
&lt;h3&gt;Testing Impact&lt;/h3&gt;
&lt;p&gt;This functionality would be unit tested in the same way as the existing config
generator.  We would need to add YAML/JSON scenarios to the unit tests.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;bnemec&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;emacchi&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="milestones"&gt;
&lt;h3&gt;Milestones&lt;/h3&gt;
&lt;p&gt;Target Milestone for completion: We would like to complete this work in Pike,
probably for consumption by deployment tools in the Queens cycle.&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 YAML output&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Implement JSON output&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add test scenarios for new formats&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="incubation"&gt;
&lt;h2&gt;Incubation&lt;/h2&gt;
&lt;p&gt;Not being incubated.&lt;/p&gt;
&lt;section id="adoption"&gt;
&lt;h3&gt;Adoption&lt;/h3&gt;
&lt;p&gt;NA&lt;/p&gt;
&lt;/section&gt;
&lt;section id="library"&gt;
&lt;h3&gt;Library&lt;/h3&gt;
&lt;p&gt;NA&lt;/p&gt;
&lt;/section&gt;
&lt;section id="anticipated-api-stabilization"&gt;
&lt;h3&gt;Anticipated API Stabilization&lt;/h3&gt;
&lt;p&gt;NA&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;This work is targeted at deployment tools, so there should be little to no
user-facing documentation changes required.  We would want to reference the
existence of these new sample formats in the oslo.config documentation.&lt;/p&gt;
&lt;p&gt;The format and structure of the output files will need to be documented for
deployment tool consumption.&lt;/p&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="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;&lt;a class="reference external" href="https://etherpad.openstack.org/p/ansible-config-mgt"&gt;Cross-Deployment Tool PTG Session&lt;/a&gt;, specifically the
Problem #1 section.&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://github.com/alanmeadows/gen-oslo-openstack-helm"&gt;https://github.com/alanmeadows/gen-oslo-openstack-helm&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 work is licensed under a Creative Commons Attribution 3.0
Unported License.
&lt;a class="reference external" href="http://creativecommons.org/licenses/by/3.0/legalcode"&gt;http://creativecommons.org/licenses/by/3.0/legalcode&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
</description><pubDate>Wed, 01 Mar 2017 00:00:00 </pubDate></item><item><title>oslo.log – &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;user_identity&lt;/span&gt;&lt;/code&gt; format flexibility</title><link>https://specs.openstack.org/openstack/oslo-specs/specs/liberty/oslo.log-user-identity-format-flexibility.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/oslo.log/+spec/user-identity-format-flexibility"&gt;https://blueprints.launchpad.net/oslo.log/+spec/user-identity-format-flexibility&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The goal of this blueprint is to make it easier to adjust the format
of the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;user_identity&lt;/span&gt;&lt;/code&gt; field in the log line without having to
specify the full log format string.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;We want devstack to log identity using names, but by default we want
identity to use UUID values because they are guaranteed to be
unique.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We don’t want devstack to override the format string for projects
individually.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We do want devstack to be able to change the default format without
having to specify the whole string, for this leaves devstack with no
info on anything added into the default formatting string.&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;Since oslo.context is not using oslo.config, and is incorrectly
enforcing formatting, we want to make this change to oslo.log.&lt;/p&gt;
&lt;p&gt;Let oslo.log control the formatting for the user_identity value in the
log output. We have to leave the value in place in oslo.context, but
we don’t have to use it any more.&lt;/p&gt;
&lt;p&gt;Add a new configuration option to specify how to format the
user_identity field. (We might find it useful to do this for other
fields in the future, too, but let’s focus on one for now.)&lt;/p&gt;
&lt;p&gt;Update oslo.log so it asks oslo.context for the values, and then
replaces the user_identity with a string it builds itself using values
it gets from oslo.context and the format string it gets from its
configuration option.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;We could require anyone wanting to customize the log format to replace
the entire format string, but that makes it a little harder to adjust
just part of it as we standardize the overall structure of the log
messages.&lt;/p&gt;
&lt;p&gt;We could place the configuration option in oslo.context, but that
library is not using oslo.config yet and it should not have log
formatting logic embedded in it.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="impact-on-existing-apis"&gt;
&lt;h3&gt;Impact on Existing APIs&lt;/h3&gt;
&lt;p&gt;None. The &lt;code class="xref py py-class docutils literal notranslate"&gt;&lt;span class="pre"&gt;RequestContext&lt;/span&gt;&lt;/code&gt; from oslo.context will still need to
provide user_identity for backwards compatibility.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;The result will be no more or less secure than before.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;One extra format call should not have a big performance impact.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="configuration-impact"&gt;
&lt;h3&gt;Configuration Impact&lt;/h3&gt;
&lt;p&gt;One new configuration option, with the default set up to result in the
same format we have now.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer Impact&lt;/h3&gt;
&lt;p&gt;Users of devstack will eventually be able to see user identity in a
nicer format.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing-impact"&gt;
&lt;h3&gt;Testing Impact&lt;/h3&gt;
&lt;p&gt;No significant change.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;p&gt;Primary assignee: doug-hellmann&lt;/p&gt;
&lt;p&gt;Other contributors: ihrachyshka&lt;/p&gt;
&lt;/section&gt;
&lt;section id="milestones"&gt;
&lt;h3&gt;Milestones&lt;/h3&gt;
&lt;p&gt;Target Milestone for completion: liberty-3&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 a new config option to oslo.log to control how the
user_identity values are formatted; default it to what oslo.context
does now&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;add a new method to oslo.context to provide identity values to go
into that format string (or just use the whole context dict?) Dict
is fine.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;update oslo.log to build a new string and update the dictionary
given to it from to_dict() always&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;update devstack to set the new configuration option in a way that
uses names instead of, or in addition to, uuids&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="incubation"&gt;
&lt;h2&gt;Incubation&lt;/h2&gt;
&lt;p&gt;N/A&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 configuration option needs to be documented.&lt;/p&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 is related to &lt;a class="reference internal" href="../kilo/app-agnostic-logging-parameters.html"&gt;&lt;span class="doc"&gt;Provide application-agnostic logging parameters in format strings&lt;/span&gt;&lt;/a&gt;
but only depends on it in the sense that only projects using
oslo.log and oslo.context will be able to take advantage of the
feature.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;notes: &lt;a class="reference external" href="https://etherpad.openstack.org/p/logging-flexibility"&gt;https://etherpad.openstack.org/p/logging-flexibility&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This work is licensed under a Creative Commons Attribution 3.0
Unported License.
&lt;a class="reference external" href="http://creativecommons.org/licenses/by/3.0/legalcode"&gt;http://creativecommons.org/licenses/by/3.0/legalcode&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
</description><pubDate>Fri, 20 Jan 2017 00:00:00 </pubDate></item><item><title>Rootwrap daemon mode</title><link>https://specs.openstack.org/openstack/oslo-specs/specs/juno/rootwrap-daemon-mode.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/oslo.rootwrap/+spec/rootwrap-daemon-mode"&gt;https://blueprints.launchpad.net/oslo.rootwrap/+spec/rootwrap-daemon-mode&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;As it was pointed out several times on ML &lt;a class="footnote-reference brackets" href="#neu-ml" id="id1" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; &lt;a class="footnote-reference brackets" href="#nova-ml" 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; different
services (most notably Neutron and Nova) suffer from performance penalty of
having to run new instance of rootwrap executable for each call that needs root
privileges. &lt;a class="footnote-reference brackets" href="#nova-ml" 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; ended basically with “Who’s up to the task?” question.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;The structure of this overhead has been analyzed in &lt;a class="footnote-reference brackets" href="#neu-ml" 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;. It’s clear that
the main issue here is rootwrap startup time that consists of  Python
interpreter startup and rootwrap config parsing.&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 creating a new mode of operation for rootwrap - daemon mode. In this
mode rootwrap would start, read config file and wait for commands to be run
with root privileges. Each service’s process will have its own rootwrap daemon
process.&lt;/p&gt;
&lt;section id="daemon-starting"&gt;
&lt;h3&gt;Daemon starting&lt;/h3&gt;
&lt;p&gt;Daemon will be started using a separate binary (like neutron-rootwrap-daemon
for Neutron) pointing to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo.rootwrap.cmd:daemon&lt;/span&gt;&lt;/code&gt; endpoint (instead of
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;:main&lt;/span&gt;&lt;/code&gt;). The binary will receive the same options (config file) as the
normal one except the command to be run in priviledged mode. For example:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;rootwrap&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;daemon&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;myservice&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;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The startup process is the same as in normal mode up to the point when the
command is about to be run. In daemon mode a separate method is called instead
that starts RPC &lt;a class="footnote-reference brackets" href="#rpc" 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; server and falls into infinite loop serving requests.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="daemon-api"&gt;
&lt;h3&gt;Daemon API&lt;/h3&gt;
&lt;p&gt;Upon startup daemon will push to its stdout:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;path to UNIX domain socket (encoded in UTF-8);&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;newline character &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;\n&lt;/span&gt;&lt;/code&gt;;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;32-byte auth key.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These credentials can be used to connect a
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;multiprocessing.BaseManager&lt;/span&gt;&lt;/code&gt;-based client. Because &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;pickle&lt;/span&gt;&lt;/code&gt; and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;xmlrpclib&lt;/span&gt;&lt;/code&gt; are unsafe, it uses its own JSON serialization (see &lt;a class="reference internal" href="#under-the-hood"&gt;Under the
hood&lt;/a&gt; section). The only exposed object is &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;rootwrap&lt;/span&gt;&lt;/code&gt; with one method:
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;run_one_command(userargs,&lt;/span&gt; &lt;span class="pre"&gt;env=None,&lt;/span&gt; &lt;span class="pre"&gt;stdin=None)&lt;/span&gt;&lt;/code&gt;. Arguments are:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;userargs&lt;/span&gt;&lt;/code&gt; - list of command line arguments that are to be used to run the
command;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;env&lt;/span&gt;&lt;/code&gt; - dict of environment variables to be set for it (by default it’s an
empty dict, so all environment variables are stripped);&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;stdin&lt;/span&gt;&lt;/code&gt; - string to be passed to standard input of child process.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The method returns 3-tuple containing:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;return code of child process;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;string containing everything captured from its stdout stream;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;string containing everything captured from its stderr stream.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Here is a sketch of basic usage for rootwrap daemon:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;subprocess&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;
&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;multiprocessing.managers&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;BaseManager&lt;/span&gt;
&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class="n"&gt;process&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Popen&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s2"&gt;"rootwrap-daemon"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"rootwrap.conf"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;stdout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;PIPE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class="n"&gt;address&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;process&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stdout&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;readline&lt;/span&gt;&lt;span class="p"&gt;()[:&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'utf-8'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class="n"&gt;authkey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;process&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stdout&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;32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyManager&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BaseManager&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;pass&lt;/span&gt;
&lt;span class="gp"&gt;...&lt;/span&gt;
&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class="n"&gt;MyManager&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"rootwrap"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;oslo.rootwrap&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;  &lt;span class="c1"&gt;# to set up 'jsonrpc' serializer only&lt;/span&gt;
&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class="n"&gt;manager&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;MyManager&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;authkey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;serializer&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'jsonrpc'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class="n"&gt;manager&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="gp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class="n"&gt;proxy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;manager&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rootwrap&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class="n"&gt;proxy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run_one_command&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s2"&gt;"cat"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;stdin&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"Hello, world!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="go"&gt;[0, u'Hello, world!', u'']&lt;/span&gt;
&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class="n"&gt;process&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;kill&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 this requires &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;rootwrap-daemon&lt;/span&gt;&lt;/code&gt; pointing to
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo.rootwrap.cmd:daemon&lt;/span&gt;&lt;/code&gt; to be available in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PATH&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;run_one_command&lt;/span&gt;&lt;/code&gt; call returns a list here because of JSON serialization
but it doesn’t change Python API usage.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="client-api"&gt;
&lt;h3&gt;Client API&lt;/h3&gt;
&lt;p&gt;To simplify daemon usage a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo.rootwrap.client&lt;/span&gt;&lt;/code&gt; module is provided
containing one class &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Client&lt;/span&gt;&lt;/code&gt; that wraps all necessary steps to work with
rootwrap daemon.&lt;/p&gt;
&lt;p&gt;Its constructor expects one argument - a list that can be passed to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Popen&lt;/span&gt;&lt;/code&gt;
to create rootwrap daemon process. For Neutron it’ll be
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;["sudo",&lt;/span&gt; &lt;span class="pre"&gt;"neutron-rootwrap-daemon",&lt;/span&gt; &lt;span class="pre"&gt;"/etc/neutron/rootwrap.conf"]&lt;/span&gt;&lt;/code&gt;
for example.&lt;/p&gt;
&lt;p&gt;The class provides one method &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;execute&lt;/span&gt;&lt;/code&gt; with the same profile as
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;run_one_command&lt;/span&gt;&lt;/code&gt; method shown above.&lt;/p&gt;
&lt;p&gt;The class lazily creates an instance of the daemon, connects to it and passes
arguments. Note that some reconnection and respawning mechanism will be in
place so that if daemon process dies or hangs, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Client&lt;/span&gt;&lt;/code&gt; will detect this on
the next call and will simply restart it.&lt;/p&gt;
&lt;p&gt;This laziness will allow user to kill all rootwrap daemon processes to reload
config file, for example.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="under-the-hood"&gt;
&lt;h3&gt;Under the hood&lt;/h3&gt;
&lt;p&gt;The biggest expected security risk in this proposal is the way that client
talks to daemon so I’ll discuss the underlying protocol in details.&lt;/p&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;&lt;p&gt;Credentials passing&lt;/p&gt;
&lt;p&gt;The credentials required to connect to daemon are passed to stdout stream
that is expected to be bound through a pipe directly to calling process.
They are exposed only to the kernel and calling process here.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Authentication&lt;/p&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;multiprocessing&lt;/span&gt;&lt;/code&gt; involves digest authentication for every new connection
made to the server. The key is never passed over the socket, so we could
even use TCP socket here (no way). The key is generated using
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;os.urandom(32)&lt;/span&gt;&lt;/code&gt; call.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Connection (non-)pooling&lt;/p&gt;
&lt;p&gt;Managers use threadlocal connections so there’s no need to create a pool of
them. Although it might sound wasteful to create new connection for every
thread, creating a connection over UNIX socket is almost nothing compared to
spawning a new process time-wise.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;On-wire protocol&lt;/p&gt;
&lt;p&gt;By default &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;multiprocessing&lt;/span&gt;&lt;/code&gt; uses &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;pickle&lt;/span&gt;&lt;/code&gt; to serialize RPC &lt;a class="footnote-reference brackets" href="#rpc" 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;
requests and responses but it’s very unsafe as it allows to call any method
on the receiving side (see warning in &lt;a class="footnote-reference brackets" href="#pickle" 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;). The only other option is
to use &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;xmlrpclib&lt;/span&gt;&lt;/code&gt; as a serializer but it’s unsafe as it’s prone to
resource exhaustion attacks &lt;a class="footnote-reference brackets" href="#xml-unsafe" id="id8" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;9&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;. That’s why JSON serialization
support is implemented. It’s very simple (~50 SLOC) and is safe because JSON
serialization is widely regarded as being safe.&lt;/p&gt;
&lt;p&gt;This serialization is plugged in using undocumented features of
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;multiprocessing.managers&lt;/span&gt;&lt;/code&gt; module:&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;listener_client&lt;/span&gt;&lt;/code&gt; - dictionary of available serialization options with
strings as keys and pairs (listener, client) as values;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;serializer&lt;/span&gt;&lt;/code&gt; - argument of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;BaseManager.__init__&lt;/span&gt;&lt;/code&gt; constructor,
contains a key in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;listener_client&lt;/span&gt;&lt;/code&gt; dictionary.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The author of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;multiprocessing&lt;/span&gt;&lt;/code&gt; module assured that this mechanism is not
going to go away any time soon &lt;a class="footnote-reference brackets" href="#ser-bug" id="id9" 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;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;Although it’s risky to rely on undocumented feature,
it’s mitigated by the assurance of the stdlib module author.&lt;/p&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;There are a number of alternative approaches to optimize number of rootwrap
calls to mitigate the overhead (see &lt;a class="footnote-reference brackets" href="#neu-eth" id="id10" 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;). There were a number of
suggestions in original thread in mailing list &lt;a class="footnote-reference brackets" href="#neu-ml" id="id11" 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 in corresponding
etherpad &lt;a class="footnote-reference brackets" href="#neu-eth" id="id12" 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;ul&gt;
&lt;li&gt;&lt;p&gt;Scrap rootwrap, switch to sudo.&lt;/p&gt;
&lt;p&gt;We’ll lose current fine-grained control over what can be run as root.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use other interpretator for rootwrap.&lt;/p&gt;
&lt;p&gt;Doesn’t fix the interpretator startup cost.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Rewrite rootwrap in other language.&lt;/p&gt;
&lt;p&gt;This includes suggestions to rewrite entirely or partially in C or some
Python dialect that would be translateable to C.&lt;/p&gt;
&lt;p&gt;As OpenStack community is focused on Python development, bringing some other
language to the field would require more developers that would be familiar
with it.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Filter commands on the calling process side and use sudo.&lt;/p&gt;
&lt;p&gt;This would provide the same security as the first option.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Consolidate calls that use rootwrap into scripts&lt;/p&gt;
&lt;p&gt;We could create scripts that would require only one rootwrap call to do all
necessary work for one request, for example. But these scripts will either
become very complex (say rewriting parts of Neutron agents in shell) or there
will be too many of them. Either way defeats the purpose of sudo and rootwrap
- to minimize amount and complexity of code running with root privileges.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Per-host daemon process&lt;/p&gt;
&lt;p&gt;This would require some D-Bus or MQ set up and secured. It doesn’t look
feasible to set up such secure daemons. Supporting them across projects
seems even less feasible since every project uses its own rootwrap
configuration and such configurations might be host-dependent.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="impact-on-existing-apis"&gt;
&lt;h3&gt;Impact on Existing APIs&lt;/h3&gt;
&lt;p&gt;Operations in standalone mode are not affected in any way, so all existing
usages will work as before.&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 require another binary to be added to sudoers for the projects
that would use daemon mode.&lt;/p&gt;
&lt;p&gt;Daemon itself will listen UNIX domain socket but every connection is passed
through digest authentication.&lt;/p&gt;
&lt;p&gt;JSON is used as a transport to avoid known vulnerabilities in other types of
serialization mechanisms.&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 benchmark results in commit message in &lt;a class="footnote-reference brackets" href="#rw-cr" id="id13" 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;. They show that
although initial daemon startup time is slightly bigger than with usual
rootwrap call, on average daemon shows over 10x better performance.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="configuration-impact"&gt;
&lt;h3&gt;Configuration Impact&lt;/h3&gt;
&lt;p&gt;None in oslo.rootwrap itself. Projects using it might require a separate option
for new behavior.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer Impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;p&gt;The feature implementation is in progress at &lt;a class="footnote-reference brackets" href="#rw-cr" id="id14" 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;. Example usage for
Neutron is at &lt;a class="footnote-reference brackets" href="#neu-cr" id="id15" 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 id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;yorik-sar (Yuriy Taraday, YorikSar @ freenode)&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="milestones"&gt;
&lt;h3&gt;Milestones&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Target Milestone for completion:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Juno-2&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 blueprint suggests rather small addition to rootwrap.&lt;/p&gt;
&lt;p&gt;Further integration into different projects should be covered separately.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Both mechanisms involved in daemon work and its API should be covered in docs.&lt;/p&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="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;aside class="footnote-list brackets"&gt;
&lt;aside class="footnote brackets" id="neu-ml" 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;a role="doc-backlink" href="#id11"&gt;3&lt;/a&gt;)&lt;/span&gt;
&lt;p&gt;Original mailing list thread:
&lt;a class="reference external" href="http://lists.openstack.org/pipermail/openstack-dev/2014-March/029017.html"&gt;http://lists.openstack.org/pipermail/openstack-dev/2014-March/029017.html&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="nova-ml" 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;Earlier mailing list thread
&lt;a class="reference external" href="http://lists.openstack.org/pipermail/openstack-dev/2013-July/012539.html"&gt;http://lists.openstack.org/pipermail/openstack-dev/2013-July/012539.html&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="rpc" 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="#id5"&gt;1&lt;/a&gt;,&lt;a role="doc-backlink" href="#id6"&gt;2&lt;/a&gt;)&lt;/span&gt;
&lt;p&gt;Nowhere in this document “RPC” refer to that MQ-based RPC messaging
that &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo.messaging&lt;/span&gt;&lt;/code&gt; does&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="pickle" 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="https://docs.python.org/2.7/library/pickle.html"&gt;https://docs.python.org/2.7/library/pickle.html&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="ser-bug" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id9"&gt;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="http://bugs.python.org/issue21078"&gt;http://bugs.python.org/issue21078&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="neu-eth" 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="#id10"&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://etherpad.openstack.org/p/neutron-agent-exec-performance"&gt;https://etherpad.openstack.org/p/neutron-agent-exec-performance&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="rw-cr" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;7&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class="backrefs"&gt;(&lt;a role="doc-backlink" href="#id13"&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://review.openstack.org/81798"&gt;https://review.openstack.org/81798&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="neu-cr" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id15"&gt;8&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://review.openstack.org/84667"&gt;https://review.openstack.org/84667&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="xml-unsafe" 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;9&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://docs.python.org/2/library/xml.html#xml-vulnerabilities"&gt;https://docs.python.org/2/library/xml.html#xml-vulnerabilities&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;/aside&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This work is licensed under a Creative Commons Attribution 3.0
Unported License.
&lt;a class="reference external" href="http://creativecommons.org/licenses/by/3.0/legalcode"&gt;http://creativecommons.org/licenses/by/3.0/legalcode&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
</description><pubDate>Tue, 01 Nov 2016 00:00:00 </pubDate></item><item><title>Dynamic Policies Overlay</title><link>https://specs.openstack.org/openstack/oslo-specs/specs/liberty/dynamic-policies-overlay.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/oslo?searchtext=dynamic-policies-overlay"&gt;https://blueprints.launchpad.net/oslo?searchtext=dynamic-policies-overlay&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://wiki.openstack.org/wiki/DynamicPolicies"&gt;Dynamic Policies&lt;/a&gt; aims to
improve access control in OpenStack by improving the mechanisms in which
policies are defined and delivered to service endpoints.&lt;/p&gt;
&lt;p&gt;One step of dynamic delivery of policies is to overlay the existing service
endpoint’s local policy file with the custom rules defined in
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Keystone&lt;/span&gt; &lt;span class="pre"&gt;server&lt;/span&gt;&lt;/code&gt;. This overlay task is delegated to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo.policy&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;section id="alice-the-cloud-deployer"&gt;
&lt;h3&gt;Alice the Cloud Deployer&lt;/h3&gt;
&lt;p&gt;Alice is the kind of person who loves new features and eagerly awaits for new
OpenStack features like &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Dynamic&lt;/span&gt; &lt;span class="pre"&gt;Policies&lt;/span&gt;&lt;/code&gt; to enable them in her cloud.&lt;/p&gt;
&lt;p&gt;With that feature, she expects to be able to define her custom policy rules in
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Keystone&lt;/span&gt; &lt;span class="pre"&gt;server&lt;/span&gt;&lt;/code&gt; and have those applied to service endpoints transparently.&lt;/p&gt;
&lt;p&gt;Behind the scenes, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Keystone&lt;/span&gt; &lt;span class="pre"&gt;Middleware&lt;/span&gt;&lt;/code&gt; will fetch the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Dynamic&lt;/span&gt; &lt;span class="pre"&gt;Policy&lt;/span&gt;&lt;/code&gt;,
which contains the custom policy rules, for the service it is serving and ask
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo.policy&lt;/span&gt;&lt;/code&gt; to overlay the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Stock&lt;/span&gt; &lt;span class="pre"&gt;Policy&lt;/span&gt;&lt;/code&gt;, which is the existing local
policy file.&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;Based on the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Dynamic&lt;/span&gt; &lt;span class="pre"&gt;Policy&lt;/span&gt;&lt;/code&gt; and on the existing &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;policy_file&lt;/span&gt;&lt;/code&gt; and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;policy_dirs&lt;/span&gt;&lt;/code&gt; options, add to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo.policy&lt;/span&gt;&lt;/code&gt; the capability to overlay
rules in the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Stock&lt;/span&gt; &lt;span class="pre"&gt;Policy&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;When there is a rule clashing, the rule from &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Dynamic&lt;/span&gt; &lt;span class="pre"&gt;Policy&lt;/span&gt;&lt;/code&gt; always
overrides the rule in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Stock&lt;/span&gt; &lt;span class="pre"&gt;Policy&lt;/span&gt;&lt;/code&gt;. It means that any customization made
directly in the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Stock&lt;/span&gt; &lt;span class="pre"&gt;Policy&lt;/span&gt;&lt;/code&gt; will be lost if there is an entry for it in
the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Dynamic&lt;/span&gt; &lt;span class="pre"&gt;Policy&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Make &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Keystone&lt;/span&gt; &lt;span class="pre"&gt;Middleware&lt;/span&gt;&lt;/code&gt; itself do the overlay logic, however it seems to
not be a task for it at all, since &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo.policy&lt;/span&gt;&lt;/code&gt; is the one which does handle
policy files and owns the config options defining where such file is placed.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="impact-on-existing-apis"&gt;
&lt;h3&gt;Impact on Existing APIs&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 touches policy rules, which are sensitive data since they define
access control to service APIs in OpenStack.&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="configuration-impact"&gt;
&lt;h3&gt;Configuration 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="testing-impact"&gt;
&lt;h3&gt;Testing 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;Samuel de Medeiros Queiroz - samueldmq&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Adam Young - ayoung
Morgan Fainberg - mdrnstm&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="milestones"&gt;
&lt;h3&gt;Milestones&lt;/h3&gt;
&lt;p&gt;Target Milestone for completion: Liberty-2&lt;/p&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Create a new function that receives as input the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Dynamic&lt;/span&gt; &lt;span class="pre"&gt;Policy&lt;/span&gt;&lt;/code&gt; as a
Python dict and write them to the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Stock&lt;/span&gt; &lt;span class="pre"&gt;Policy&lt;/span&gt;&lt;/code&gt;, i.e the existing local
policy file, using override strategy when a clashing occurs.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="incubation"&gt;
&lt;h2&gt;Incubation&lt;/h2&gt;
&lt;section id="adoption"&gt;
&lt;h3&gt;Adoption&lt;/h3&gt;
&lt;p&gt;Any service using the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Dynamic&lt;/span&gt; &lt;span class="pre"&gt;Policies&lt;/span&gt;&lt;/code&gt; mechanism for access control will
be using the proposed change through &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Keystone&lt;/span&gt; &lt;span class="pre"&gt;Middleware&lt;/span&gt;&lt;/code&gt;, which means that
adoption is transparent to services.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="library"&gt;
&lt;h3&gt;Library&lt;/h3&gt;
&lt;p&gt;The proposed change will affect the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo.policy&lt;/span&gt;&lt;/code&gt; library.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="anticipated-api-stabilization"&gt;
&lt;h3&gt;Anticipated API Stabilization&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;None besides the regular Python code level documentation.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;A list of related specs defining the dynamic delivery of policies can be found
under the topic &lt;a class="reference external" href="https://review.openstack.org/#/q/topic:bp/dynamic-policies-delivery,n,z"&gt;dynamic-policies-delivery&lt;/a&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This work is licensed under a Creative Commons Attribution 3.0
Unported License.
&lt;a class="reference external" href="http://creativecommons.org/licenses/by/3.0/legalcode"&gt;http://creativecommons.org/licenses/by/3.0/legalcode&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
</description><pubDate>Tue, 01 Nov 2016 00:00:00 </pubDate></item><item><title>JSON schema for versioned objects</title><link>https://specs.openstack.org/openstack/oslo-specs/specs/newton/json-schema-for-versioned-object.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/oslo?searchtext=json-schema-for-versioned-object"&gt;https://blueprints.launchpad.net/oslo?searchtext=json-schema-for-versioned-object&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Versioned objects have a well defined schema that is available as python code.
This schema can also be expressed in a python independent way for example
with JSON Schema. Nova uses versioned objects to define its notification
interface. For the consumers of the notifications it would be super awesome
to have the schema defined in a easy to process and python independent way.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Versioned notifications in nova have a well defined schema implemented with
versioned objects. This schema prevents from changing the structure of the
notification without communicating the change to the notification consumers.
This communication is done via the version number embedded into the
notification payload. However this communication is limited and does not
contain information about what is changed in the schema or what is the
structure of a new notification.&lt;/p&gt;
&lt;p&gt;Notification consumers can understand the structure of the notification payload
based on notification samples or based on the object model only.
If a notification payload is changed then the object model is updated. However
this information is hard to consume from software and the consumer shall not
depend on the object model of the service directly.&lt;/p&gt;
&lt;p&gt;Also the consumer does not have an independent and automatic way to ensure that
the received notification has the expected structure without trying to consume
it.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h3&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;I as a notification consumer want to have a way to see the structure of the
notification payload without looking into the nova object model or
using human intelligence to understand the notification sample, so that I
can further automate the consumption of the new or changed notifications.&lt;/p&gt;
&lt;p&gt;I as a notification consumer want to validate that the received notification
has the defined structure automatically so that I can be sure my software can
consume the notification properly and detect problems earlier.&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;Notification payload is a versioned object and the wire format of it is a json
blob generated by the oslo.versionedobject serialization therefore it is
natural to define the structure of this json blob with a JSON Schema.
This way there would be a implementation independent, machine readable
description of the versioned objects.&lt;/p&gt;
&lt;p&gt;Therefore this spec proposes to add JSON Schema generation function to the
VersionedObject base class. The implementation would iterate through the items
in the &lt;cite&gt;fields&lt;/cite&gt; field of the VersionedObject class and would use the field type
to collect the schema pieces. Every FieldType object would need to have a new
function &lt;cite&gt;get_schema(self)&lt;/cite&gt; which returns the schema piece of the field.
The Object field type will do a recursion and generate the schema of the
referred class.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;As an alternative it would be possible to externalize the object
model used to define the notifications and offer it as a python library to
consumers. However this would only help consumer that are capable of import
python libraries and it would force the consumers to depend on oslo versioned
objects.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="impact-on-existing-apis"&gt;
&lt;h3&gt;Impact on Existing APIs&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;A new class method &lt;cite&gt;to_json_schema(cls)&lt;/cite&gt; will be added to VersionedObject
class that returns a JSON schema of the class.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A new method &lt;cite&gt;get_schema(self)&lt;/cite&gt; will be added to the FieldType base class.
Every field type shall override it to provide the field specific schema.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="configuration-impact"&gt;
&lt;h3&gt;Configuration 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;Service should use the new class method to generate the schema for validation
and documentation generation purposes.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing-impact"&gt;
&lt;h3&gt;Testing Impact&lt;/h3&gt;
&lt;p&gt;Besides unit testing the service using this feature can add test coverage with
real versioned objects.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;balazs-gibizer&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="milestones"&gt;
&lt;h3&gt;Milestones&lt;/h3&gt;
&lt;p&gt;Newton-2&lt;/p&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;update the FieldType classes to provide the &lt;cite&gt;get_schema()&lt;/cite&gt; method&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;add the new class method to the VersionedObject class&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="incubation"&gt;
&lt;h2&gt;Incubation&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;section id="adoption"&gt;
&lt;h3&gt;Adoption&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="library"&gt;
&lt;h3&gt;Library&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="anticipated-api-stabilization"&gt;
&lt;h3&gt;Anticipated API Stabilization&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&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="dependencies"&gt;
&lt;h2&gt;Dependencies&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;[1] The Nova spec tracking the versioned notification work that will be the
user of this new API in oslo
&lt;a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/versioned-notification-transformation-newton"&gt;https://blueprints.launchpad.net/nova/+spec/versioned-notification-transformation-newton&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This work is licensed under a Creative Commons Attribution 3.0
Unported License.
&lt;a class="reference external" href="http://creativecommons.org/licenses/by/3.0/legalcode"&gt;http://creativecommons.org/licenses/by/3.0/legalcode&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
</description><pubDate>Fri, 29 Apr 2016 00:00:00 </pubDate></item><item><title>Mutable logging configuration</title><link>https://specs.openstack.org/openstack/oslo-specs/specs/newton/reconfigurable-oslo-logging.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/oslo-log/+spec/mutable-logging"&gt;https://blueprints.launchpad.net/oslo-log/+spec/mutable-logging&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;There is a strong desire from operators to be able to reconfigure logging
without a service restart. For example, to selectively enable DEBUG logging in
response to observed issues. Mutable config patches have enabled options to be
mutated at runtime, now we need to do the same for logging config.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;section id="mutable-logging"&gt;
&lt;h3&gt;Mutable logging&lt;/h3&gt;
&lt;p&gt;Previous work on oslo.config and oslo.log has allowed the ‘debug’ flag to be
mutable at runtime. However, oslo.log also accepts a ‘log_config_append’
option. If this is provided, most of the options are ignored and a logging
config file is read. In this case, mutating the ‘debug’ flag is insufficient
to change the log level.&lt;/p&gt;
&lt;p&gt;This flag also provides minimal control over logging. It should be possible to
change the log level of individual loggers at runtime. To support this, full
mutation of the logging config should be supported.&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;Mark ‘log_config_append’ as mutable. When the hook is called, call
logging.fileConfig if the value of log_config_append changed or the timestamp
of the file it points to changed.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;The primary usecase for a logging config file is to output log records as JSON
suitable for Logstash. If oslo.log provided a simple way to configure this
then full logging configurations would be less common. Other suggestions are
for ‘syslog’, ‘fluentd’ and ‘color’ logging.&lt;/p&gt;
&lt;p&gt;There are three reasons to proceed with the proposed change. Firstly, making
one change does not preclude the other. We can “make the simple easy and the
complex possible”. Secondly, the plurality of “simple” configurations implies
that another could be needed at any moment. Until this can be provided, users
would have to do without or use a full logging config.&lt;/p&gt;
&lt;p&gt;Lastly, although configuring an additional handler is the most common reason
to use a full logging config, it is also common to reconfigure some log
levels. If we expose options which can turn on Logstash and/or Fluentd and/or
syslog handlers, plus set arbitrary logger levels - have we not reinvented the
logging config system? And with a plethora of switches and options rather than
a well-defined DSL. This feels like a retrograde step.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="impact-on-existing-apis"&gt;
&lt;h3&gt;Impact on Existing APIs&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="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="configuration-impact"&gt;
&lt;h3&gt;Configuration 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="testing-impact"&gt;
&lt;h3&gt;Testing Impact&lt;/h3&gt;
&lt;p&gt;Although the oslo.log change is simple, the ‘logging’ module is doing a lot
for us. Unit tests will demonstrate the behaviour in cases such as when a
handler initially configured is no longer mentioned when the config is
reloaded.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;alexisl&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;Mark ‘log_config_append’ as mutable.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Call logging.fileConfig from the hook.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&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="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;This work relates to the mutate_config_files work in oslo.config, which has
already merged.&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://review.openstack.org/#/c/254821/"&gt;https://review.openstack.org/#/c/254821/&lt;/a&gt; adds a mutate hook to oslo.log. This
spec will extend the hook by making log-config-append mutable.&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;Some testing of fileConfig:
&lt;a class="reference external" href="https://gist.github.com/lxsli/3ef859d641da7bcc9bd6"&gt;https://gist.github.com/lxsli/3ef859d641da7bcc9bd6&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The ‘logging’ module was creating a Lock before eventlet could monkey-patch
it. Eventlet now patches that lock so this is no longer a problem. Gevent
already has code to do this.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Locking issue originally diagnosed by Alexander Makarov:
&lt;a class="reference external" href="https://review.openstack.org/#/c/154838"&gt;https://review.openstack.org/#/c/154838&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Demonstration of the locking issue:
&lt;a class="reference external" href="https://gist.github.com/lxsli/9d2458834e13ad0f5e25"&gt;https://gist.github.com/lxsli/9d2458834e13ad0f5e25&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Eventlet fix: &lt;a class="reference external" href="https://github.com/eventlet/eventlet/pull/309"&gt;https://github.com/eventlet/eventlet/pull/309&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This work is licensed under a Creative Commons Attribution 3.0
Unported License.
&lt;a class="reference external" href="http://creativecommons.org/licenses/by/3.0/legalcode"&gt;http://creativecommons.org/licenses/by/3.0/legalcode&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
</description><pubDate>Tue, 22 Mar 2016 00:00:00 </pubDate></item><item><title>Managing Release Notes</title><link>https://specs.openstack.org/openstack/oslo-specs/specs/policy/release-note-management.html</link><description>

&lt;p&gt;This spec documents the policy for where and how to manage release
notes for Oslo libraries.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem Description&lt;/h2&gt;
&lt;p&gt;Oslo libraries have several potential audiences:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;OpenStack service developers&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;OpenStack deployers&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;other developers&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The type of information those audiences want for release notes can be
quite different. This policy describes how we manage release notes to
ensure we are communicating appropriately with each audience.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-policy"&gt;
&lt;h2&gt;Proposed Policy&lt;/h2&gt;
&lt;p&gt;Release notes for developers, whether part of the OpenStack community
or not, are handled in the developer documentation published for the
libraries. This ensures that all developer-focused information is in
one place.&lt;/p&gt;
&lt;p&gt;The packaging library pbr includes a facility for automatically
generating a ChangeLog file based on the git history for the project
being packaged. That file is reStructuredText, and should be included
directly in the developer documentation compiled by Sphinx into HTML
and published under &lt;a class="reference external" href="http://docs.openstack.org/developer/"&gt;http://docs.openstack.org/developer/&lt;/a&gt; by adding a
static &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;history.rst&lt;/span&gt;&lt;/code&gt; file that uses the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;include&lt;/span&gt;&lt;/code&gt; directive to
load the generated file.&lt;/p&gt;
&lt;p&gt;Additional information for developers can be added directly to the
developer documentation. Docstrings in code should be annotated with
version information for new features or parameters using the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;versionadded&lt;/span&gt;&lt;/code&gt; directive and for deprecations using the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;warning&lt;/span&gt;&lt;/code&gt;
directive.&lt;/p&gt;
&lt;p&gt;Release notes for deployers should be managed through &lt;a class="reference external" href="http://docs.openstack.org/developer/reno/"&gt;reno&lt;/a&gt; and
published under &lt;a class="reference external" href="http://docs.openstack.org/releasenotes/"&gt;http://docs.openstack.org/releasenotes/&lt;/a&gt;. Each library
with configuration options or other deployer-facing interfaces should
set up reno to publish release notes. Not all Oslo libraries will need
to do that.&lt;/p&gt;
&lt;p&gt;The deployer-facing release notes should be written with them in mind,
and only describe features or changes from the perspective of someone
who is not also reading the source code for the library. For example,
it is not necessary to document changes to a library unless they are
visible to the deployer. Changes to configuration options or file
formats should have reno notes. Changes to internal APIs do not need
them. New features and bug fixes should be documented with reno
release notes. For example, changes such as better timeout handling or
reconnection management for messaging or database services should have
reno release notes.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="alternatives-history"&gt;
&lt;h2&gt;Alternatives &amp;amp; History&lt;/h2&gt;
&lt;p&gt;In the past we focused on communicating with developers using Oslo
libraries. This is no longer sufficient, since we now manage
configuration options and other features that are visible to deployers
of software built using Oslo libraries.&lt;/p&gt;
&lt;p&gt;We could add a section to the developer documentation, but this will
make it more difficult to build a single set of release notes for all
of OpenStack, or at the very least link directly to release notes in a
location common to all projects.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="author-s"&gt;
&lt;h3&gt;Author(s)&lt;/h3&gt;
&lt;p&gt;Primary author: doug-hellmann&lt;/p&gt;
&lt;/section&gt;
&lt;section id="milestones"&gt;
&lt;h3&gt;Milestones&lt;/h3&gt;
&lt;p&gt;This policy applies starting with the Mitaka cycle, where we added
reno to oslo.log and oslo.config.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;p&gt;Add reno build instructions and CI jobs to libraries, as needed.&lt;/p&gt;
&lt;/section&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/reno-rollout"&gt;https://etherpad.openstack.org/p/reno-rollout&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="http://lists.openstack.org/pipermail/openstack-dev/2015-November/078301.html"&gt;http://lists.openstack.org/pipermail/openstack-dev/2015-November/078301.html&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="revision-history"&gt;
&lt;h2&gt;Revision 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;Mitaka&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;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This work is licensed under a Creative Commons Attribution 3.0
Unported License.
&lt;a class="reference external" href="http://creativecommons.org/licenses/by/3.0/legalcode"&gt;http://creativecommons.org/licenses/by/3.0/legalcode&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
</description><pubDate>Mon, 22 Feb 2016 00:00:00 </pubDate></item><item><title>Unstable APIs without an incubator</title><link>https://specs.openstack.org/openstack/oslo-specs/specs/mitaka/no-incubator-api-freedom.html</link><description>

&lt;p&gt;We want to get rid of the incubator, but there is no replacement process for
stabilising new APIs.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;The incubator with its copy-paste approach to code has a harmful side to it -
we end up with copied code in a bunch of projects that needs to be updated and
can skew - in particular we not uncommonly find that projects have edited
their local copies and synchronisation is tricky.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;When a new project is started, create the library immediately. Use an API
namespace within the library to offer concurrent access to multiple API
versions during the early evolution of the library, with graduation involving
exposing the API at the top of the library. CI checks will let us evaluate the
impact of removing the interim API versions when consumers no longer use them.&lt;/p&gt;
&lt;p&gt;Project versions that release while using interim versions will cause us to
retain the interim version for some time - in line with normal backward
compatibility concerns.&lt;/p&gt;
&lt;p&gt;Once projects have finished early evolution and are ready to stabilise their
API, they will release a 1.0.0 version a non-namespaced API.&lt;/p&gt;
&lt;section id="api-update-policy"&gt;
&lt;h3&gt;API update policy&lt;/h3&gt;
&lt;p&gt;Non-breaking changes will proceed as normal. Breaking changes during the early
evolution period will create a new API namespace, using a serial number - 1,
2, 3 etc.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="code-structure"&gt;
&lt;h3&gt;Code structure&lt;/h3&gt;
&lt;p&gt;Each unstable API version will be in a subdirectory of the project along with
its tests.&lt;/p&gt;
&lt;p&gt;E.g. if a new library fred has had two unstable API versions, the code tree
would look like:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;fred&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
&lt;span class="n"&gt;fred&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;v1&lt;/span&gt;
&lt;span class="n"&gt;fred&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;tests&lt;/span&gt;
&lt;span class="n"&gt;fred&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;v2&lt;/span&gt;
&lt;span class="n"&gt;fred&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;tests&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Where v2 starts as a copy of v1, and v1 is frozen from that point on.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="using-a-namespaced-version"&gt;
&lt;h3&gt;Using a namespaced version&lt;/h3&gt;
&lt;p&gt;Code should be imported 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="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;fred&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;v1&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;fred&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="entrypoints"&gt;
&lt;h3&gt;Entrypoints&lt;/h3&gt;
&lt;p&gt;Where a library consumes entrypoints as part of its API, while the API is
being namespaced, so must the entrypoints, in the same way:&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;fred&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;extensionname&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;section id="stable-from-start"&gt;
&lt;h4&gt;Stable-from-start&lt;/h4&gt;
&lt;p&gt;We could just apply semver from the very first commit. Folk have expressed
great concern about the impact of development that this would have.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="use-library-name-namespaces"&gt;
&lt;h4&gt;Use library name namespaces&lt;/h4&gt;
&lt;p&gt;Rather than having multiple versions inside one distribution, we could version
the name of the library. E.g. fred0, fred1, fred2 etc until the API
stabilises. This pollutes the global namespace though, and will require lots
of changes to global-requirements, making it high friction.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="impact-on-existing-apis"&gt;
&lt;h3&gt;Impact on Existing APIs&lt;/h3&gt;
&lt;p&gt;We’ll want a tool to warn on the use of older-than-latest api versions in oslo
projects: much like the automated update-from-incubator scripts do today.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;It may be slightly easier to keep using old versions of in-incubation code.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;Packages will git a little bigger (multiple copies of similar code), but the
number of copies on disk will reduce (since they won’t be copied into each
project).&lt;/p&gt;
&lt;/section&gt;
&lt;section id="configuration-impact"&gt;
&lt;h3&gt;Configuration 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;Projects will no longer be able to make local changes to incubated projects
and will instead need to work with oslo to get their changes done centrally
from the start.&lt;/p&gt;
&lt;p&gt;Existing workflows will change, so we need to socialise and communicate
effectively about the change.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing-impact"&gt;
&lt;h3&gt;Testing Impact&lt;/h3&gt;
&lt;p&gt;No impact.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;p&gt;Written at Dims’ request, no current volunteers to execute.&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="milestones"&gt;
&lt;h3&gt;Milestones&lt;/h3&gt;
&lt;p&gt;Target Milestone for completion:&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;Document this somewhere in olso docs&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Write the update / lint thing to check for the latest version being used.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Profit.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="incubation"&gt;
&lt;h2&gt;Incubation&lt;/h2&gt;
&lt;p&gt;N/A - replaces Incubation entirely.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;None that I know of.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;No dependencies, though a mild interaction with the deprecation policy will
happen - in that we’ll be releasing things we want to delete as soon as
possible. See above for details.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This work is licensed under a Creative Commons Attribution 3.0
Unported License.
&lt;a class="reference external" href="http://creativecommons.org/licenses/by/3.0/legalcode"&gt;http://creativecommons.org/licenses/by/3.0/legalcode&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
</description><pubDate>Fri, 20 Nov 2015 00:00:00 </pubDate></item><item><title>Tooz Driver Policy</title><link>https://specs.openstack.org/openstack/oslo-specs/specs/mitaka/tooz-driver-policy.html</link><description>

&lt;p&gt;OpenStack project teams have identified a number of opportunities for making
use of distributed lock managers and the primitives that they provide. Tooz
has traditionally included a number of drivers which meet the bare minimum
requirements for some of these, but are deficient in many ways.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Given the weight that in-tree drivers will carry with users of OpenStack,
there is a desire to ensure that users deploying will only be presented with
choices of high quality that meet all of the requirements of the projects
in OpenStack that consume tooz.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Drivers that are not sufficient must be deprecated and eventually removed
from tooz. They will still be consumable for downstreams of tooz that do
not have the same requirements of all of the OpenStack projects.&lt;/p&gt;
&lt;p&gt;In order to identify which drivers are sufficient, a policy will be added to
the documentation of tooz which provides the requirements for inclusion. This
policy will be modeled on the oslo.messaging drivers policy.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Drivers could be classified in documentation, but kept in-tree. This would
have minimum impact on tooz downstreams, but also add some risk to OpenStack
deployers who might select tooz.&lt;/p&gt;
&lt;p&gt;The API of tooz could also be changed to force callers to express their
needs and allow drivers to specify their assumptions aroune the capabilities
of the tooz backend in use. This would be extremely complex and make tooz
harder to consume.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="impact-on-existing-apis"&gt;
&lt;h3&gt;Impact on Existing APIs&lt;/h3&gt;
&lt;p&gt;The API will be unchanged, but the configuration options available to
downstreams of tooz will be more limited.&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 lower the surface area of tooz slightly.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;Some backends are deficient entirely because they are non-performant or
non-scalable. So this reduces the risk of a user of OpenStack encountering
performance problems.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="configuration-impact"&gt;
&lt;h3&gt;Configuration Impact&lt;/h3&gt;
&lt;p&gt;Some backends will not be available anymore, or will cause deprecation
warnings. The drivers will not be removed for several cycles after
deprecation, so this is a long-term impact.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer Impact&lt;/h3&gt;
&lt;p&gt;Testing requirements on backends will be elevated, so developers will need
to spend more effort on backends, especially on new drivers.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing-impact"&gt;
&lt;h3&gt;Testing Impact&lt;/h3&gt;
&lt;p&gt;Drivers will need to have a higher level of test coverage.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;clint-fewbar (SpamapS)&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="milestones"&gt;
&lt;h3&gt;Milestones&lt;/h3&gt;
&lt;p&gt;Target Milestone for completion:&lt;/p&gt;
&lt;p&gt;mitaka-1&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;Write policy in tooz documentation&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;N/A&lt;/p&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="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;&lt;a class="reference external" href="https://etherpad.openstack.org/p/mitaka-cross-project-dlm"&gt;https://etherpad.openstack.org/p/mitaka-cross-project-dlm&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 work is licensed under a Creative Commons Attribution 3.0
Unported License.
&lt;a class="reference external" href="http://creativecommons.org/licenses/by/3.0/legalcode"&gt;http://creativecommons.org/licenses/by/3.0/legalcode&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
</description><pubDate>Fri, 30 Oct 2015 00:00:00 </pubDate></item><item><title>PBR enhancements to support pip</title><link>https://specs.openstack.org/openstack/oslo-specs/specs/mitaka/pip-pbr.html</link><description>

&lt;p&gt;pip, the Python package installation tool is looking for something very much
like pbr. pbr itself will benefit from the generalisations pip is looking for.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;There are a few places where pbr today doesn’t meet pips needs.&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;pbr requires pbr be easy_installable or pre-installed for both from-git and
from-tarball installations. This is sufficiently fragile that pip wishes to
avoid it from from-tarball situations. pbr has had that requested of it
already by OpenStack users.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;pbr has no way to turn off requirements.txt reflection. This is already
planned as part of converging on upstream practices.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Needs to be able to generate dynamic entry points based on the Python
environment being installed into. e.g. foo, foo2, foo2.7, when installing
into Python 2.7, whether globally or a venv.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;section id="embed-pbr-in-sdists"&gt;
&lt;h3&gt;embed pbr in sdists&lt;/h3&gt;
&lt;p&gt;Via an opt-in option we can embed pbr in the root directory of the sdist. When
run from an sdist, the local directory is first in the Python path and this
will cause the embedded copy of pbr to be found and loaded. The embedding
process will copy a statically defined subset of the pbr source code (and we
may wish to refactor things a little to make this more manageable). pbr’s
non-test code is 128K today uncompressed, 30K compressed - which is tolerable.
Embedding all of pbr permits tests, doc builds and so on to all work from an
sdist.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="opt-out-of-requirements-txt-reflection"&gt;
&lt;h3&gt;opt-out of requirements.txt reflection&lt;/h3&gt;
&lt;p&gt;We’ll add an option, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;skip_requirements_files&lt;/span&gt;&lt;/code&gt; to disable requirements file
reflection. When set requirements will be managed via &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;setup.cfg&lt;/span&gt;&lt;/code&gt; or
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;setup.py&lt;/span&gt;&lt;/code&gt; exclusively. This is in line with our eventual deprecation of
those files.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="entry-point-merging"&gt;
&lt;h3&gt;entry point merging&lt;/h3&gt;
&lt;p&gt;Rather than introducing a template language that wouldn’t be supported by
wheels, we’ll allow setup() to pass in entry points and merge them. That will
prevent this being an attractive-nuisance within OpenStack while still
permitting pip to perform its current workarounds for the lack of entry point
templating in the wider set of tooling.&lt;/p&gt;
&lt;/section&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;Say ‘no, thats not pbr’ to pip. Unnecessary. Growing the ecosystem is part
of OpenStack’s mission.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee/contact:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Robert Collins - lifeless&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;Embedding pbr in sdists.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Opting out of requirements reflection.&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="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;Mitaka&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;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This work is licensed under a Creative Commons Attribution 3.0 Unported License.
&lt;a class="reference external" href="http://creativecommons.org/licenses/by/3.0/legalcode"&gt;http://creativecommons.org/licenses/by/3.0/legalcode&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
</description><pubDate>Wed, 02 Sep 2015 00:00:00 </pubDate></item><item><title>Extend the gettext support of oslo.i18n library</title><link>https://specs.openstack.org/openstack/oslo-specs/specs/liberty/more-gettext-support.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/oslo.i18n/+spec/more-gettext-support"&gt;https://blueprints.launchpad.net/oslo.i18n/+spec/more-gettext-support&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The oslo.i18n library already supports the standard gettext function.&lt;/p&gt;
&lt;p&gt;But the “contextual markers” and “plural form” gettext functions
are needed for translations.
See the Reference - Horizon Translation Wiki.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;The standard gettext function support the most of use cases of translations.&lt;/p&gt;
&lt;p&gt;But there are two situations needed to be addressed:
* different translations of the same English words from different contexts,
such as menu item and label;
* plural form of some languages like English,
different translations are needed for single item or plural items;&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;In python gettext module, “contextual markers” and “plural form” are supported
but without lazy translation support.&lt;/p&gt;
&lt;p&gt;The plan is to add the two features with lazy translation support
in oslo.i18n library.&lt;/p&gt;
&lt;p&gt;oslo.i18n will provide contextual_form and plural_form as additional properties,
and abbreviated forms of the two properties as “_C” and “_P”.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Actually we can translate without using “contextual markers” or “plural form”.&lt;/p&gt;
&lt;p&gt;But in some cases, “contextual markers” can reduce ambiguities, “plural form”
can improve the translation quality.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="impact-on-existing-apis"&gt;
&lt;h3&gt;Impact on Existing APIs&lt;/h3&gt;
&lt;p&gt;The new contextual_form and plural_form properties on TranslatorFactory
will be provided, and exported from the library.&lt;/p&gt;
&lt;p&gt;This spec only covers User Interface strings now, message logs are not
affected.&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="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;For using the new methods, some gettext call _(“str”) needs to be replaced
by _C(“context”, “str”), or _P(“singular”, “plural”, count).&lt;/p&gt;
&lt;p&gt;As new methods requires additional arguments, only user cases where new methods
can improve the translation quality need to switch to use the new methods.&lt;/p&gt;
&lt;p&gt;Most of the code can still use the standard gettext function.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="configuration-impact"&gt;
&lt;h3&gt;Configuration Impact&lt;/h3&gt;
&lt;p&gt;Need to change Jenkins jobs to extract translatable messages with contextual form and plural form.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer Impact&lt;/h3&gt;
&lt;p&gt;This spec only adds more functions to oslo.i18n, developers only need to
switch to the new functions when improving translations.&lt;/p&gt;
&lt;p&gt;If no problem, the code can still use the standard gettext function.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing-impact"&gt;
&lt;h3&gt;Testing 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;alexepico&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;anish-developer&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="milestones"&gt;
&lt;h3&gt;Milestones&lt;/h3&gt;
&lt;p&gt;Target Milestone for completion:&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;extend class Message to support contextual_form and plural_form;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;export contextual_form and plural_form on TranslatorFactory;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;document when and how to use contextual_form or plural_form properties;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;change Jenkins jobs to extract translatable messages with contextual form and plural form;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="incubation"&gt;
&lt;h2&gt;Incubation&lt;/h2&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;section id="adoption"&gt;
&lt;h3&gt;Adoption&lt;/h3&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;section id="library"&gt;
&lt;h3&gt;Library&lt;/h3&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;section id="anticipated-api-stabilization"&gt;
&lt;h3&gt;Anticipated API Stabilization&lt;/h3&gt;
&lt;p&gt;New contextual_form and plural_form properties will be provided on TranslatorFactory from oslo.i18n.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Update the developer documentation for oslo.i18n with examples.&lt;/p&gt;
&lt;p&gt;Translation team needs to translate “contextual markers” and “plural form”
gettext message if used by developers.&lt;/p&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://blueprints.launchpad.net/oslo/+spec/graduate-oslo-i18n"&gt;https://blueprints.launchpad.net/oslo/+spec/graduate-oslo-i18n&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Horizon Translation Wiki:
&lt;a class="reference external" href="https://wiki.openstack.org/wiki/I18n/TranslatableStrings"&gt;https://wiki.openstack.org/wiki/I18n/TranslatableStrings&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Some Experimental Code:
&lt;a class="reference external" href="https://review.openstack.org/134850"&gt;https://review.openstack.org/134850&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This work is licensed under a Creative Commons Attribution 3.0
Unported License.
&lt;a class="reference external" href="http://creativecommons.org/licenses/by/3.0/legalcode"&gt;http://creativecommons.org/licenses/by/3.0/legalcode&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
</description><pubDate>Fri, 10 Jul 2015 00:00:00 </pubDate></item><item><title>Oslo Service Workers for Windows</title><link>https://specs.openstack.org/openstack/oslo-specs/specs/liberty/windows-oslo-service-workers.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/oslo.service/+spec/"&gt;https://blueprints.launchpad.net/oslo.service/+spec/&lt;/a&gt;
windows-oslo-service-workers&lt;/p&gt;
&lt;p&gt;The goal of this blueprint is implement a way which will allow OpenStack
services to run under Windows.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Currently, oslo_service project has a couple of Linux specific implementations,
which makes it impossible to use under Windows. A few examples would be
service.ProcessLauncher, which uses:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;eventlet.greenio.GreenPipe, which it cannot be used, as it tries to set the
pipe as non-blocking, mechanism that does not exist in Windows. [1]&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;os.fork, which does not exist in Windows. [2]&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;An alternative option for forking would be spawning subprocesses by using the
multiprocessing module, which avoids the GIL problem. [3]&lt;/p&gt;
&lt;p&gt;Multiprocessing module still forks the process on Linux systems, which means
that the behaviour will remain consistent with the current implementation.&lt;/p&gt;
&lt;p&gt;The proposed change is that service.ProcessLauncher to spawn
mutliprocessing.Process objects as service workers instead.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Cygwin can be used under Windows [3], which is a collection of tools providing
similar functionality to a “Linux distribution on Windows”.&lt;/p&gt;
&lt;p&gt;The problem is, forking in Cygwin is known to be problematic and inefficient,
as it does not map well on top of the WIN32 API. [4]&lt;/p&gt;
&lt;/section&gt;
&lt;section id="impact-on-existing-apis"&gt;
&lt;h3&gt;Impact on Existing APIs&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="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None, functionality and performance should not change for Linux.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="configuration-impact"&gt;
&lt;h3&gt;Configuration 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="testing-impact"&gt;
&lt;h3&gt;Testing Impact&lt;/h3&gt;
&lt;p&gt;Unit tests.&lt;/p&gt;
&lt;p&gt;CI testing will be performed by Jenkins for Linux and Hyper-V CI for Windows.&lt;/p&gt;
&lt;p&gt;Testing should be done for both Python 2.7 and 3.4, as the implementation of
the multiprocessing module differs greatly. Needed in order not to introduce
regressions for a certain Python version.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Claudiu Belu &amp;lt;&lt;a class="reference external" href="mailto:cbelu%40cloudbasesolutions.com"&gt;cbelu&lt;span&gt;@&lt;/span&gt;cloudbasesolutions&lt;span&gt;.&lt;/span&gt;com&lt;/a&gt;&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="milestones"&gt;
&lt;h3&gt;Milestones&lt;/h3&gt;
&lt;p&gt;Target Milestone for completion:&lt;/p&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;p&gt;As per Proposed Change.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="incubation"&gt;
&lt;h2&gt;Incubation&lt;/h2&gt;
&lt;section id="adoption"&gt;
&lt;h3&gt;Adoption&lt;/h3&gt;
&lt;p&gt;The current services that use the oslo_services module.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="library"&gt;
&lt;h3&gt;Library&lt;/h3&gt;
&lt;p&gt;oslo_service&lt;/p&gt;
&lt;/section&gt;
&lt;section id="anticipated-api-stabilization"&gt;
&lt;h3&gt;Anticipated API Stabilization&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&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="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;multiprocessing&lt;/p&gt;
&lt;p&gt;Version might be different for Python 2.7 and 3.4.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;[1] GreenIO exception&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;&lt;a class="reference external" href="http://paste.openstack.org/show/284115/"&gt;http://paste.openstack.org/show/284115/&lt;/a&gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;[2] os.fork available only on Unix.&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;&lt;a class="reference external" href="https://docs.python.org/2/library/os.html#os.fork"&gt;https://docs.python.org/2/library/os.html#os.fork&lt;/a&gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;[3] multiprocessing module&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;&lt;a class="reference external" href="http://sebastianraschka.com/Articles/2014_multiprocessing_intro.html"&gt;http://sebastianraschka.com/Articles/2014_multiprocessing_intro.html&lt;/a&gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;[4] Cygwin&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;&lt;a class="reference external" href="https://www.cygwin.com/"&gt;https://www.cygwin.com/&lt;/a&gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;[5] Cygwin fork issues:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;&lt;a class="reference external" href="http://cygwin.com/cygwin-ug-net/highlights.html#ov-hi-process"&gt;http://cygwin.com/cygwin-ug-net/highlights.html#ov-hi-process&lt;/a&gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This work is licensed under a Creative Commons Attribution 3.0
Unported License.
&lt;a class="reference external" href="http://creativecommons.org/licenses/by/3.0/legalcode"&gt;http://creativecommons.org/licenses/by/3.0/legalcode&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
</description><pubDate>Fri, 12 Jun 2015 00:00:00 </pubDate></item><item><title>Optional Dependencies</title><link>https://specs.openstack.org/openstack/oslo-specs/specs/liberty/optional-deps.html</link><description>

&lt;p&gt;Projects wish to capture their optional dependencies - things they need only
when specific configuration options are enabled. We need to make sure the
plumbing works for this to allow them to do that.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Python tooling supports ‘extras’ but pbr hasn’t exposed it, and our tooling is
unaware of it.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Add extras to oslo.db exporting the various driver options it uses, and update
keystone to consume those during CI. Deal with any issues, and then open the
floodgates.&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="impact-on-existing-apis"&gt;
&lt;h3&gt;Impact on Existing APIs&lt;/h3&gt;
&lt;p&gt;Folk introspecting requirements.txt will not see the optional dependencies
within a project (but they wouldn’t before either). Dependencies using extras
can already be used (e.g. requests[security]) so this isn’t new in that
dimension.&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="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="configuration-impact"&gt;
&lt;h3&gt;Configuration 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 need to know a little bit more about how Python packaging
works, but not much.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing-impact"&gt;
&lt;h3&gt;Testing 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;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="milestones"&gt;
&lt;h3&gt;Milestones&lt;/h3&gt;
&lt;p&gt;Target Milestone for completion:&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;Raise the cap on pbr to &amp;lt;2.0 everywhere in master, or perhaps uncapped.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Decide whether to centralise the driver choices (e.g. postgresql) into the
oslo library directly using it, or to keep them in the applications, or to
export the choice from the application but centralise the implementation.
Concretely, is it ‘pip install nova oslo.db[mysql]’ or ‘pip install
nova[mysql]’, and should the latter case be defined as ‘mysql: PyMySQL’ or
‘mysql: oslo.db[mysql]’.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Ensure everyone knows to use latest virtualenv packages (the requirements
management spec will be driving that).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Teach update.py to update extras in setup.cfg.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Document the convention of things for test being in the ‘test’ extra (used
via pip install -e .[test]).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add extras to oslo.db.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add use of those to keystone for CI.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Announce the readiness and encourage people to do this.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="incubation"&gt;
&lt;h2&gt;Incubation&lt;/h2&gt;
&lt;p&gt;N/A.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;We need to update some pbr docs, but thats about it AFAIK.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None known.&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;summit session &lt;a class="reference external" href="https://etherpad.openstack.org/p/YVR-oslo-optional-dependencies"&gt;https://etherpad.openstack.org/p/YVR-oslo-optional-dependencies&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;oslo.db patch &lt;a class="reference external" href="https://review.openstack.org/#/c/184328/"&gt;https://review.openstack.org/#/c/184328/&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This work is licensed under a Creative Commons Attribution 3.0
Unported License.
&lt;a class="reference external" href="http://creativecommons.org/licenses/by/3.0/legalcode"&gt;http://creativecommons.org/licenses/by/3.0/legalcode&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
</description><pubDate>Wed, 03 Jun 2015 00:00:00 </pubDate></item><item><title>Change ZeroMQ driver underlying pattern to REQ/REP</title><link>https://specs.openstack.org/openstack/oslo-specs/specs/liberty/zmq-req-rep.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/oslo.messaging/+spec/zmq-req-rep"&gt;https://blueprints.launchpad.net/oslo.messaging/+spec/zmq-req-rep&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Because of too many changes are proposed lately (not only pattern substitution)
this spec actually proposes to provide a parallel implementation of ZeroMQ
driver (zmqv2). The recommended underlying pattern is REQ/REP + ROUTER/DEALER
which will simplify drivers implementation and improve its reliability.
After the implementation there will be a possibility to compare both implementations.&lt;/p&gt;
&lt;p&gt;The key advantage of the legacy zmq driver will be it’s backwards compatibility
and compatibility with older versions of ZeroMQ library (after some fixes).&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Currently ZeroMQ driver actually implements request-reply pattern,
but do it on top of more primitive and less reliable PUSH/PULL.&lt;/p&gt;
&lt;p&gt;The main lack is that PUSH/PULL have no backwards connection for
replying to sender. We send message one way and forget. If we would like
to receive reply we need to establish one more connection.
In current driver implementation it is done over PUB/SUB.
It results in a need of serving for one more socket connection pipeline.
More code to make things work. More probability of connection fails.&lt;/p&gt;
&lt;p&gt;The main reason to change to REQ/REP is that it do all things “out of the box”.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Current ZeroMQ driver implementation uses cross-service zmq_receiver
daemon as a proxy to have a single TCP connection (port) per node.
All messages come to the TCP connection and then are spreading between
services via IPC. The new version will stick to this general architecture.&lt;/p&gt;
&lt;p&gt;So we have three parts to connect:&lt;/p&gt;
&lt;p&gt;rpc_client (REQ) &amp;lt;=&amp;gt; (ROUTER) zmq_receiver (DEALER) &amp;lt;=&amp;gt; (REP) rpc_server&lt;/p&gt;
&lt;p&gt;That is enough for CALL method.&lt;/p&gt;
&lt;p&gt;The advantage of REQ/REP socket is that it implements state machine to
manage requests/replies and sending request when socket is in
“waiting for reply” state causes an exception. So it ideally matches
CALL requirements which should block awaiting reply.&lt;/p&gt;
&lt;p&gt;But this is bad for CAST. Here we can substitute REQ with DEALER which is
async equivalent for REQ. We do not need to wait for reply when we use DEALER,
but we still can receive replies. We even do not need to ignore them, but
use as acknowledge signal that CAST message is delivered successfully.
We also have a possibility to track unacknowledged messages and report
about them if needed. So on this step we can see that reliability of REQ/REP
is higher than with PUSH/PULL. There is some magic needed with REQ envelope
when work with DEALER, but that is not a problem and it is clearly described
in zmq-guide.&lt;/p&gt;
&lt;p&gt;So a chain for CAST will look like the following:&lt;/p&gt;
&lt;p&gt;rpc_client (DEALER) &amp;lt;=&amp;gt; (ROUTER) zmq_receiver (DEALER) &amp;lt;=&amp;gt; (REP) rpc_server&lt;/p&gt;
&lt;p&gt;DEALER is also suits perfectly for CAST with fanout. Message chain remains
the same. And also the same for notifier.&lt;/p&gt;
&lt;p&gt;The rule is simple: if we need to block waiting for request then we use REQ,
otherwise DEALER for sending asynchronous requests. ROUTER is an async
substitution for REP.&lt;/p&gt;
&lt;p&gt;As we are talking about a new driver implementation it’s worth mention that
matchmaking for fanout topics, message formats, proxy daemon will stay,
but refactored. We are going to address such proposals like &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;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;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;, &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;.
&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; Should also be applied here, but as an optimisation, after implementation
is done.&lt;/p&gt;
&lt;p&gt;Configuration options and messaging API should not change, so we could have
possibility to easily use new driver instead of current driver on devstack
(and any other deployment).&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;It is also possible to substitute the pattern inside the current implementation.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="impact-on-existing-apis"&gt;
&lt;h3&gt;Impact on Existing APIs&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="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;Number of connections will be reduced so it may increase performance.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="configuration-impact"&gt;
&lt;h3&gt;Configuration 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;Less code for supporting replies.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing-impact"&gt;
&lt;h3&gt;Testing Impact&lt;/h3&gt;
&lt;p&gt;Existing functional tests should cover this change.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;ozamiatin&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="milestones"&gt;
&lt;h3&gt;Milestones&lt;/h3&gt;
&lt;p&gt;Target Milestone for completion: liberty-3&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;dl class="simple"&gt;
&lt;dt&gt;Implement CALL pipeline and surrounding modules&lt;/dt&gt;&lt;dd&gt;&lt;ul&gt;
&lt;li&gt;&lt;p&gt;package hierarchy according to &lt;a class="footnote-reference brackets" href="#id7" id="id6" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;move message serialization, topics manipulations etc.
from existing implementation to appropriate modules&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;rpc_client part&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;broker_part&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;rpc_server part&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;replies handling&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Implement CAST&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Implement fanout&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Implement notifier&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="incubation"&gt;
&lt;h2&gt;Incubation&lt;/h2&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;section id="adoption"&gt;
&lt;h3&gt;Adoption&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="library"&gt;
&lt;h3&gt;Library&lt;/h3&gt;
&lt;p&gt;oslo.messaging.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="anticipated-api-stabilization"&gt;
&lt;h3&gt;Anticipated API Stabilization&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&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="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;aside class="footnote-list brackets"&gt;
&lt;aside class="footnote brackets" id="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="#id6"&gt;2&lt;/a&gt;)&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/oslo.messaging/+spec/zmq-driver-folder"&gt;https://blueprints.launchpad.net/oslo.messaging/+spec/zmq-driver-folder&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://blueprints.launchpad.net/oslo.messaging/+spec/zmq-context-per-driver-instance"&gt;https://blueprints.launchpad.net/oslo.messaging/+spec/zmq-context-per-driver-instance&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://blueprints.launchpad.net/oslo.messaging/+spec/zmq-work-without-eventlet"&gt;https://blueprints.launchpad.net/oslo.messaging/+spec/zmq-work-without-eventlet&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://blueprints.launchpad.net/oslo.messaging/+spec/zmq-topic-object"&gt;https://blueprints.launchpad.net/oslo.messaging/+spec/zmq-topic-object&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://blueprints.launchpad.net/oslo.messaging/+spec/zmq-socket-reuse"&gt;https://blueprints.launchpad.net/oslo.messaging/+spec/zmq-socket-reuse&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;/aside&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This work is licensed under a Creative Commons Attribution 3.0
Unported License.
&lt;a class="reference external" href="http://creativecommons.org/licenses/by/3.0/legalcode"&gt;http://creativecommons.org/licenses/by/3.0/legalcode&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
</description><pubDate>Tue, 02 Jun 2015 00:00:00 </pubDate></item><item><title>New ZeroMQ driver implementation details</title><link>https://specs.openstack.org/openstack/oslo-specs/specs/liberty/zmq-patterns-usage.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/oslo.messaging/+spec/zmq-patterns-usage"&gt;https://blueprints.launchpad.net/oslo.messaging/+spec/zmq-patterns-usage&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This specification proposes new ZeroMQ driver implementation details.
This proposal may be considered as extension of &lt;a class="footnote-reference brackets" href="#id10" id="id1" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; and further
driver development road-map. Drawings and charts are presented in &lt;a class="footnote-reference brackets" href="#id11" id="id2" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;2&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Oslo.messaging provides a few patterns of communication between components.
These patterns are CAST(FANOUT), CALL and NOTIFY.&lt;/p&gt;
&lt;p&gt;ZeroMQ driver may be implemented in several ways.
Existing driver implementation sticks to a universal socket pipeline approach.
This means that all messaging patterns are implemented over a single socket
pipeline.&lt;/p&gt;
&lt;p&gt;In &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; there were proposed to switch from a splitted universal
forward(PUSH/PULL)+backward(PUB/SUB) pipeline to a unified REQ/REP
bidirectional pipeline. The change simplifies the driver implementation and
makes it more reliable but the pipeline still remains universal.&lt;/p&gt;
&lt;p&gt;The main drawback of the universal pipeline is that it can not be optimized
for some specific messaging pattern. For example, if we would like to
make a FANOUT cast over a universal pipeline (PUSH/PULL or REQ/REP does not matter)
we have to emulate it over a number of direct casts while it could be
done over PUB/SUB zeromq pattern using a single api call.&lt;/p&gt;
&lt;p&gt;This specification proposes to extend new zmq driver implementation
with several specific socket pipelines according to each messaging pattern.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;section id="zmq-proxy"&gt;
&lt;h3&gt;ZMQ Proxy&lt;/h3&gt;
&lt;p&gt;The main reason to have a proxy entity between the client and server
is lack of ability in zmq library to bind several sockets to a single
IP port.&lt;/p&gt;
&lt;p&gt;The alternative path is to use dynamic port binding which in terms of zmq API
means using of a &lt;code class="xref py py-meth docutils literal notranslate"&gt;&lt;span class="pre"&gt;zmq.Socket.bind_to_random_port()&lt;/span&gt;&lt;/code&gt; method.&lt;/p&gt;
&lt;p&gt;Despite the fact that brokerless dynamic port binding seems attractive,
the following serious pitfalls show that the proxy solution is actually
simpler and more reliable.&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Dynamic port binding consumes more time to establish a connection.
Time exceeding may happen if too many ports in a system are busy
and the function needs a lot of retries.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Number of ports is limited to a number of 16-bit integer 2^16 = 65535.
So a number of unoccupied ports may also come to the end especially for
a large-scale clouds.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Less critical but significant complexity is a necessity to notify a
client about the chosen port somehow. Such mechanism may be implemented
using Redis to pass information between nodes. Time for Redis to
sync tables has to be added to a connection time in 1. Here the delay
may be even greater than in 1, because of the network latency.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;All these points makes us to give preference to a proxy solution. It also
has its drawbacks, but advantages are:&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;More predictable time to establish a connection.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Fixed number of ports to allocate for the driver.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;Important point is the proxy should stay as close to the rpc-server as possible
and should be considered as a part of an rpc-server. The proxy is not a central broker
to run it on a separate host even if it would be some kind of a virtual host.&lt;/p&gt;
&lt;p&gt;The proxy communicates with rpc-servers over IPC protocol and shields them from TCP network.
To implement the concept of a &lt;cite&gt;Dedicated socket pipeline&lt;/cite&gt; we can use a separate proxy for
each pipeline to keep them independent.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="dedicated-socket-pipelines"&gt;
&lt;h3&gt;Dedicated Socket Pipelines&lt;/h3&gt;
&lt;p&gt;The main part of a change proposal which complements to &lt;a class="footnote-reference brackets" href="#id10" 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;.
The purpose is to use the most appropriate zmq pattern for oslo.messaging pattern
implementation.&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;REQ/REP (ROUTER/DEALER) for CALL&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;In &lt;a class="footnote-reference brackets" href="#id10" id="id5" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; spec there was proposed to use a socket pipeline built over REQ/REP.
We do not change our mind here and keep this pipeline, but use it only for
CALL pattern purposes.&lt;/p&gt;
&lt;ol class="arabic simple" start="2"&gt;
&lt;li&gt;&lt;p&gt;PUB/SUB for FANOUT CAST&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;PUB socket provides a possibility to publish to a number of connected hosts.
SUB allows to subscribe to a number of publishers listening to a specific topic.
Having a proxy in the middle we actually have 2 steps of FANOUT message passing.
First is TCP between nodes. And the other is local per node between rpc-servers
subscribed to a topic.&lt;/p&gt;
&lt;p&gt;rpc-client(PUB:TCP) -&amp;gt; (XSUB:TCP)proxy(XPUB:IPC) -&amp;gt; (SUB:IPC)rpc-server&lt;/p&gt;
&lt;p&gt;To exactly know which host listens to which topic we need a kind of a directory service (DS)
in the middle of a cloud. The service will most likely reside on a controller node(s).
It may be distributed or stay standalone. Address(es) of the DS should be
passed over config option to the driver.&lt;/p&gt;
&lt;p&gt;Rpc-server listener puts a record to DS about host + topic it listens to.
Rpc-client gets all hosts by topic and publishes a message to them.&lt;/p&gt;
&lt;p&gt;In some sense DS becomes a single point of failure, because FANOUT will not work properly
without DS up and running. So for real-life deployments all standard HA
methods should be applied for the service.&lt;/p&gt;
&lt;p&gt;The first candidate for DS implementation is Redis, but it is not necessarily so.&lt;/p&gt;
&lt;p&gt;It worth noting that using of a DS doesn’t mimic a central-broker concept.
All messages go from node to node directly, therefore we still stay
peer-to-peer on messages level which is important for scalability.
We also don’t waste time requesting DS while using a direct messaging patterns like CALL.
DS state caching on local brokers (proxy) may also help to reduce dependency
on a central node(s). But latter is a kind of optimization matter.&lt;/p&gt;
&lt;ol class="arabic simple" start="3"&gt;
&lt;li&gt;&lt;p&gt;PUSH/PULL for direct CAST&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This is optional, but PUSH/PULL is exact pattern for direct CAST,
so should be the most optimal. Technically direct CAST could be implemented
over any available zmq socket type.&lt;/p&gt;
&lt;ol class="arabic simple" start="4"&gt;
&lt;li&gt;&lt;p&gt;PUB/SUB for Notifier&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The PUB/SUB zeromq pattern well suited for Notifier implementation.
In order to keep socket pipelines as well as messaging patterns implementation independent
from each other we need to make this in a separate pipeline in spite of 2 also uses PUB/SUB.&lt;/p&gt;
&lt;p&gt;Notifier is not as widely used as an RPC (1-3), so this item may be optionally implemented
in next iterations. Ceilometer seems to be the main client of the pattern.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="heartbeats"&gt;
&lt;h3&gt;Heartbeats&lt;/h3&gt;
&lt;p&gt;As we use TCP transport in all patterns we can use ZMQ_TCP_KEEPALIVE
zmq option to detect dead connections.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;All things may be implemented over universal socket pipeline as described in &lt;a class="footnote-reference brackets" href="#id10" id="id6" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="impact-on-existing-apis"&gt;
&lt;h3&gt;Impact on Existing APIs&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 the sake of secure message passing some features from &lt;a class="footnote-reference brackets" href="#id12" id="id7" 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; may be used.&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="configuration-impact"&gt;
&lt;h3&gt;Configuration Impact&lt;/h3&gt;
&lt;p&gt;Configuration options should be added to setup pre-allocated ports.&lt;/p&gt;
&lt;p&gt;9501 - zmq REQ/REP pipeline port
9502 - zmq PUB/SUB CAST+FANOUT port
9503 - zmq PUB/SUB Notifier port
9504 - probably direct CAST port&lt;/p&gt;
&lt;p&gt;fanout_ds_address - address of the name service used by the driver.&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="testing-impact"&gt;
&lt;h3&gt;Testing Impact&lt;/h3&gt;
&lt;p&gt;Unit tests should be rewritten because driver internals will change significantly.&lt;/p&gt;
&lt;p&gt;Existing functional tests should pass without changes.
Maybe we can extend them by adding some more tricky cases.&lt;/p&gt;
&lt;p&gt;We also have py27-func-zeromq configuration to run as CI gate job.
This gate should be used for the new driver to check it.&lt;/p&gt;
&lt;p&gt;We also need some kind of multi-node deployment testing.
Some HA scenarios testing is also needed.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;ozamiatin&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="milestones"&gt;
&lt;h3&gt;Milestones&lt;/h3&gt;
&lt;p&gt;Target Milestone for completion: liberty-3&lt;/p&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;p&gt;Modified work items from &lt;a class="footnote-reference brackets" href="#id10" id="id8" 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;ul class="simple"&gt;
&lt;li&gt;&lt;dl class="simple"&gt;
&lt;dt&gt;Implement CALL (REQ/REP) pipeline and surrounding modules&lt;/dt&gt;&lt;dd&gt;&lt;ul&gt;
&lt;li&gt;&lt;p&gt;move message serialization, topics manipulations etc.
from existing implementation to appropriate modules&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;rpc_client part&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;broker_part&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;rpc_server part&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;replies handling&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Implement CAST over PUSH/PULL pipeline (client-proxy-server)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Implement FANOUT and its PUB/SUB pipeline&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Implement Notifier separate PUB/SUB pipeline&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="incubation"&gt;
&lt;h2&gt;Incubation&lt;/h2&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;section id="adoption"&gt;
&lt;h3&gt;Adoption&lt;/h3&gt;
&lt;p&gt;Deployment guide may slightly differ because of some new config options added
(e.g. additional ports allocated for each pipeline).&lt;/p&gt;
&lt;p&gt;It worth noting that during stabilization period both drivers the old and the
new one will stay in repos. After stabilization is over the old driver will
be deprecated over a standard deprecation path.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="library"&gt;
&lt;h3&gt;Library&lt;/h3&gt;
&lt;p&gt;oslo.messaging&lt;/p&gt;
&lt;/section&gt;
&lt;section id="anticipated-api-stabilization"&gt;
&lt;h3&gt;Anticipated API Stabilization&lt;/h3&gt;
&lt;p&gt;The new driver should successfully run with devstack.
Existing oslo.messaging functional tests should successfully pass in devstack-gate.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;We need to cover all aspects of the new driver with detailed documentation and UML charts.
We need to update zmq deployment guide &lt;a class="footnote-reference brackets" href="#id13" id="id9" 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; for the new driver as well.&lt;/p&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="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;aside class="footnote-list brackets"&gt;
&lt;aside class="footnote brackets" id="id10" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class="backrefs"&gt;(&lt;a role="doc-backlink" href="#id1"&gt;1&lt;/a&gt;,&lt;a role="doc-backlink" href="#id3"&gt;2&lt;/a&gt;,&lt;a role="doc-backlink" href="#id4"&gt;3&lt;/a&gt;,&lt;a role="doc-backlink" href="#id5"&gt;4&lt;/a&gt;,&lt;a role="doc-backlink" href="#id6"&gt;5&lt;/a&gt;,&lt;a role="doc-backlink" href="#id8"&gt;6&lt;/a&gt;)&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://review.openstack.org/#/c/171131/"&gt;https://review.openstack.org/#/c/171131/&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id11" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id2"&gt;2&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="http://www.slideshare.net/davanum/oslomessaging-new-0mq-driver-proposal"&gt;http://www.slideshare.net/davanum/oslomessaging-new-0mq-driver-proposal&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id12" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id7"&gt;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://rfc.zeromq.org/spec:26"&gt;http://rfc.zeromq.org/spec:26&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="#id9"&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://docs.openstack.org/developer/oslo.messaging/zmq_driver.html"&gt;http://docs.openstack.org/developer/oslo.messaging/zmq_driver.html&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;/aside&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This work is licensed under a Creative Commons Attribution 3.0
Unported License.
&lt;a class="reference external" href="http://creativecommons.org/licenses/by/3.0/legalcode"&gt;http://creativecommons.org/licenses/by/3.0/legalcode&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
</description><pubDate>Mon, 01 Jun 2015 00:00:00 </pubDate></item><item><title>oslo.messaging: remove ending message for rpc reply</title><link>https://specs.openstack.org/openstack/oslo-specs/specs/liberty/oslo.messaging-remove-double-reply.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/oslo.messaging?searchtext=remove-double-reply"&gt;https://blueprints.launchpad.net/oslo.messaging?searchtext=remove-double-reply&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;We are going to send a single message for RPC reply.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Currently, when we wait for a RPC reply, for each msg_id we receive two AMQP
messages - first one with the payload, a second one to ensure the other have
finish to send the payload. This was made because a long time ago ‘reply’
allowed generator as payload to send multiple messages on one ‘rpc.call’ -
see &lt;a class="footnote-reference brackets" href="#id3" id="id1" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Oslo.messaging do not support providing a generator as the payload - it send
reply with data and then reply with ending - so it becomes useless to double
RPC messages for each call. Based on this suggestions, so we are going to
remove the second AMQP message sending.&lt;/p&gt;
&lt;p&gt;This change will be not backward compatible, so we have to choice how we handle
this backward compatibility and the deprecation. This spec is the proposed
change about that.&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 is not backward compatible, so we need to make sure that there is
some way to run mixed versions of services, where version N can always talk to
N+1 and the reverse, so that we can do rolling upgrades.&lt;/p&gt;
&lt;section id="plan-for-the-rolling-upgrade"&gt;
&lt;h3&gt;Plan for the rolling upgrade:&lt;/h3&gt;
&lt;section id="in-kilo"&gt;
&lt;h4&gt;In Kilo:&lt;/h4&gt;
&lt;p&gt;The old behavior, fully compatible with Liberty and older versions.&lt;/p&gt;
&lt;p&gt;RPC-server sends reply in two messages, can reply to clients, versions &amp;lt;= L+1.
RPC-client expects replies in two messages, can receive replies from servers
with versions &amp;lt;= L.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="in-liberty"&gt;
&lt;h4&gt;In Liberty:&lt;/h4&gt;
&lt;p&gt;We are going to implement a new behavior, but keep the old one by default.
Fully compatible with Kilo and older versions.&lt;/p&gt;
&lt;p&gt;We change the ReplyWaiters to handle reply in one message and two messages,
like it does &lt;a class="footnote-reference brackets" href="#id4" id="id2" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;2&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;We create a boolean configuration option, defaulted to False. If this one is
True, we sent the reply in one message otherwise we keep the current behavior
of two messages. This config option will allow us to test the both - old and
new - behavior into our tests suite and allow to enable this new behavior
earlier. So this is only dedicated for early adopter and testing.
This options is not need in normal upgrade workflow and must be removed as soon
as we enable the new behavior by default to be sure that deployed cloud with
L+1 will not break when they are upgraded to L+2 because cloud operator
enforced the old behavior.&lt;/p&gt;
&lt;p&gt;RPC-server sends reply in two messages, can reply to &amp;lt;= L+1
RPC-client expects replies in two messages or one message, can receive replies
from all versions&lt;/p&gt;
&lt;/section&gt;
&lt;section id="in-m-release-cycle"&gt;
&lt;h4&gt;In M release cycle:&lt;/h4&gt;
&lt;p&gt;We are going to enable the new behavior by default, remove the config option
and support only the reply in one message. This will break backward
compatibility with oslo.messaging &amp;lt;= kilo and oslo-incubator RPC legacy code.&lt;/p&gt;
&lt;p&gt;rpc-server sends reply in one messages, can reply to &amp;gt;= L
rpc-client expects replies in two messages or one messages from all versions&lt;/p&gt;
&lt;/section&gt;
&lt;section id="in-n-release-cycle"&gt;
&lt;h4&gt;In N release cycle:&lt;/h4&gt;
&lt;p&gt;We are going to remove legacy code that allow to receive replies from &amp;lt;= L.&lt;/p&gt;
&lt;p&gt;rpc-server sends reply in one messages, can reply to &amp;gt;= L+1
rpc-client expects replies in one messages, can receive replies from &amp;gt;= L+1&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Using the oslo.messaging payload version.
But this have been designed for the content of the message itself.
Not really for this purpose. And the deserialization occurs in the lower
layer of oslo.messaging. When we handle the reply the version fields have
already been removed.&lt;/p&gt;
&lt;p&gt;This breaks backward compatibility too.&lt;/p&gt;
&lt;p&gt;We can already track the old and the new format because the old format has
the attribute “result” OR “ending” the new one will have “result” AND
“ending”.&lt;/p&gt;
&lt;p&gt;Note that issue is in the RPC call replies code. In case of rolling upgrade, we
have to think about the fact that the client will wait message that can
come from same or upper version of oslo.messaging. We already do not support
lower versions from the application PoV.&lt;/p&gt;
&lt;p&gt;Or from the server point of view, we will send reply that must be
understandable by a wide panel of versions.&lt;/p&gt;
&lt;p&gt;This is the first time (I guess), we encounter this kind of issue, some other
bugs need to break the backward compatibility to be fixed, too.
(Because we need to change RabbitMQ queue attributes or move a queue to
another exchange)&lt;/p&gt;
&lt;p&gt;The main goal is to choose the backward compatible versions count and use
the same kind of deprecation in other changes like this one.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="impact-on-existing-apis"&gt;
&lt;h3&gt;Impact on Existing APIs&lt;/h3&gt;
&lt;p&gt;NA&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;NA&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;This will reduce by 2 the number of reply messages that will transit on a
RabbitMQ/QPID cluster.
Local performance tests shows, that this change brings nearly 30 percent
increase in the number of RPC &lt;cite&gt;call&lt;/cite&gt; messages per second.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="configuration-impact"&gt;
&lt;h3&gt;Configuration Impact&lt;/h3&gt;
&lt;p&gt;A hidden configuration option will allow to switch to the future behavior
for early adopter and for testing purpose.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer Impact&lt;/h3&gt;
&lt;p&gt;NA&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing-impact"&gt;
&lt;h3&gt;Testing Impact&lt;/h3&gt;
&lt;p&gt;We must test that the new ReplyWaiters code can handle reply that come from
a oslo.messaging version that sent reply in one message and from the one
that sent the reply into two messages. This is driver specific change, so we
should implement this in unittests.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;vsergeyev&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;sileht&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="milestones"&gt;
&lt;h3&gt;Milestones&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Target Milestone for completion:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Liberty for the step 1
M or N for the step 2&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;Change the ReplyWaiters to handle reply in one message and two messages.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add a config option and change the _send_reply() method to allow sent reply
and &lt;cite&gt;ending&lt;/cite&gt; in a single message, based on config option.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Remove the config option and enable the new behavior by default.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Remove the &lt;cite&gt;ending&lt;/cite&gt; parameter procession from the ReplyWaiters.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="incubation"&gt;
&lt;h2&gt;Incubation&lt;/h2&gt;
&lt;p&gt;NA&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Inform deployer about future incompatibility with a too old oslo.messaging
version&lt;/p&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;NA&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;aside class="footnote-list brackets"&gt;
&lt;aside class="footnote brackets" id="id3" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id1"&gt;1&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;Legacy oslo rpc behavior: &lt;a class="reference external" href="https://github.com/openstack/oslo-incubator/blob/stable/icehouse/openstack/common/rpc/amqp.py#L461-L470"&gt;https://github.com/openstack/oslo-incubator/blob/stable/icehouse/openstack/common/rpc/amqp.py#L461-L470&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="id4" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="#id2"&gt;2&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;Refactor processing reply in ReplyWaiter: &lt;a class="reference external" href="https://review.openstack.org/#/c/180583/"&gt;https://review.openstack.org/#/c/180583/&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;/aside&gt;
&lt;p&gt;WIP reviews:&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/180542/"&gt;https://review.openstack.org/#/c/180542/&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/180583/"&gt;https://review.openstack.org/#/c/180583/&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This work is licensed under a Creative Commons Attribution 3.0
Unported License.
&lt;a class="reference external" href="http://creativecommons.org/licenses/by/3.0/legalcode"&gt;http://creativecommons.org/licenses/by/3.0/legalcode&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
</description><pubDate>Thu, 07 May 2015 00:00:00 </pubDate></item><item><title>Creating/adopting automaton</title><link>https://specs.openstack.org/openstack/oslo-specs/specs/liberty/adopt-automaton.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/oslo.utils/+spec/adopt-automaton"&gt;https://blueprints.launchpad.net/oslo.utils/+spec/adopt-automaton&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The goal of this library would be to provide a well documented
state machine classes/utilities that start off with the a basic set and
can expand into a larger set as time goes on. The state machine pattern (or
the implemented variation there-of) is a commonly used pattern and has a
multitude of various usages.&lt;/p&gt;
&lt;p&gt;Some of the current usages for it (that are being actively pursued):&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Provided state &amp;amp; transition validation for &lt;a class="reference external" href="https://github.com/openstack/ironic/blob/master/ironic/common/states.py"&gt;ironic&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Providing state &amp;amp; transition validation &amp;amp; running/scheduling/analysis of
the execution of &lt;a class="reference external" href="http://docs.openstack.org/developer/taskflow/"&gt;taskflow&lt;/a&gt; engines.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The code for this library was extracted from taskflow and has been copied into
ironic and appears to be a key part of that projects states work where it is
now serving a useful purpose there; so I would consider the API mostly
stable (ironic is not currently using the FSM runner properties while taskflow
would be/is). The code/mini-library was recently split off into
&lt;a class="reference external" href="https://github.com/harlowja/automaton"&gt;https://github.com/harlowja/automaton&lt;/a&gt; where it has been developed and
isolated (the tests extracted for example, a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;setup.py&lt;/span&gt;&lt;/code&gt; added and &lt;a class="reference external" href="http://docs.openstack.org/developer/pbr/"&gt;pbr&lt;/a&gt;
integrated…) and it has &lt;a class="reference external" href="https://travis-ci.org/harlowja/automaton"&gt;travis-ci&lt;/a&gt; running against it for testing
integration (this would no longer be needed as the openstackci serves a
similar/equivalent purpose).&lt;/p&gt;
&lt;section id="library-name"&gt;
&lt;h2&gt;Library Name&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;automaton&lt;/em&gt;&lt;/p&gt;
&lt;/section&gt;
&lt;section id="contents"&gt;
&lt;h2&gt;Contents&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;automaton/__init__.py&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;automaton/exceptions.py&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;automaton/machines.py&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;This is the &lt;em&gt;main file&lt;/em&gt; that contains a finite state machine and a
hierarchical state machine and associated run classes that can be used to
run the state machines until they terminate; this usage of these runners
is optional and is not necessary to use the machines for state and
transition processing and/or validation.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For those wondering what a hierarchical state machine is the following
can be referred to about it (the concepts are similar to what is described
in the following slide-set).&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="http://www.cis.upenn.edu/~lee/06cse480/lec-HSM.pdf"&gt;http://www.cis.upenn.edu/~lee/06cse480/lec-HSM.pdf&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="early-adopters"&gt;
&lt;h2&gt;Early Adopters&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Taskflow&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Ironic&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Others?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="public-api"&gt;
&lt;h2&gt;Public API&lt;/h2&gt;
&lt;p&gt;Currently the machine &lt;em&gt;public&lt;/em&gt; API is the following:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;FiniteMachine
    - runner (read-only property)
    - default_start_state (read/write property)
    - current_state (read-only property)
    - terminated (read-only property)
    - add_state(state, terminal=False, on_enter=None, on_exit=None)
    - add_reaction(state, event, reaction, *args, **kwargs)
    - add_transition(start, end, event)
    - process_event(event) -- main function/method!!
    - initialize(start_state=None)
    - copy(shallow=False, unfreeze=False)
    - freeze()
    - frozen (read/write property)
    - states (read-only property)
    - events (read-only property)
    - pformat(sort=True, empty='.')

HierarchicalFiniteMachine(FiniteMachine)
    - runner (read-only property)
    - add_state(state, terminal=False,
                on_enter=None, on_exit=None, machine=None)
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The runners of each state machine have the following &lt;em&gt;public&lt;/em&gt; API:&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;run(event,&lt;/span&gt; &lt;span class="pre"&gt;initialize=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;run_iter(event,&lt;/span&gt; &lt;span class="pre"&gt;initialize=True)&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Further API documentation (that is likely more readable and better commented)
can be found at:&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://github.com/harlowja/automaton"&gt;https://github.com/harlowja/automaton&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Or from the live taskflow docs (that are using a slightly older
version of the machines, minus a couple API adjustments; nothing major
changed though):&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="http://docs.openstack.org/developer/taskflow/types.html#module-taskflow.types.fsm"&gt;http://docs.openstack.org/developer/taskflow/types.html#module-taskflow.types.fsm&lt;/a&gt;&lt;/p&gt;
&lt;/section&gt;
&lt;section id="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;Harlowja&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;You?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="primary-maintainer"&gt;
&lt;h3&gt;Primary maintainer&lt;/h3&gt;
&lt;p&gt;Primary maintainer:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Harlowja (until further notice).&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;Praneshp (@yahoo)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="security-contact"&gt;
&lt;h3&gt;Security Contact&lt;/h3&gt;
&lt;p&gt;Security Contact: harlowja&lt;/p&gt;
&lt;/section&gt;
&lt;section id="milestones"&gt;
&lt;h3&gt;Milestones&lt;/h3&gt;
&lt;p&gt;Target Milestone for completion: liberty-1&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 launchpad project&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Change owner of Launchpad project (make it part of the Oslo projectgroup)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Give openstackci Owner permissions on PyPI&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create Initial Repository&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Make the library do something&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update the README.rst&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Publish git repo&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Oslo team review new repository&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Infra project configuration&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update Gerrit Groups and ACLs&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;openstack-infra/devstack-gate adjustments&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;openstack/requirements projects.txt adjustments&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update project list on docs.openstack.org&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Tag a release&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Profit!&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="adoption-notes"&gt;
&lt;h2&gt;Adoption Notes&lt;/h2&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;section id="requirements"&gt;
&lt;h3&gt;Requirements&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;python 2.6 –&amp;gt; 3.4 (and beyond!)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;ordereddict (only needed on python 2.6)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;pbr&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;prettytable&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;six&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;All of the currently planned dependencies are in the requirements repository.&lt;/p&gt;
&lt;/div&gt;
&lt;/section&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;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This work is licensed under a Creative Commons Attribution 3.0
Unported License.
&lt;a class="reference external" href="http://creativecommons.org/licenses/by/3.0/legalcode"&gt;http://creativecommons.org/licenses/by/3.0/legalcode&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
</description><pubDate>Thu, 16 Apr 2015 00:00:00 </pubDate></item><item><title>Graduating fileutils</title><link>https://specs.openstack.org/openstack/oslo-specs/specs/liberty/graduate-fileutils.html</link><description>

&lt;p&gt;blueprint: &lt;a class="reference external" href="https://blueprints.launchpad.net/oslo-incubator/+spec/graduate-oslo-io"&gt;https://blueprints.launchpad.net/oslo-incubator/+spec/graduate-oslo-io&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;summary: move the fileutils code (and associated tests) into oslo.utils&lt;/p&gt;
&lt;section id="library-name"&gt;
&lt;h2&gt;Library Name&lt;/h2&gt;
&lt;p&gt;oslo.utils and oslo.policy&lt;/p&gt;
&lt;/section&gt;
&lt;section id="contents"&gt;
&lt;h2&gt;Contents&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;openstack/common/fileutils.py&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;tests/unit/test_fileutils.py&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="early-adopters"&gt;
&lt;h2&gt;Early Adopters&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;keystone&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="public-api"&gt;
&lt;h2&gt;Public API&lt;/h2&gt;
&lt;p&gt;fileutils.py has only 7 functions and 1 global. Their usage, and
graduation plan will be broken down below.&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;ensure_tree()&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;used by nova/cinder/ironic&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;to be added to oslo.utils&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;ol class="arabic simple" start="2"&gt;
&lt;li&gt;&lt;p&gt;delete_if_exists()&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;used extensively in nova and cinder and a bit in neutron&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;to be added to oslo.utils&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;ol class="arabic simple" start="3"&gt;
&lt;li&gt;&lt;p&gt;remove_path_on_error()&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;used by nova/cinder/ironic&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;to be added to oslo.utils&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;ol class="arabic simple" start="4"&gt;
&lt;li&gt;&lt;p&gt;write_to_tempfile()&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;used sparingly in keystone and ceilometer (tests only)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;consider deprecation&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;ol class="arabic simple" start="5"&gt;
&lt;li&gt;&lt;p&gt;file_open&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;used extensively in cinder&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;can be replaced with just an open() call&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;consider deprecation&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;ol class="arabic simple" start="6"&gt;
&lt;li&gt;&lt;p&gt;read_cached_file()&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;used only by nova’s policy engine, and by oslo.policy&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;can push both of these into oslo.policy and when/if nova switches to
oslo.policy, they will no longer require these functions.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;ol class="arabic simple" start="7"&gt;
&lt;li&gt;&lt;p&gt;delete_cached_file()&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;same as above.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;ol class="arabic simple" start="8"&gt;
&lt;li&gt;&lt;p&gt;DEFAULT_MODE&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;not being referred to, can be marked as private.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;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 Martinelli (stevemar)&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="primary-maintainer"&gt;
&lt;h3&gt;Primary Maintainer&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary Maintainer:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Steve Martinelli (stevemar)&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="security-contact"&gt;
&lt;h3&gt;Security Contact&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Security Contact:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Doug Hellmann (doug-hellmann)&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="milestones"&gt;
&lt;h3&gt;Milestones&lt;/h3&gt;
&lt;p&gt;Liberty-1&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;&lt;a class="reference external" href="https://wiki.openstack.org/wiki/Oslo/CreatingANewLibrary#Checklist"&gt;https://wiki.openstack.org/wiki/Oslo/CreatingANewLibrary#Checklist&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="adoption-notes"&gt;
&lt;h2&gt;Adoption Notes&lt;/h2&gt;
&lt;p&gt;Projects currently importing:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;openstack.common&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;fileutils&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;would have to switch to importing:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;oslo_utils&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;fileutils&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;if using:&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;fileutils&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;file_open&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;switch to:&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;open&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;if using:&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;fileutils&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read_cached_file&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;switch to:&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;oslo_policy&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&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="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/kilo-oslo-library-proposals"&gt;https://etherpad.openstack.org/p/kilo-oslo-library-proposals&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;WIP patch &lt;a class="reference external" href="https://review.openstack.org/#/c/154975/"&gt;https://review.openstack.org/#/c/154975/&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This work is licensed under a Creative Commons Attribution 3.0
Unported License.
&lt;a class="reference external" href="http://creativecommons.org/licenses/by/3.0/legalcode"&gt;http://creativecommons.org/licenses/by/3.0/legalcode&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
</description><pubDate>Sat, 04 Apr 2015 00:00:00 </pubDate></item><item><title>Graduating versionutils to oslo.log</title><link>https://specs.openstack.org/openstack/oslo-specs/specs/liberty/graduate-oslo-versionutils.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/oslo?searchtext=graduate-oslo-versionutils"&gt;https://blueprints.launchpad.net/oslo?searchtext=graduate-oslo-versionutils&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The versionutils module contains tools for reporting deprecations of
features at OpenStack release cycle boundaries. It is being added to
oslo.log because it is not large enough to make sense to manage as a
library on its own, and the primary use is as a logging helper
function.&lt;/p&gt;
&lt;section id="library-name"&gt;
&lt;h2&gt;Library Name&lt;/h2&gt;
&lt;p&gt;What is the name of the new library?: oslo.log and oslo.utils&lt;/p&gt;
&lt;/section&gt;
&lt;section id="contents"&gt;
&lt;h2&gt;Contents&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;openstack/common/versionutils.py&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;tests/unit/test_versionutils.py&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="early-adopters"&gt;
&lt;h2&gt;Early Adopters&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="public-api"&gt;
&lt;h2&gt;Public API&lt;/h2&gt;
&lt;p&gt;The &lt;code class="xref py py-func docutils literal notranslate"&gt;&lt;span class="pre"&gt;deprecated()&lt;/span&gt;&lt;/code&gt; decorator and &lt;code class="xref py py-func docutils literal notranslate"&gt;&lt;span class="pre"&gt;report_deprecated_feature()&lt;/span&gt;&lt;/code&gt;
will be available through &lt;code class="xref py py-mod docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo_log.versionutils&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;code class="xref py py-func docutils literal notranslate"&gt;&lt;span class="pre"&gt;is_compatible()&lt;/span&gt;&lt;/code&gt; will be added to &lt;code class="xref py py-mod docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo_utils.versionutils&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="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: Doug Hellmann&lt;/p&gt;
&lt;p&gt;Other contributors: None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="primary-maintainer"&gt;
&lt;h3&gt;Primary Maintainer&lt;/h3&gt;
&lt;p&gt;Primary Maintainer: Existing library maintainers&lt;/p&gt;
&lt;p&gt;Other Contributors: None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-contact"&gt;
&lt;h3&gt;Security Contact&lt;/h3&gt;
&lt;p&gt;Security Contact: Existing contacts&lt;/p&gt;
&lt;/section&gt;
&lt;section id="milestones"&gt;
&lt;h3&gt;Milestones&lt;/h3&gt;
&lt;p&gt;Target Milestone for completion: liberty-1&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;Extract the history for the versionutils code into a new
repository.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Import that history into a branch of the oslo.log repo. The changes
in the branch will need to be submitted to gerrit for review, but
we can fast-approve them because they have already been reviewed in
the incubator.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Merge the branch into master, with accompanying fixes to make the
tests work.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Remove &lt;code class="xref py py-func docutils literal notranslate"&gt;&lt;span class="pre"&gt;is_compatible()&lt;/span&gt;&lt;/code&gt; from oslo.log.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Import that history into a branch of the oslo.utils repo. The changes
in the branch will need to be submitted to gerrit for review, but
we can fast-approve them because they have already been reviewed in
the incubator.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Merge the branch into master, with accompanying fixes to make the
tests work.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Remove the parts of versionutils not related to
&lt;code class="xref py py-func docutils literal notranslate"&gt;&lt;span class="pre"&gt;is_compatible()&lt;/span&gt;&lt;/code&gt; from oslo.utils.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Release both oslo.log and oslo.utils.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Remove versionutils from the incubator.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="adoption-notes"&gt;
&lt;h2&gt;Adoption Notes&lt;/h2&gt;
&lt;p&gt;Most applications will already be using versionutils, and the API
won’t be changing, so adoption should be fairly straightforward.&lt;/p&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="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Discussing git/gerrit techniques with the infra team starting at
2015-03-25T18:48:19 in
&lt;a class="reference external" href="http://eavesdrop.openstack.org/irclogs/%23openstack-infra/%23openstack-infra.2015-03-25.log"&gt;http://eavesdrop.openstack.org/irclogs/%23openstack-infra/%23openstack-infra.2015-03-25.log&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Patches for review in oslo.log: &lt;a class="reference external" href="https://review.openstack.org/#/q/project:openstack/oslo.log+topic:bp/graduate-oslo-versionutils,n,z"&gt;https://review.openstack.org/#/q/project:openstack/oslo.log+topic:bp/graduate-oslo-versionutils,n,z&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Patches for review in oslo.utils: &lt;a class="reference external" href="https://review.openstack.org/#/q/project:openstack/oslo.utils+topic:bp/graduate-oslo-versionutils,n,z"&gt;https://review.openstack.org/#/q/project:openstack/oslo.utils+topic:bp/graduate-oslo-versionutils,n,z&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This work is licensed under a Creative Commons Attribution 3.0
Unported License.
&lt;a class="reference external" href="http://creativecommons.org/licenses/by/3.0/legalcode"&gt;http://creativecommons.org/licenses/by/3.0/legalcode&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
</description><pubDate>Wed, 25 Mar 2015 00:00:00 </pubDate></item><item><title>oslo.log: Quiet Libraries</title><link>https://specs.openstack.org/openstack/oslo-specs/specs/liberty/oslo.log-quiet-libraries.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/oslo?searchtext=quiet-libraries"&gt;https://blueprints.launchpad.net/oslo?searchtext=quiet-libraries&lt;/a&gt;&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;As we add more dependencies, we find more cases where we need to
customize the logging output for those libraries. Rather than forcing
applications to manage their own list of customizations, and rather
than having a single large list of customizations in oslo.log, we
should change the way we configure the logger tree so that libraries
are quiet by default.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;We currently attach a logging handler to the root logging node and
configure it to emit output to whatever source the user has specified
(a file, syslog, etc.) using a default log level. We then use the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;default_log_levels&lt;/span&gt;&lt;/code&gt; option to specify different default settings
for other libraries, usually to quiet them so that output is only
produced at warning or higher levels. This configuration takes
advantage of the fact that Python’s logging module configures the
loggers in a tree structure, where messages move up the tree until
they find a node that handles them.&lt;/p&gt;
&lt;p&gt;That gives us a logger structure like:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&amp;lt;root&amp;gt; - INFO&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;myapp (messages propagate up to &amp;lt;root&amp;gt;)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;amqp - WARN&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;amqplib - WARN&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;boto - WARN&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;qpid - WARN&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;sqlalchemy - WARN&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;suds - INFO&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;oslo&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;messaging - INFO&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;iso8601 - WARN&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;requests&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;packages&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;urllib3&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;connectionpool - WARN&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;urllib3&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;util&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;retry - WARN&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;keystonemiddleware - WARN&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;routes&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;middleware - WARN&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;stevedore - WARN&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;One drawback to this approach is that new versions of libraries affect
the log content and the settings to control them need to be updated
fairly frequently. This problem will increase as we start to support
more drivers with additional third-party dependencies.&lt;/p&gt;
&lt;p&gt;To solve the problem, we configure the loggers so that the root
node always only emits data at WARN or higher, and then configure a
logger named for the base package of the application to emit messages
at the level requested by the logging configuration flags
(&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;--debug&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;--verbose&lt;/span&gt;&lt;/code&gt;, etc.).&lt;/p&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;default_log_levels&lt;/span&gt;&lt;/code&gt; option will still be supported, but any
libraries with custom output levels managed through
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;default_log_levels&lt;/span&gt;&lt;/code&gt; can be ignored unless their output level is
different than WARN. This is a minor optimization in the configuration
setup, though, so we don’t need to implement it.&lt;/p&gt;
&lt;p&gt;The result would look more like:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&amp;lt;root&amp;gt; - WARN&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;myapp - INFO (has a local handler)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;suds - INFO&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;oslo - INFO&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The other loggers still exist, but they wouldn’t need custom
configuration. They could still be given levels based on the
configuration options, in case that turns out to be useful.&lt;/p&gt;
&lt;p&gt;Moving all of the Oslo library loggers under the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo&lt;/span&gt;&lt;/code&gt; part of the
logger tree will require a little custom logic in
&lt;code class="xref py py-func docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo_log.log.getLogger()&lt;/span&gt;&lt;/code&gt; to replace &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;"oslo_library"&lt;/span&gt;&lt;/code&gt; with
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;"oslo.library"&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;section id="don-t-place-oslo-libraries-under-a-common-node"&gt;
&lt;h4&gt;Don’t Place Oslo Libraries Under a Common Node&lt;/h4&gt;
&lt;p&gt;We could keep the Oslo libraries logging under their own
library-specific names &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo_config&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo_concurrency&lt;/span&gt;&lt;/code&gt;,
etc. However, this makes it more difficult to configure them to all
log at a consistent level. Because the Oslo library code is a growing
part of the overall OpenStack code base, and errors frequently require
information about the libraries’ behavior to debug, having them all
under a single common node makes it easy to adjust the log output.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="leave-things-alone"&gt;
&lt;h4&gt;Leave Things Alone&lt;/h4&gt;
&lt;p&gt;We do have &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;default_log_levels&lt;/span&gt;&lt;/code&gt; and the ability to configure logging
through a file instead of just configuration flags, so deployers could
set this up themselves. However, the default behavior of oslo.log is
supposed to represent a useful configuration for &lt;em&gt;most&lt;/em&gt; deployers, so
making the change there is better than asking each deployer to figure
it out for themselves.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="set-root-logger-level-to-error"&gt;
&lt;h4&gt;Set Root Logger Level to ERROR&lt;/h4&gt;
&lt;p&gt;Rather than using WARN as the default level for the root logger, we
could use ERROR or even CRITICAL. This would further reduce the extra
output, but WARN seems like it should be good enough for most
libraries that we are using now. We can evaluate changing the level
after the main part of the work is done, since it will be a simple
change to experiment with at that point.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="add-configuration-option-for-root-logger-level"&gt;
&lt;h4&gt;Add Configuration Option for Root Logger Level&lt;/h4&gt;
&lt;p&gt;Rather than hard-coding the level of the root logger, we could use a
configuration option to let the deployer control it. We can evaluate
this alternative after the main part of the work is done, since it
will be a simple change to experiment with at that point.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="impact-on-existing-apis"&gt;
&lt;h3&gt;Impact on Existing APIs&lt;/h3&gt;
&lt;p&gt;No API changes.&lt;/p&gt;
&lt;p&gt;We already have the application name as the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;product_name&lt;/span&gt;&lt;/code&gt; argument
to &lt;code class="xref py py-func docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo_log.log.setup()&lt;/span&gt;&lt;/code&gt;, so we can use it to set up the
application’s primary log handler.&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="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="configuration-impact"&gt;
&lt;h3&gt;Configuration Impact&lt;/h3&gt;
&lt;p&gt;All of the existing configuration options will continue to produce the
same results.&lt;/p&gt;
&lt;p&gt;We can eventually change the default value of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;default_log_levels&lt;/span&gt;&lt;/code&gt;,
although that’s not necessary at first.&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="testing-impact"&gt;
&lt;h3&gt;Testing Impact&lt;/h3&gt;
&lt;p&gt;We will want to verify that the log output doesn’t increase
significantly when we change the default behavior for the Oslo
libraries.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="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: Doug Hellmann&lt;/p&gt;
&lt;p&gt;Other contributors: None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="milestones"&gt;
&lt;h3&gt;Milestones&lt;/h3&gt;
&lt;p&gt;Target Milestone for completion: Liberty-2&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;Modify the setup code to create separate root and application
loggers with their own handlers.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Modify &lt;code class="xref py py-func docutils literal notranslate"&gt;&lt;span class="pre"&gt;getLogger()&lt;/span&gt;&lt;/code&gt; to handle the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;"oslo_"&lt;/span&gt;&lt;/code&gt; to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;"oslo."&lt;/span&gt;&lt;/code&gt;
conversion.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="incubation"&gt;
&lt;h2&gt;Incubation&lt;/h2&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;section id="adoption"&gt;
&lt;h3&gt;Adoption&lt;/h3&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;section id="library"&gt;
&lt;h3&gt;Library&lt;/h3&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;section id="anticipated-api-stabilization"&gt;
&lt;h3&gt;Anticipated API Stabilization&lt;/h3&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;The proposed change affects the default log levels, but all of the
configuration options will work in the same way so no documentation
changes should be needed.&lt;/p&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="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Python’s logging module: &lt;a class="reference external" href="https://docs.python.org/2/library/logging.html"&gt;https://docs.python.org/2/library/logging.html&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Brant Knudson’s patch to make the default logger list expandable
through &lt;code class="xref py py-func docutils literal notranslate"&gt;&lt;span class="pre"&gt;set_defaults()&lt;/span&gt;&lt;/code&gt;: &lt;a class="reference external" href="https://review.openstack.org/#/c/164503"&gt;https://review.openstack.org/#/c/164503&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This work is licensed under a Creative Commons Attribution 3.0
Unported License.
&lt;a class="reference external" href="http://creativecommons.org/licenses/by/3.0/legalcode"&gt;http://creativecommons.org/licenses/by/3.0/legalcode&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
</description><pubDate>Mon, 16 Mar 2015 00:00:00 </pubDate></item><item><title>Refactor Test Base Class in oslotest</title><link>https://specs.openstack.org/openstack/oslo-specs/specs/liberty/oslotest-refactor-test-base-class.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/oslo?searchtext=oslotest-refactor"&gt;https://blueprints.launchpad.net/oslo?searchtext=oslotest-refactor&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;As a general policy we want to avoid requiring projects to use test
base classes defined in libraries they do not control. Test fixtures
are more composable, and easier to test themselves.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Copied from &lt;a class="reference internal" href="../policy/test-tools.html"&gt;&lt;span class="doc"&gt;Providing Test Tools&lt;/span&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;We originally created oslotest as a place to include the base
class for all unit tests across all projects, to give the projects
common behaviors in their test suites. Using a common base class
is not always possible, however, when applications want to use
their own base class and test fixture classes in ways that do not
mix well. Multiple inheritance, in particular, is a problem
because the order of setup and tear-down for test cases is harder
to reason about.&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;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Provide a fixture to change the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;maxDiff&lt;/span&gt;&lt;/code&gt; attribute of a test
case, with a default of 10,000 as in BaseTestCase.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Provide a fixture to wrap &lt;code class="xref py py-class docutils literal notranslate"&gt;&lt;span class="pre"&gt;fixtures.Timeout&lt;/span&gt;&lt;/code&gt; using an environment
variable to set the actual timeout, based on
&lt;code class="xref py py-meth docutils literal notranslate"&gt;&lt;span class="pre"&gt;BaseTestCase._set_timeout()&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Provide a fixture to mock stdout and stderr, based on
&lt;code class="xref py py-meth docutils literal notranslate"&gt;&lt;span class="pre"&gt;BaseTestCase._fake_output()&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Provide a fixture to wrap &lt;code class="xref py py-class docutils literal notranslate"&gt;&lt;span class="pre"&gt;fixtures.FakeLogger&lt;/span&gt;&lt;/code&gt; using an
environment variable to set the actual timeout, based on
&lt;code class="xref py py-meth docutils literal notranslate"&gt;&lt;span class="pre"&gt;BaseTestCase._fake_logs()&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Provide a fixture to create a temporary file with content to
replicate the features of
&lt;code class="xref py py-meth docutils literal notranslate"&gt;&lt;span class="pre"&gt;BaseTestCase.create_tempfiles()&lt;/span&gt;&lt;/code&gt;. We should use one fixture
per file, and provide the full path to the resulting file as an
attribute of the fixture.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add &lt;code class="xref py py-class docutils literal notranslate"&gt;&lt;span class="pre"&gt;DeprecationWarning&lt;/span&gt;&lt;/code&gt; to &lt;code class="xref py py-meth docutils literal notranslate"&gt;&lt;span class="pre"&gt;BaseTestCase.setUp()&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;section id="leave-everything-alone"&gt;
&lt;h4&gt;Leave Everything Alone&lt;/h4&gt;
&lt;p&gt;Leaving &lt;code class="xref py py-class docutils literal notranslate"&gt;&lt;span class="pre"&gt;BaseTestCase&lt;/span&gt;&lt;/code&gt; alone risks making it completely
obsolete as projects drop its use due to issues with multiple
inheritance.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="impact-on-existing-apis"&gt;
&lt;h3&gt;Impact on Existing APIs&lt;/h3&gt;
&lt;p&gt;The existing &lt;code class="xref py py-class docutils literal notranslate"&gt;&lt;span class="pre"&gt;DeprecationWarning&lt;/span&gt;&lt;/code&gt; will not be changed other
than to add the deprecation warning, so all existing users will
continue to be able to use it until they move to the new fixtures.&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="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="configuration-impact"&gt;
&lt;h3&gt;Configuration 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 will need to create or update their own test base classes
to use the desired fixtures. The old test case will not be removed for
at least one cycle, to allow for migration time.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing-impact"&gt;
&lt;h3&gt;Testing Impact&lt;/h3&gt;
&lt;p&gt;We will need unit tests for the new fixtures.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Doug Hellmann&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="milestones"&gt;
&lt;h3&gt;Milestones&lt;/h3&gt;
&lt;p&gt;Target Milestone for completion: Liberty-2&lt;/p&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;p&gt;See “Proposed change” above.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="incubation"&gt;
&lt;h2&gt;Incubation&lt;/h2&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;section id="adoption"&gt;
&lt;h3&gt;Adoption&lt;/h3&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;section id="library"&gt;
&lt;h3&gt;Library&lt;/h3&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;section id="anticipated-api-stabilization"&gt;
&lt;h3&gt;Anticipated API Stabilization&lt;/h3&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Each change will require updates to the API documentation for oslotest.&lt;/p&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 internal" href="../policy/test-tools.html"&gt;&lt;span class="doc"&gt;Providing Test Tools&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference internal" href="../policy/test-tools.html"&gt;&lt;span class="doc"&gt;Providing Test Tools&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This work is licensed under a Creative Commons Attribution 3.0
Unported License.
&lt;a class="reference external" href="http://creativecommons.org/licenses/by/3.0/legalcode"&gt;http://creativecommons.org/licenses/by/3.0/legalcode&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
</description><pubDate>Tue, 24 Feb 2015 00:00:00 </pubDate></item><item><title>Providing Test Tools</title><link>https://specs.openstack.org/openstack/oslo-specs/specs/policy/test-tools.html</link><description>

&lt;p&gt;Each Oslo library needs to provide support tools for testing code that
uses the library. Over time we have found some patterns that work and
others that do not work, and this policy document describes our
general approach.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem Description&lt;/h2&gt;
&lt;p&gt;We originally created oslotest as a place to include the base class
for all unit tests across all projects, to give the projects common
behaviors in their test suites. Using a common base class is not
always possible, however, when applications want to use their own base
class and test fixture classes in ways that do not mix well. Multiple
inheritance, in particular, is a problem because the order of setup
and tear-down for test cases is harder to reason about.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-policy"&gt;
&lt;h2&gt;Proposed Policy&lt;/h2&gt;
&lt;p&gt;Most libraries include fixtures, rather than test base
classes. Fixtures are more isolated, easier to test, and generally
prove less complex to combine in unforeseen ways. Based on this
experience, and the issues with inheritance in test classes, we should
limit unit test tools to fixtures and avoid using base classes or
mix-in classes.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="alternatives-history"&gt;
&lt;h2&gt;Alternatives &amp;amp; History&lt;/h2&gt;
&lt;p&gt;As mentioned above, the original plan was to create base classes in
oslotest.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="author-s"&gt;
&lt;h3&gt;Author(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary author:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Doug Hellmann&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="milestones"&gt;
&lt;h3&gt;Milestones&lt;/h3&gt;
&lt;p&gt;This policy will go into effect during the Liberty cycle.&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;Deprecate the test base class in oslotest and replicate its features
in fixtures (see &lt;a class="reference internal" href="../liberty/oslotest-refactor-test-base-class.html"&gt;&lt;span class="doc"&gt;Refactor Test Base Class in oslotest&lt;/span&gt;&lt;/a&gt;).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Deprecate the test base class(es) in oslo.db and replicate their
features in fixtures (see
&lt;a class="reference external" href="https://blueprints.launchpad.net/oslo.db/+spec/make-db-fixture-public"&gt;https://blueprints.launchpad.net/oslo.db/+spec/make-db-fixture-public&lt;/a&gt;).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&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;IRC discussion of issues with oslo.db and nova, starting around
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;2015-02-24T11:36:58&lt;/span&gt;&lt;/code&gt; in
&lt;a class="reference external" href="http://eavesdrop.openstack.org/irclogs/%23openstack-oslo/%23openstack-oslo.2015-02-24.log"&gt;http://eavesdrop.openstack.org/irclogs/%23openstack-oslo/%23openstack-oslo.2015-02-24.log&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference internal" href="../liberty/oslotest-refactor-test-base-class.html"&gt;&lt;span class="doc"&gt;Refactor Test Base Class in oslotest&lt;/span&gt;&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/oslo.db/+spec/make-db-fixture-public"&gt;https://blueprints.launchpad.net/oslo.db/+spec/make-db-fixture-public&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="revision-history"&gt;
&lt;h2&gt;Revision 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;Liberty&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;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This work is licensed under a Creative Commons Attribution 3.0
Unported License.
&lt;a class="reference external" href="http://creativecommons.org/licenses/by/3.0/legalcode"&gt;http://creativecommons.org/licenses/by/3.0/legalcode&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
</description><pubDate>Tue, 24 Feb 2015 00:00:00 </pubDate></item><item><title>Spec Approval</title><link>https://specs.openstack.org/openstack/oslo-specs/specs/policy/spec-approval.html</link><description>

&lt;p&gt;This document describes the process for having a specification
approved in Oslo.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem Description&lt;/h2&gt;
&lt;p&gt;Specification approval for Oslo is managed a little differently than
other projects, because although Oslo has a single core/driver team we
also have core reviewer teams for each of the libraries.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-policy"&gt;
&lt;h2&gt;Proposed Policy&lt;/h2&gt;
&lt;p&gt;Rather than a simple majority vote of the driver team, we look for
consensus among the important contributors to that part of the code.&lt;/p&gt;
&lt;p&gt;Specifications related to oslo-incubator are reviewed by oslo-core.&lt;/p&gt;
&lt;p&gt;Specifications related to an existing library are reviewed by
oslo-core and the core review team for the library.&lt;/p&gt;
&lt;p&gt;When consensus is reached on a spec, the Oslo PTL gives the
workflow +1 vote to merge the change and publish the spec.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="alternatives-history"&gt;
&lt;h2&gt;Alternatives &amp;amp; History&lt;/h2&gt;
&lt;section id="two-2"&gt;
&lt;h3&gt;Two +2&lt;/h3&gt;
&lt;p&gt;Using two +2 votes as we do with code review would be faster, but we
do not necessarily strive for speed when managing specification
reviews. We want the team to have time to consider the implications of
the change, the proposed API, and otherwise contemplate the spec.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="separate-specs-repositories"&gt;
&lt;h3&gt;Separate Specs Repositories&lt;/h3&gt;
&lt;p&gt;We could use separate a specs repository for each library, to allow
the core team of that library to manage reviews directly. We have not
yet had so many specs related to a given library that we have felt the
need to do this. We also want the API generalists on the oslo-core
team to be able to participate easily, without having to track reviews
in the large number of different specs repositories we would have.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="author-s"&gt;
&lt;h3&gt;Author(s)&lt;/h3&gt;
&lt;p&gt;Primary author: Doug Hellmann&lt;/p&gt;
&lt;p&gt;Other contributors: None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="milestones"&gt;
&lt;h3&gt;Milestones&lt;/h3&gt;
&lt;p&gt;We adopted this policy starting with Juno.&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="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="http://lists.openstack.org/pipermail/openstack-dev/2014-May/035349.html"&gt;email describing the specs experiment&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="http://lists.openstack.org/pipermail/openstack-dev/2014-June/037068.html"&gt;email describing the approval process&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="revision-history"&gt;
&lt;h2&gt;Revision 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;Juno&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;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This work is licensed under a Creative Commons Attribution 3.0
Unported License.
&lt;a class="reference external" href="http://creativecommons.org/licenses/by/3.0/legalcode"&gt;http://creativecommons.org/licenses/by/3.0/legalcode&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
</description><pubDate>Thu, 19 Feb 2015 00:00:00 </pubDate></item><item><title>Liaisons</title><link>https://specs.openstack.org/openstack/oslo-specs/specs/policy/liaisons.html</link><description>

&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem Description&lt;/h2&gt;
&lt;p&gt;There are now more projects consuming code from the Oslo incubator
than we have Oslo contributors. That means the oslo-core team will
need help to make library adoptions happen.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-policy"&gt;
&lt;h2&gt;Proposed Policy&lt;/h2&gt;
&lt;p&gt;We are asking for one person from each project to serve as a liaison
between the project and Oslo, and to assist with integrating changes
as code moves out of the incubator into libraries or as library API
changes need to be made.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;It is important that the person understand the project well enough
to be able to make significant changes, especially if the API of a
library differs from the incubated modules. We prefer the liaison to
be a core reviewer for the project, but leave that up to the
project. The liaison does not need to be the PTL (and probably
should not be).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The liaison should be prepared to assist with writing and reviewing
patches in their project as libraries are adopted, and with
discussions of API changes to the libraries to make them easier to
use within the project.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Liaisons should pay attention to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;[Oslo]&lt;/span&gt;&lt;/code&gt; tagged messages on the
openstack-dev mailing list.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It is also useful for liaisons to be able to attend the Oslo team
meeting (&lt;a class="reference external" href="https://wiki.openstack.org/wiki/Meetings/Oslo"&gt;Meetings/Oslo&lt;/a&gt;) to participate
in discussions and raise issues for real-time discussion.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h2&gt;Alternatives&lt;/h2&gt;
&lt;section id="add-more-oslo-core-developers"&gt;
&lt;h3&gt;Add more Oslo Core Developers&lt;/h3&gt;
&lt;p&gt;We are always watching for candidates to be added to the oslo-core
team. However, we’re not able to keep up with the rate of addition of
new projects.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="committer-in-oslo-updates-applications"&gt;
&lt;h3&gt;Committer in Oslo Updates Applications&lt;/h3&gt;
&lt;p&gt;This solution does not scale either. A developer changing something in
Oslo will not necessarily also have time or knowledge needed to update
all consuming applications.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="author-s"&gt;
&lt;h3&gt;Author(s)&lt;/h3&gt;
&lt;p&gt;Primary author: doug-hellmann&lt;/p&gt;
&lt;p&gt;Other contributors: None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="milestones"&gt;
&lt;h3&gt;Milestones&lt;/h3&gt;
&lt;p&gt;The Liaison program was started in Oslo during Juno, and expanded to
other cross-project teams for Kilo.&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;Recruit liaisons from all of the projects.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&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;The Liaison program was original described in
&lt;a class="reference external" href="http://wiki.openstack.org/wiki/Oslo/Liaisons"&gt;http://wiki.openstack.org/wiki/Oslo/Liaisons&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;After other projects started using liaisons, the description and
list of volunteers moved to
&lt;a class="reference external" href="https://wiki.openstack.org/wiki/CrossProjectLiaisons"&gt;https://wiki.openstack.org/wiki/CrossProjectLiaisons&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="revision-history"&gt;
&lt;h2&gt;Revision 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;Juno&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;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This work is licensed under a Creative Commons Attribution 3.0
Unported License.
&lt;a class="reference external" href="http://creativecommons.org/licenses/by/3.0/legalcode"&gt;http://creativecommons.org/licenses/by/3.0/legalcode&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
</description><pubDate>Tue, 03 Feb 2015 00:00:00 </pubDate></item><item><title>Naming an Oslo Library</title><link>https://specs.openstack.org/openstack/oslo-specs/specs/policy/naming-libraries.html</link><description>

&lt;p&gt;Choosing a good name for a new Oslo library is important because the
name can be used to signal how we intend the library to be used. This
page describes the guidelines we use when choosing a new name.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem Description&lt;/h2&gt;
&lt;p&gt;Library names need to convey the purpose of the library, as well as
the intended audience.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-policy"&gt;
&lt;h2&gt;Proposed Policy&lt;/h2&gt;
&lt;p&gt;The &lt;a class="reference external" href="http://docs.openstack.org/infra/manual/creators.html#choosing-a-good-name-for-your-project"&gt;Project Creator’s Guide&lt;/a&gt; includes guidelines for finding unique
names with valid character sets and other technical criteria. This
policy extends those guidelines to cover some criteria that are unique
to Oslo.&lt;/p&gt;
&lt;p&gt;There are currently three naming schemes used for Oslo libraries.&lt;/p&gt;
&lt;section id="production-runtime-dependencies-meant-for-openstack"&gt;
&lt;h3&gt;Production Runtime Dependencies Meant for OpenStack&lt;/h3&gt;
&lt;p&gt;Libraries used for production runtime dependencies of OpenStack
projects should follow the naming pattern &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo.something&lt;/span&gt;&lt;/code&gt; for the
library and dist, but use &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo_something&lt;/span&gt;&lt;/code&gt; for the top level package
name. Avoid using the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo.&lt;/span&gt;&lt;/code&gt; namespace package
(&lt;a class="reference internal" href="../kilo/drop-namespace-packages.html"&gt;&lt;span class="doc"&gt;Drop our use of namespace packages&lt;/span&gt;&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;Examples of production runtime dependencies include &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo.config&lt;/span&gt;&lt;/code&gt;
and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo.messaging&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="non-production-dependencies-meant-for-openstack"&gt;
&lt;h3&gt;Non-production Dependencies Meant for OpenStack&lt;/h3&gt;
&lt;p&gt;Libraries used for non-production or non-runtime dependencies of
OpenStack projects should follow the naming convention
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslosomething&lt;/span&gt;&lt;/code&gt; (leaving out the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;.&lt;/span&gt;&lt;/code&gt; between “oslo” and
“something”) for the library, dist, and top level package.&lt;/p&gt;
&lt;p&gt;Examples of non-production dependencies include &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslosphinx&lt;/span&gt;&lt;/code&gt; and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslotest&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;If you are planning to use a name like this, please discuss it with
the Oslo team first - we aren’t sure we like this name scheme and
may suggest an alternative.&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="everything-else"&gt;
&lt;h3&gt;Everything Else&lt;/h3&gt;
&lt;p&gt;Libraries that may be generally useful outside of OpenStack, no matter
how they are used within OpenStack, should be given a descriptive and
unique name, without the “oslo” prefix in any form.&lt;/p&gt;
&lt;p&gt;Other examples of Oslo names include &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;pbr&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;taskflow&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h2&gt;Alternatives&lt;/h2&gt;
&lt;section id="always-use-a-generic-name"&gt;
&lt;h3&gt;Always Use a Generic Name&lt;/h3&gt;
&lt;p&gt;One alternative is to use all generic names, without the “oslo”
prefix. The main drawback of this approach is that it lacks the
ability to signal our intended audience for the library. Some of the
libraries we build are not useful to an audience working outside of
OpenStack.  That could be because it is unencumbered with dependencies
on OpenStack-specific libraries such as &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo.config&lt;/span&gt;&lt;/code&gt;, uses patterns
not used elsewhere, or is simply unlikely to be of interest to anyone
else.  Using the “oslo” prefix gives us a way to indicate to the rest
of the Python community that the library is meant primarily for use in
OpenStack.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="non-production-libs-to-use-oslo-prefix"&gt;
&lt;h3&gt;Non-production Libs to Use “oslo.” Prefix&lt;/h3&gt;
&lt;p&gt;As mentioned above, the Oslo team is not entirely happy with names
like &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslotest&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslosphinx&lt;/span&gt;&lt;/code&gt;. The decision to use the prefix
without the dot separator comes from the fact that those libraries
were not installed into the old “oslo” namespace package. The library
names were selected to be consistent with the package name used in
import statements, and we’ve kept those names rather than going
through the trouble of renaming a library like oslotest, on which much
of OpenStack relies.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="author-s"&gt;
&lt;h3&gt;Author(s)&lt;/h3&gt;
&lt;p&gt;Primary author: doug-hellmann&lt;/p&gt;
&lt;/section&gt;
&lt;section id="milestones"&gt;
&lt;h3&gt;Milestones&lt;/h3&gt;
&lt;p&gt;Effective from the Icehouse release.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="http://docs.openstack.org/infra/manual/creators.html#choosing-a-good-name-for-your-project"&gt;Guidelines from the Project Creator’s Guide&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="revision-history"&gt;
&lt;h2&gt;Revision 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;Icehouse&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;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This work is licensed under a Creative Commons Attribution 3.0
Unported License.
&lt;a class="reference external" href="http://creativecommons.org/licenses/by/3.0/legalcode"&gt;http://creativecommons.org/licenses/by/3.0/legalcode&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
</description><pubDate>Tue, 03 Feb 2015 00:00:00 </pubDate></item><item><title>Public vs. Private Symbols in Oslo Libraries</title><link>https://specs.openstack.org/openstack/oslo-specs/specs/policy/private-symbols.html</link><description>

&lt;p&gt;The Oslo team differentiates between “public” and “private” parts of
Oslo libraries using “&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;_&lt;/span&gt;&lt;/code&gt;” as a prefix in private names. Code using
private symbols is going to break as we move things around in the
libraries, so it should be changed to avoid those symbols.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem Description&lt;/h2&gt;
&lt;p&gt;The Oslo team strives to create stable APIs for all Oslo libraries. We
try to follow good practices for defining those APIs, by making them
as small as possible at first and by extending them in
backwards-compatible ways, slowly over time.&lt;/p&gt;
&lt;p&gt;One challenge we have in doing this is with protecting implementation
details from consuming projects. Languages like C++ and Java have
language-level constructs for hiding data and methods inside classes
and modules. Python is a more open language, and has no parallel to
those data-hiding facilities. Instead, Python developers have adopted
conventions of designating private parts of libraries by naming
symbols that are “private” with a single underscore as the prefix for
the name and by explicitly documenting the supported public interface
of a library. The Oslo team is following these conventions throughout
the Oslo code base.&lt;/p&gt;
&lt;p&gt;The work we started during the Kilo cycle to &lt;a class="reference external" href="https://blueprints.launchpad.net/oslo-incubator/+spec/drop-namespace-packages"&gt;move out of the “oslo”
namespace package&lt;/a&gt; exposed places in several projects where symbols
we have marked as private are being imported and used
directly. Usually this happens in tests, but not always. This was the
source of problems in a couple of applications as we released new
versions of the libraries where those private symbols either no longer
exist or have moved to a new location.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-policy"&gt;
&lt;h2&gt;Proposed Policy&lt;/h2&gt;
&lt;p&gt;As a result of the repeated issues with recent releases, we have built
some tools to let us run the tests for projects with pre-release
versions of the libraries, which we are using to minimize issues for
now.  At the same time, we do expect to be able to change the
implementation details of libraries fairly freely – that’s why we go
to such lengths to designate the public API, just as with the REST
APIs of the applications.&lt;/p&gt;
&lt;p&gt;We expect consuming projects to honor the private designations of
symbols and to avoid using them directly or mocking them in
tests. Where it is impossible or inconvenient to mock the public API
of the library, we have provided (and will continue to add) fixtures
for configuring libraries to be used in application unit tests. We
also have &lt;a class="reference external" href="http://docs.openstack.org/developer/openstack-projects"&gt;documentation for the public APIs of all Oslo libraries&lt;/a&gt;
to try to make clear what portion of the API is considered stable and
supported.&lt;/p&gt;
&lt;p&gt;There are a couple of easy guidelines for determining what part of a
library is private:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;If the name of the module, class, function, variable, attribute, or
other symbol starts with “&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;_&lt;/span&gt;&lt;/code&gt;” it is private and should not be
used.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If the symbol is not documented, it may be private and should
probably not be used. There may be symbols we’ve missed in the
documentation, so please ask in #openstack-oslo or on the
mailing list if you aren’t sure.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
&lt;section id="alternatives-history"&gt;
&lt;h2&gt;Alternatives &amp;amp; History&lt;/h2&gt;
&lt;section id="automatically-run-the-tests-in-the-gate"&gt;
&lt;h3&gt;Automatically Run the Tests in the Gate&lt;/h3&gt;
&lt;p&gt;Running the unit tests for consuming projects before every release is
&lt;em&gt;very&lt;/em&gt; expensive. A single pre-release of oslo.i18n currently requires
running test jobs against 37 repositories. We run the py27 and pep8
jobs for each of those projects, so we actually run 74 jobs. We cannot
do that on the CI infrastructure without consuming enough VMs to
&lt;a class="reference external" href="https://etherpad.openstack.org/p/juno-infra-library-testing"&gt;negatively impact the ability to land patches elsewhere&lt;/a&gt;, so we
are using other resources and doing the testing by hand.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="manually-run-the-tests-before-releases"&gt;
&lt;h3&gt;Manually Run the Tests Before Releases&lt;/h3&gt;
&lt;p&gt;Running the tests by hand before releases will delay important patches
and bug fixes from being released quickly. It also requires individual
library maintainers to have access to enough resources to run all of
the unit tests.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="author-s"&gt;
&lt;h3&gt;Author(s)&lt;/h3&gt;
&lt;p&gt;Primary author: Doug Hellmann&lt;/p&gt;
&lt;p&gt;Other contributors: None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="milestones"&gt;
&lt;h3&gt;Milestones&lt;/h3&gt;
&lt;p&gt;We will be running these tests for the remaining namespace package
releases, to try to minimize further breaks. However, we do not plan
to continue doing this level of testing by hand after the namespace
package changes are completed (currently scheduled for the Kilo-2
milestone) because we do not anticipate having the same level of code
churn.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/oslo-incubator/+spec/drop-namespace-packages"&gt;https://blueprints.launchpad.net/oslo-incubator/+spec/drop-namespace-packages&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/juno-infra-library-testing"&gt;https://etherpad.openstack.org/p/juno-infra-library-testing&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/openstack-projects"&gt;http://docs.openstack.org/developer/openstack-projects&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="revision-history"&gt;
&lt;h2&gt;Revision 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;Icehouse&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Introduced&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Kilo&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Formalized during the move out of the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo&lt;/span&gt;&lt;/code&gt; namespace package.&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This work is licensed under a Creative Commons Attribution 3.0
Unported License.
&lt;a class="reference external" href="http://creativecommons.org/licenses/by/3.0/legalcode"&gt;http://creativecommons.org/licenses/by/3.0/legalcode&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
</description><pubDate>Tue, 03 Feb 2015 00:00:00 </pubDate></item><item><title>Choosing Version Numbers</title><link>https://specs.openstack.org/openstack/oslo-specs/specs/policy/versioning.html</link><description>

&lt;p&gt;As part of the push to release code from the oslo incubator in
stand-alone libraries, we have had several different discussions about
versioning and release schedules. This is an attempt to collect all of
the decisions we have made in those discussions and to lay out the
rationale for the approach we are taking.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem Description&lt;/h2&gt;
&lt;p&gt;We have two types of Oslo libraries. Libraries like &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo.config&lt;/span&gt;&lt;/code&gt;
and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo.messaging&lt;/span&gt;&lt;/code&gt; were created by extracting incubated code,
updating the public API, and packaging it. Libraries like &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cliff&lt;/span&gt;&lt;/code&gt;
and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;taskflow&lt;/span&gt;&lt;/code&gt; were created as standalone packages from the
beginning, and later adopted by the Oslo team to manage their
development and maintenance.&lt;/p&gt;
&lt;p&gt;Incubated libraries have been released at the end of a release cycle,
as with the rest of the integrated packages. Adopted libraries have
historically been released “as needed” during their development.&lt;/p&gt;
&lt;p&gt;The first release of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo.config&lt;/span&gt;&lt;/code&gt; was 1.1.0, as part of the grizzly
release. The first release of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo.messaging&lt;/span&gt;&lt;/code&gt; was 1.2.0, as part of
the havana release. &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo.config&lt;/span&gt;&lt;/code&gt; was also updated to 1.2.0 during
havana. All “adopted” libraries (created elsewhere and brought into
the Oslo project) had release numbers less than 1.0.0 when the
original draft of this policy was written.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-policy"&gt;
&lt;h2&gt;Proposed Policy&lt;/h2&gt;
&lt;p&gt;At the Juno summit, Josh Harlow &lt;a class="reference external" href="https://etherpad.openstack.org/p/juno-oslo-semantic-versioning"&gt;proposed&lt;/a&gt;
that we use semantic versioning (SemVer) for oslo libraries. Part of
that proposal also included ideas for allowing breaking backwards
compatibility at some release boundaries, and this policy does not yet
address that issue. The first step is choosing a rational release
versioning scheme.&lt;/p&gt;
&lt;p&gt;SemVer is widely used and gives us relatively clear guidelines about
choosing new version numbers. Oslo started using &lt;a class="reference external" href="http://docs.openstack.org/developer/pbr/semver.html"&gt;pbr’s modified
SemVer&lt;/a&gt; for new releases, beginning in the Juno cycle.&lt;/p&gt;
&lt;section id="semver-life-cycle"&gt;
&lt;h3&gt;SemVer Life Cycle&lt;/h3&gt;
&lt;p&gt;New libraries should start with version 0.1.0, incrementing following
the SemVer policies through the end of the cycle with the goal of
reaching 1.0.0 by the end of their first full development cycle.&lt;/p&gt;
&lt;p&gt;Existing libraries will follow SemVer, incrementing from the version
they had at the start of Kilo.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="frequent-releases"&gt;
&lt;h3&gt;Frequent Releases&lt;/h3&gt;
&lt;p&gt;While we can run gate jobs using the master branch of Oslo libraries,
developers will have to take extra steps to run unit tests this way
locally. To reduce this process overhead, while still ensuring that
developers use current versions of the code, we produce releases of
libraries during the release cycle fairly frequently. We have a weekly
check-up during the Oslo team meetings, and tag releases early on
Mondays when deemed necessary. Waiting until Monday prevents us from
introducing a gate issue just before the weekend starts.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="patch-releases-for-stable-branches"&gt;
&lt;h3&gt;Patch Releases for Stable Branches&lt;/h3&gt;
&lt;p&gt;Updates to existing library releases can be made from stable
branches. Checking out &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;stable/icehouse&lt;/span&gt;&lt;/code&gt; of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo.config&lt;/span&gt;&lt;/code&gt; for
example would allow a release 1.3.1. We don’t have a formal policy
about whether we will create patch releases, or whether applications
are better off using the latest release of the library.&lt;/p&gt;
&lt;p&gt;All libraries will need to maintain stable branches to support these
patch releases. We will cap the versions of Oslo libs used in stable
branches to allow patch releases but not updates with minor version
number changes.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="alternatives-history"&gt;
&lt;h2&gt;Alternatives &amp;amp; History&lt;/h2&gt;
&lt;section id="synchronizing-with-the-rest-of-openstack"&gt;
&lt;h3&gt;Synchronizing with the Rest of OpenStack&lt;/h3&gt;
&lt;p&gt;The Oslo team could release libraries at any point, without concern
for the release schedule of the rest of OpenStack. We have to be
prepared for libraries we do not maintain to be updated at any point,
so this wouldn’t be adding a new aspect to our release and testing
processes. However, Oslo is part of OpenStack and so we initially
wanted to be on the same schedule.&lt;/p&gt;
&lt;p&gt;Mark McLoughlin has written &lt;a class="reference external" href="http://lists.openstack.org/pipermail/openstack-dev/2012-November/003345.html"&gt;a good justificiation for this&lt;/a&gt;,
which is summarized as “my instinct is to do everything just like any
of the other core projects except in those cases where Oslo really is
a special case.” With Oslo following the release schedule of the other
projects, we get all of the benefits (shifting focus from features to
bugs; stable branches; synchronization with the users of our
libraries; the OpenStack release manager).&lt;/p&gt;
&lt;p&gt;When we stopped creating Alpha releases, we stopped full release
synchronization. We do still release a final version for a given major
and minor version number at the end of a release, and we do still
follow the feature freeze process.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="alpha-releases"&gt;
&lt;h3&gt;Alpha Releases&lt;/h3&gt;
&lt;p&gt;In the past, alpha releases of Oslo libraries have been distributed as
tarballs on an openstack server, with official releases going to
PyPI. Applications that required the alpha release specified the
tarball in their requirements list, followed by a version
specifier. This allowed us to prepare alpha releases, without worrying
that their release would break continuous-deployment systems by making
new library releases available to pip. This approach still made it
difficult for an application developer to rely on new features of an
oslo library, until an alpha version was produced.&lt;/p&gt;
&lt;p&gt;When the PyPI mirror was introduced in our CI system, relying on
tarballs not available on the mirror conflicted with our desire to
have the gate system install &lt;em&gt;only&lt;/em&gt; from the package mirror. When we
started installing only from the mirror, we needed to publish our
alpha releases in a format that will work with the mirror, and so we
started using alpha version numbers of predicted final versions during
a release.&lt;/p&gt;
&lt;p&gt;At the Kilo summit, a vocal group of consumers of Oslo libraries
requested that we stop using alpha versioning and switch to simple
SemVer. We started doing that in Kilo, with mixed results (breaking
changes made it into the stable branch test environments). At this
point, there is no sense in going back to alpha releases during Kilo,
so we will stick with the current plan and work through the resulting
issues.&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://etherpad.openstack.org/p/kilo-oslo-alpha-versioning"&gt;https://etherpad.openstack.org/p/kilo-oslo-alpha-versioning&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;We decided that new libraries should start with version 0.1.0,
incrementing following the SemVer policies through the end of the
cycle with the goal of reaching 1.0.0 by that time.&lt;/p&gt;
&lt;p&gt;Existing libraries will follow SemVer, incrementing from the version
they had at the start of Kilo.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="juno-policy"&gt;
&lt;h3&gt;Juno Policy&lt;/h3&gt;
&lt;p&gt;The versions for existing libraries oslo.config and oslo.messaging
will be incremented from their Icehouse versions but updating the
minor number (1.x.0) at the end of the Juno cycle.&lt;/p&gt;
&lt;p&gt;All adopted libraries using numbers less than 1.0 will be released as
1.0.0 at the end of the Juno cycle, based on the fact that we expect
deployers to use them in production.&lt;/p&gt;
&lt;p&gt;Releases of new libraries graduated during Juno will be tagged with
regular release numbers &amp;lt; 1.0. This allows us to add them to our
requirements list (which won’t accept alphas of packages with no other
release). At the end of Juno, we will tag the libraries 1.0.0.&lt;/p&gt;
&lt;p&gt;Releases of existing libraries during Juno should &lt;em&gt;all&lt;/em&gt; be marked as
alphas of the anticipated upcoming SemVer-based release number
(1.0.0.0aN or 1.2.0.0aN or whatever). The new CI system can create
packages as Python wheels and publish them to the appropriate servers,
which means projects will no longer need to refer explicitly to
pre-release tarballs. pip won’t install alpha libraries unless you
explicitly request them with a command line flag to install any alphas
available or you explicitly require the alpha version. pip &amp;lt;= 1.3
didn’t support the flag for controlling alphas (they were always seen
and installed), but also didn’t support wheels, so we publish alphas
only as wheels to ensure that older pips don’t see them.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="cross-project-unit-testing-in-the-gate"&gt;
&lt;h3&gt;Cross-Project Unit Testing in the Gate&lt;/h3&gt;
&lt;p&gt;We had a blueprint for Juno to &lt;a class="reference external" href="https://blueprints.launchpad.net/openstack-ci/+spec/testing-pre-releases-of-oslo-libs-with-apps"&gt;add cross-project unit test gating&lt;/a&gt;
for applications and oslo libraries. This would have allowed us to
verify that tests for applications do not break then Oslo libraries
change, but also that those tests do not make assumptions about Oslo
library implementation details. However, this level of testing was
deemed too expensive in terms of test servers, and so the plan was
dropped.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="capping-requirements-in-stable-branches"&gt;
&lt;h3&gt;Capping Requirements in Stable Branches&lt;/h3&gt;
&lt;p&gt;We do not typically use upper bounds on the requirements
specifications for Oslo libraries, so new releases may automatically
be adopted by continuous-deployment systems building packages for
stable branches of OpenStack applications. Although we have been
careful about API compatibility in the past, there is a chance that a
new release could break an older application. Applications could add
an upper bound using SemVer numbering if they choose, although that
may prevent them from seeing bug fixes so it is not recommended.&lt;/p&gt;
&lt;p&gt;During the Kilo summit we discussed capping versions of requirements
in stable branches. The initial attempt to do this right after the
summit failed because it prevented some upgrades from working
correctly. Work to apply caps is ongoing, and is outside of the scope
of this policy.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="tagging-milestones-in-libraries"&gt;
&lt;h3&gt;Tagging milestones in libraries&lt;/h3&gt;
&lt;p&gt;We don’t tag libraries at the milestones like we do with applications,
since the tags we use for milestones (e.g., 2014.2.b1) aren’t valid
versions for libraries and would be out of order with other releases
anyway. We may tag an alpha release around the time of the milestone,
but since we do those on demand anyway there’s no strict rule that we
must do it at that time.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="author-s"&gt;
&lt;h3&gt;Author(s)&lt;/h3&gt;
&lt;p&gt;Primary author: doug-hellmann&lt;/p&gt;
&lt;p&gt;Other contributors: markmc&lt;/p&gt;
&lt;/section&gt;
&lt;section id="milestones"&gt;
&lt;h3&gt;Milestones&lt;/h3&gt;
&lt;p&gt;The current policy was put into place for Kilo.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="http://lists.openstack.org/pipermail/openstack-dev/2012-November/003345.html"&gt;http://lists.openstack.org/pipermail/openstack-dev/2012-November/003345.html&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="http://lists.openstack.org/pipermail/openstack-dev/2014-June/037159.html"&gt;http://lists.openstack.org/pipermail/openstack-dev/2014-June/037159.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/pbr/semver.html"&gt;pbr’s modified SemVer&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="revision-history"&gt;
&lt;h2&gt;Revision 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;Juno&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;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This work is licensed under a Creative Commons Attribution 3.0
Unported License.
&lt;a class="reference external" href="http://creativecommons.org/licenses/by/3.0/legalcode"&gt;http://creativecommons.org/licenses/by/3.0/legalcode&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
</description><pubDate>Tue, 03 Feb 2015 00:00:00 </pubDate></item><item><title>Adopting nova.objects</title><link>https://specs.openstack.org/openstack/oslo-specs/specs/kilo/adopt-oslo-versionedobjects.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/oslo?searchtext=graduate-oslo-versionedobjects"&gt;https://blueprints.launchpad.net/oslo?searchtext=graduate-oslo-versionedobjects&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The nova.objects package abstracts versionable internal objects for use with RPC.&lt;/p&gt;
&lt;p&gt;Rather than moving this code into the incubator, I propose that we
move it directly to a new library. The code has been around long
enough that the API is reasonably stable.&lt;/p&gt;
&lt;section id="library-name"&gt;
&lt;h2&gt;Library Name&lt;/h2&gt;
&lt;p&gt;oslo.versionedobjects&lt;/p&gt;
&lt;/section&gt;
&lt;section id="contents"&gt;
&lt;h2&gt;Contents&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;nova/exception.py (with cleanup to remove extraneous parts; tests not needed)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;nova/objects/__init__.py&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;nova/objects/base.py&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;nova/objects/fields.py&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;nova/test.py&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;nova/tests/fixtures.py&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;nova/tests/unit/objects/__init__.py&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;nova/tests/unit/objects/test_fields.py&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;nova/tests/unit/objects/test_objects.py&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;nova/tests/unit/test_utils.py (with cleanup to remove extraneous parts)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;nova/safe_utils.py (with cleanup to remove extraneous parts)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;nova/utils.py (with cleanup to remove extraneous parts)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="early-adopters"&gt;
&lt;h2&gt;Early Adopters&lt;/h2&gt;
&lt;p&gt;These projects are already using the code:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;nova&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;ironic&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The divergence in Ironic is minimal and their version is generally
slightly behind nova, as new things are only copied over as needed.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="public-api"&gt;
&lt;h2&gt;Public API&lt;/h2&gt;
&lt;p&gt;The public API is relatively well-defined at this point. Major elements consist of:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;base.VersionedObject - The base object to subclass for each implementation&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;base.remotable - A decorator to make an object method into an RPC-able thing&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;base.remotable_classmethod - A decorator to make a classmethod into an
RPC-able thing&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;base.ObjectListBase - A mix-in to gain list-of-objects functionality&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;base.VersionedObjectSerializer - an oslo.messaging.NoOpSerializer that marshals
VersionedObject objects over the wire&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following things are fairly nova-specific and should be left in the
Nova tree (for now at least):&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;base.obj_make_list()&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;base.serialize_args()&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;base.NovaPersistentObject&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Things that are public now (or, too public for a library) that should be
made private:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;base.make_class_properties()&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;base.get_attrname()&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Things that need some definition that are currently rather obscure and
nova-centric:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;The base.VersionedObjectMetaclass.indirection_api interface is how
RPC-able things are remoted. Right now, this is nova’s conductor
class, but a simple base class to define the interface should be
created for others to subclass. In nova, we set this rather forcibly,
but in this library, we should provide methods to set/clear the indirection
service.&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 service and conductor code will be left out of the initial
import, and the tests using it commented out. Fixing those tests
will be a high priority item before we release.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Finally, there is one detail of the implementation that deserves some thought
before we codify it in a library. Right now, the simple act of subclassing
NovaObject will register the implementation in the registry, via the metaclass.
This is convenient because the author doesn’t have to do anything in order to
use their implementation immediately. However, it may be a little “too magic”
or “too automatic”. If you want to subclass NovaObject but not register it,
there is currently no way to do that. We could have an unregister function,
but then it’s impossible to avoid the small window of being registered. The
unit tests currently have some weirdness because of this, for their test
objects.&lt;/p&gt;
&lt;p&gt;The alternate proposal for registration would be a simple class decorator
that you apply to objects that you wish to be registered.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Dan Smith&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Doug Hellmann&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="primary-maintainer"&gt;
&lt;h3&gt;Primary Maintainer&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary Maintainer:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Dan Smith&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other Contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Chris Behrens&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="security-contact"&gt;
&lt;h3&gt;Security Contact&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Security Contact:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Dan Smith&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="milestones"&gt;
&lt;h3&gt;Milestones&lt;/h3&gt;
&lt;p&gt;Target Milestone for completion: kilo-2&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 Initial Repository&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update MAINTAINERS in incubator with status and name&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Remove Oslo logging calls in incubator&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Run graduate.sh&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Fix the output of graduate.sh&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use cookiecutter template to make a new project&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Sync tools from nova&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Remove novaisms&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Finish moving should-be-private things to private names&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Make changes to the registry according to review&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Finish documenting any public interfaces lacking proper docs&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Publish git repo&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Oslo team review new repository&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;openstack-infra/project-config - gerrit/projects.yaml&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;openstack-infra/project-config - gerrit/acls/openstack/project-name.config&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;openstack-infra/project-config - jenkins/jobs/projects.yaml&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;openstack-infra/project-config - zuul/layout.yaml&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;openstack-infra/project-config - gerritbot/channels.yaml&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update Gerrit Groups and ACLs&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;openstack-infra/devstack-gate - devstack-vm-gate-wrap.sh&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;openstack/requirements projects.txt&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;openstack/governance reference/programs.yaml&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update list of libraries on Oslo wiki page&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create Launchpad project&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create Launchpad bug tracker&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create Launchpad blueprint tracker&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Change owner of Launchpad project&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Make the library do something&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Give openstackci Owner permissions on PyPI&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Tag a release&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Remove graduated code from oslo-incubator&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update oslo-incubator/update.py to not rewrite references to the library&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;openstack/requirements - global-requirements.txt&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Document Migration Process&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;openstack-dev/devstack - lib/oslo&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;openstack-dev/devstack - stackrc&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update project list on docs.openstack.org&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Fix/update tests that depend on nova’s service code&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="adoption-notes"&gt;
&lt;h2&gt;Adoption Notes&lt;/h2&gt;
&lt;p&gt;Adoption will include synchronization with changes that may be going into Nova
at the same time until the point at which nova can move to using the oslo
library.&lt;/p&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="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Earlier patch to incubator to import this code: &lt;a class="reference external" href="https://review.openstack.org/#/c/60376/"&gt;https://review.openstack.org/#/c/60376/&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="export-script"&gt;
&lt;h2&gt;Export Script&lt;/h2&gt;
&lt;div class="highlight-bash notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="ch"&gt;#!/bin/bash&lt;/span&gt;

&lt;span class="c1"&gt;# Depends on refactored graduation scripts found&lt;/span&gt;
&lt;span class="c1"&gt;# in https://review.openstack.org/#/c/151027/&lt;/span&gt;

&lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-ex

&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;nova&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;git&lt;span class="w"&gt; &lt;/span&gt;checkout&lt;span class="w"&gt; &lt;/span&gt;master&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;git&lt;span class="w"&gt; &lt;/span&gt;pull&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;new_repo&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;oslo.versionedobjects-&lt;span class="k"&gt;$(&lt;/span&gt;date&lt;span class="w"&gt; &lt;/span&gt;+%Y-%m-%d-%H%M&lt;span class="k"&gt;)&lt;/span&gt;
git&lt;span class="w"&gt; &lt;/span&gt;clone&lt;span class="w"&gt; &lt;/span&gt;nova&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$new_repo&lt;/span&gt;
&lt;span class="nb"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$new_repo&lt;/span&gt;

&lt;span class="nv"&gt;tooldir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;~/repos/openstack/oslo-incubator/tools

&lt;span class="nv"&gt;FILES&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="s2"&gt;    nova/exception.py&lt;/span&gt;
&lt;span class="s2"&gt;    nova/objects/__init__.py&lt;/span&gt;
&lt;span class="s2"&gt;    nova/objects/base.py&lt;/span&gt;
&lt;span class="s2"&gt;    nova/objects/fields.py&lt;/span&gt;
&lt;span class="s2"&gt;    nova/test.py&lt;/span&gt;
&lt;span class="s2"&gt;    nova/tests/fixtures.py&lt;/span&gt;
&lt;span class="s2"&gt;    nova/tests/unit/objects/__init__.py&lt;/span&gt;
&lt;span class="s2"&gt;    nova/tests/unit/objects/test_fields.py&lt;/span&gt;
&lt;span class="s2"&gt;    nova/tests/unit/objects/test_objects.py&lt;/span&gt;
&lt;span class="s2"&gt;    nova/tests/unit/test_utils.py&lt;/span&gt;
&lt;span class="s2"&gt;    nova/safe_utils.py&lt;/span&gt;
&lt;span class="s2"&gt;    nova/utils.py&lt;/span&gt;
&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="nv"&gt;$tooldir&lt;/span&gt;/filter_git_history.sh&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$FILES&lt;/span&gt;

git&lt;span class="w"&gt; &lt;/span&gt;mv&lt;span class="w"&gt; &lt;/span&gt;nova&lt;span class="w"&gt; &lt;/span&gt;oslo_versionedobjects
git&lt;span class="w"&gt; &lt;/span&gt;mv&lt;span class="w"&gt; &lt;/span&gt;oslo_versionedobjects/objects/*&lt;span class="w"&gt; &lt;/span&gt;oslo_versionedobjects/
rmdir&lt;span class="w"&gt; &lt;/span&gt;oslo_versionedobjects/objects
git&lt;span class="w"&gt; &lt;/span&gt;mv&lt;span class="w"&gt; &lt;/span&gt;oslo_versionedobjects/tests/unit/objects/*&lt;span class="w"&gt; &lt;/span&gt;oslo_versionedobjects/tests/
rmdir&lt;span class="w"&gt; &lt;/span&gt;oslo_versionedobjects/tests/unit/objects
git&lt;span class="w"&gt; &lt;/span&gt;mv&lt;span class="w"&gt; &lt;/span&gt;oslo_versionedobjects/tests/unit/test_utils.py&lt;span class="w"&gt; &lt;/span&gt;oslo_versionedobjects/tests/
rmdir&lt;span class="w"&gt; &lt;/span&gt;oslo_versionedobjects/tests/unit

&lt;span class="nv"&gt;$tooldir&lt;/span&gt;/apply_cookiecutter.sh&lt;span class="w"&gt; &lt;/span&gt;versionedobjects

cat&lt;span class="w"&gt; &lt;/span&gt;-&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;requirements.txt&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;lt;&amp;lt;EOF&lt;/span&gt;
&lt;span class="s"&gt;six&amp;gt;=1.7.0&lt;/span&gt;
&lt;span class="s"&gt;Babel&amp;gt;=1.3&lt;/span&gt;
&lt;span class="s"&gt;netaddr&amp;gt;=0.7.12&lt;/span&gt;
&lt;span class="s"&gt;oslo.concurrency&amp;gt;=1.4.1         # Apache-2.0&lt;/span&gt;
&lt;span class="s"&gt;oslo.context&amp;gt;=0.1.0                     # Apache-2.0&lt;/span&gt;
&lt;span class="s"&gt;oslo.messaging&amp;gt;=1.4.0,!=1.5.0&lt;/span&gt;
&lt;span class="s"&gt;oslo.serialization&amp;gt;=1.2.0               # Apache-2.0&lt;/span&gt;
&lt;span class="s"&gt;oslo.utils&amp;gt;=1.2.0                       # Apache-2.0&lt;/span&gt;
&lt;span class="s"&gt;iso8601&amp;gt;=0.1.9&lt;/span&gt;
&lt;span class="s"&gt;EOF&lt;/span&gt;

cat&lt;span class="w"&gt; &lt;/span&gt;-&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;test-requirements.txt&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;lt;&amp;lt;EOF&lt;/span&gt;
&lt;span class="s"&gt;hacking&amp;gt;=0.5.6,&amp;lt;0.8&lt;/span&gt;
&lt;span class="s"&gt;oslotest&amp;gt;=1.2.0  # Apache-2.0&lt;/span&gt;
&lt;span class="s"&gt;mock&amp;gt;=1.0&lt;/span&gt;
&lt;span class="s"&gt;testtools&amp;gt;=0.9.36,!=1.2.0&lt;/span&gt;
&lt;span class="s"&gt;# These are needed for docs generation&lt;/span&gt;
&lt;span class="s"&gt;oslosphinx&amp;gt;=2.2.0  # Apache-2.0&lt;/span&gt;
&lt;span class="s"&gt;sphinx&amp;gt;=1.1.2,!=1.2.0,!=1.3b1,&amp;lt;1.3&lt;/span&gt;
&lt;span class="s"&gt;EOF&lt;/span&gt;

&lt;span class="nb"&gt;echo&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Output in &lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;pwd&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="nb"&gt;exit&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$?&lt;/span&gt;


&lt;span class="c1"&gt;# oslo-incubator modules:&lt;/span&gt;
&lt;span class="c1"&gt;# versionutils&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This work is licensed under a Creative Commons Attribution 3.0
Unported License.
&lt;a class="reference external" href="http://creativecommons.org/licenses/by/3.0/legalcode"&gt;http://creativecommons.org/licenses/by/3.0/legalcode&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
</description><pubDate>Mon, 02 Feb 2015 00:00:00 </pubDate></item><item><title>ZeroMQ Context should be created once per driver instance</title><link>https://specs.openstack.org/openstack/oslo-specs/specs/liberty/zmq-context-per-driver-instance.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/oslo.messaging/+spec/zmq-context-per-driver-instance"&gt;https://blueprints.launchpad.net/oslo.messaging/+spec/zmq-context-per-driver-instance&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;ZeroMQ context object has singleton nature, so producing it
more than once per driver is inefficient consuming of resources.&lt;/p&gt;
&lt;p&gt;Now it is created per socket.&lt;/p&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;section id="oslo-messaging"&gt;
&lt;h3&gt;oslo-messaging&lt;/h3&gt;
&lt;p&gt;Move creation of zmq context from ZmqSocket constructor
&lt;code class="xref py py-meth docutils literal notranslate"&gt;&lt;span class="pre"&gt;ZmqSocket.__init__()&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="c1"&gt;# oslo_messaging/_drivers/impl_zmq.py&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ZmqSocket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;object&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;

   &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;addr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;zmq_type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bind&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;subscribe&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
      &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ctxt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;zmq&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CONF&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rpc_zmq_contexts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sock&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;ctxt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;zmq_type&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;to ZmqDriver constructor &lt;code class="xref py py-meth docutils literal notranslate"&gt;&lt;span class="pre"&gt;ZmqDriver.__init__()&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="c1"&gt;# oslo_messaging/_drivers/impl_zmq.py&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ZmqDriver&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;BaseDriver&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;conf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;default_exchange&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                 &lt;span class="n"&gt;allowed_remote_exmods&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ctxt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;zmq&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CONF&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rpc_zmq_contexts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Update &lt;code class="xref py py-meth docutils literal notranslate"&gt;&lt;span class="pre"&gt;ZmqSocket.__init__()&lt;/span&gt;&lt;/code&gt; to pass zmq context as an argument&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="c1"&gt;# oslo_messaging/_drivers/impl_zmq.py&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ZmqSocket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;object&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
   &lt;span class="o"&gt;...&lt;/span&gt;
   &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;zmq_ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;addr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;zmq_type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bind&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;subscribe&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
      &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ctxt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;zmq_ctx&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;sock&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;ctxt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;zmq_type&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="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="impact-on-existing-apis"&gt;
&lt;h3&gt;Impact on Existing APIs&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="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="configuration-impact"&gt;
&lt;h3&gt;Configuration 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;Oleksii Zamiatin (&lt;a class="reference external" href="mailto:ozamiatin%40mirantis.com"&gt;ozamiatin&lt;span&gt;@&lt;/span&gt;mirantis&lt;span&gt;.&lt;/span&gt;com&lt;/a&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="milestones"&gt;
&lt;h3&gt;Milestones&lt;/h3&gt;
&lt;p&gt;next-kilo&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;Perform the code movements&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update all places in impl_zmq where socket used&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="incubation"&gt;
&lt;h2&gt;Incubation&lt;/h2&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;section id="adoption"&gt;
&lt;h3&gt;Adoption&lt;/h3&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;section id="library"&gt;
&lt;h3&gt;Library&lt;/h3&gt;
&lt;p&gt;oslo.messaging&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;N/A&lt;/p&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="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;Check neutron &lt;a class="reference external" href="https://bugs.launchpad.net/neutron/+bug/1364814"&gt;https://bugs.launchpad.net/neutron/+bug/1364814&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
</description><pubDate>Wed, 28 Jan 2015 00:00:00 </pubDate></item><item><title>Graduating oslo.service</title><link>https://specs.openstack.org/openstack/oslo-specs/specs/liberty/graduate-oslo-service.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/oslo-incubator/+spec/graduate-oslo-service"&gt;https://blueprints.launchpad.net/oslo-incubator/+spec/graduate-oslo-service&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The oslo.service library contains common code for running OpenStack services.&lt;/p&gt;
&lt;section id="library-name"&gt;
&lt;h2&gt;Library Name&lt;/h2&gt;
&lt;p&gt;oslo.service&lt;/p&gt;
&lt;/section&gt;
&lt;section id="contents"&gt;
&lt;h2&gt;Contents&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;openstack/common/eventlet_backdoor.py&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;tests/unit/test_eventlet_backdoor.py&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;openstack/common/loopingcall.py&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;tests/unit/test_loopingcall.py&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;openstack/common/service.py&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;tests/unit/test_service.py&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;tests/unit/eventlet_service.py&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;openstack/common/sslutils.py&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;tests/unit/test_sslutils.py&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;openstack/common/systemd.py&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;tests/unit/test_systemd.py&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;openstack/common/threadgroup.py&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;tests/unit/test_threadgroup.py&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;openstack/common/periodic_task.py&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;tests/unit/test_periodic.py&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="early-adopters"&gt;
&lt;h2&gt;Early Adopters&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Ironic&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="public-api"&gt;
&lt;h2&gt;Public API&lt;/h2&gt;
&lt;p&gt;All of the existing public functions and classes will remain public.&lt;/p&gt;
&lt;p&gt;New public function &lt;code class="xref py py-func docutils literal notranslate"&gt;&lt;span class="pre"&gt;list_opts()&lt;/span&gt;&lt;/code&gt; that will return a list of oslo.config
options available in the library. will be added.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Sachi King (nakato)&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Elena Ezhova (eezhova)&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="primary-maintainer"&gt;
&lt;h3&gt;Primary Maintainer&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary Maintainer:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;To Be Determined&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="security-contact"&gt;
&lt;h3&gt;Security Contact&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Security Contact:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;To Be Determined&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="milestones"&gt;
&lt;h3&gt;Milestones&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Target Milestone for completion:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;liberty-1&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;&lt;a class="reference external" href="https://wiki.openstack.org/wiki/Oslo/CreatingANewLibrary#Checklist"&gt;https://wiki.openstack.org/wiki/Oslo/CreatingANewLibrary#Checklist&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Move the option definitions into a private file.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create a &lt;code class="xref py py-func docutils literal notranslate"&gt;&lt;span class="pre"&gt;list_opts()&lt;/span&gt;&lt;/code&gt; function that will return a list of oslo.config
options available in the library.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Change API of &lt;code class="xref py py-func docutils literal notranslate"&gt;&lt;span class="pre"&gt;launch()&lt;/span&gt;&lt;/code&gt; in service.py to take a config object as
an argument.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Change API of &lt;code class="xref py py-func docutils literal notranslate"&gt;&lt;span class="pre"&gt;periodic_task()&lt;/span&gt;&lt;/code&gt; in periodic_task to take a config
object as an argument.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Remove usage of global config throughout the library and update
the existing classes/functions to register the options they use
automatically at runtime.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="adoption-notes"&gt;
&lt;h2&gt;Adoption Notes&lt;/h2&gt;
&lt;p&gt;The code changes described above should allow all apps to import with
a statement 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="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;oslo_service&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;bar&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;replacing the current form:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;foo.openstack.common&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;bar&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&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="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/kilo-oslo-library-proposals"&gt;https://etherpad.openstack.org/p/kilo-oslo-library-proposals&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This work is licensed under a Creative Commons Attribution 3.0
Unported License.
&lt;a class="reference external" href="http://creativecommons.org/licenses/by/3.0/legalcode"&gt;http://creativecommons.org/licenses/by/3.0/legalcode&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
</description><pubDate>Thu, 18 Dec 2014 00:00:00 </pubDate></item><item><title>Creating debtcollector</title><link>https://specs.openstack.org/openstack/oslo-specs/specs/kilo/adopt-debtcollector.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/oslo.utils/+spec/adopt-debtcollector"&gt;https://blueprints.launchpad.net/oslo.utils/+spec/adopt-debtcollector&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The goal of this library would be to provide well documented
&lt;em&gt;developer facing deprecation&lt;/em&gt; patterns that start of with the a basic set and
can expand into a larger set of patterns as time goes on (it would &lt;strong&gt;not&lt;/strong&gt;
start off being a library that would be used for operator facing deprecation,
as that is already covered by the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;versionutils.py&lt;/span&gt;&lt;/code&gt; module in the
oslo-incubator).&lt;/p&gt;
&lt;p&gt;For example the following patterns could be considered common:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Deprecating a keyword argument to be later replaced with a replacement
keyword argument (useful when a new name was later determined to be better
than an initial name).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Altering the name of a property to refer to a new and improved name (useful
when say a property name is discovered after a certain amount of time to
make more sense than an initial property name).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Moving a class (with or without breaking those who are inheriting from
your old location); this is useful when a class is better located at a
different (potentially better named, more meaningfully named) module than
it was initially placed at (this is common when the initial location was
thought of to be a good location, but after usage a alternative location
would make more sense).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;…&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The desired output of these patterns would be an application of
the &lt;a class="reference external" href="https://docs.python.org/2/library/warnings.html"&gt;warnings&lt;/a&gt; module that would use the common functions that module provides
to emit &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;DeprecationWarning&lt;/span&gt;&lt;/code&gt; or &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;PendingDeprecationWarning&lt;/span&gt;&lt;/code&gt; or similar
derivative to developers using libraries (or potentially applications)
about future deprecations.&lt;/p&gt;
&lt;p&gt;Since the &lt;a class="reference external" href="https://docs.python.org/2/library/warnings.html"&gt;warnings&lt;/a&gt; module supports different types of actions we should
take advantage of that capability (or extend it as needed) to avoid creating
a bunch of &lt;em&gt;garbage&lt;/em&gt; messages that will appear for the developers using
deprecated features/functionality.&lt;/p&gt;
&lt;p&gt;For example the library/functions provided should be affected by the warnings
modules action strings that are defined/copied below.&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;Value&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Disposition&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;error&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;turn matching warnings into exceptions&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;ignore&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;never print matching warnings (the &lt;em&gt;default&lt;/em&gt; in python 2.7+)&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;always&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;always print matching warnings&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;default&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;print the first occurrence of matching warnings for each location
where the warning is issued&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;module&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;print the first occurrence of matching warnings for each module where
the warning is issued&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;once&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;print only the first occurrence of matching warnings, regardless of
location&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Using these settings appropriately would be expected to help avoid polluting
logs or &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;sys.stderr&lt;/span&gt;&lt;/code&gt; where these messages can show up (we should look
into how to make these messages visible in the openstack CI system, and
less/not visible in a released library).&lt;/p&gt;
&lt;p&gt;To aid in this process it might be useful to hook into the following (but
this can be for later discussion):&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://docs.python.org/2/library/logging.html#logging.captureWarnings"&gt;https://docs.python.org/2/library/logging.html#logging.captureWarnings&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Depending on future functionality we could let applications use the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;logging.captureWarnings&lt;/span&gt;&lt;/code&gt; function, or provide this in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo.log&lt;/span&gt;&lt;/code&gt; or do
something different (the point being that the &lt;a class="reference external" href="https://docs.python.org/2/library/warnings.html"&gt;warnings&lt;/a&gt; module and supporting
API will be the entrypoint that these patterns use, how applications or other
libraries adapt/plugin to the &lt;a class="reference external" href="https://docs.python.org/2/library/warnings.html"&gt;warnings&lt;/a&gt; module can be adjusted and tweaked
as seen fit).&lt;/p&gt;
&lt;section id="library-name"&gt;
&lt;h2&gt;Library Name&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;debtcollector&lt;/em&gt;&lt;/p&gt;
&lt;/section&gt;
&lt;section id="contents"&gt;
&lt;h2&gt;Contents&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;debtcollector/__init__.py&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;debtcollector/utils.py&lt;/span&gt;&lt;/code&gt;  (internal utils, not for public usage)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;debtcollector/moves.py&lt;/span&gt;&lt;/code&gt; (for patterns common to
moving code/classes/properties…)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;debtcollector/renames.py&lt;/span&gt;&lt;/code&gt; (for patterns common to
renaming code/classes/properties…)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;… (others as patterns emerge)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="early-adopters"&gt;
&lt;h2&gt;Early Adopters&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Taskflow&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Others?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="public-api"&gt;
&lt;h2&gt;Public API&lt;/h2&gt;
&lt;p&gt;Current idea for API (will likely evolve as new patterns appear…)&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;debtcollector/moves.py&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="c1"&gt;# Patterns devoted to 'moving' functions, methods, classes, arguments...&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;moved_decorator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;new_attribute_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;removal_version&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="n"&gt;stacklevel&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

 &lt;span class="c1"&gt;# Creates a decorator of the given kind for the given attribute name&lt;/span&gt;
 &lt;span class="c1"&gt;# with the provided message, version deprecated in, the version it will&lt;/span&gt;
 &lt;span class="c1"&gt;# be removed in and the given stacklevel (used to output the users code&lt;/span&gt;
 &lt;span class="c1"&gt;# location when this decorator is called).&lt;/span&gt;
 &lt;span class="c1"&gt;#&lt;/span&gt;
 &lt;span class="c1"&gt;# An example message:&lt;/span&gt;
 &lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;kind&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Property'&lt;/span&gt;
 &lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;new_attribute_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'a'&lt;/span&gt;
 &lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;what&lt;/span&gt; &lt;span class="o"&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;' has moved to '&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;kind&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'b'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;new_attribute_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
 &lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;deprecation&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_generate_moved_message&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;what&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'sorry its going away'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'0.1'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;removal_version&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'0.2'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
 &lt;span class="s2"&gt;"Property 'a' has moved to 'b' in version '0.1' and will be removed in version '0.2': sorry its going away"&lt;/span&gt;

 &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;moved_property&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;new_attribute_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;removal_version&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stacklevel&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;

 &lt;span class="c1"&gt;# Decorator specialization of moved_decorator that sets the kind to&lt;/span&gt;
 &lt;span class="c1"&gt;# a property instead of allowing it to be specified.&lt;/span&gt;

 &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;moved_class&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;new_class&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;old_class_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;old_module_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                 &lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;removal_version&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stacklevel&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;

 &lt;span class="c1"&gt;# Same as moved_decorator but for classes, returns a class proxy that can&lt;/span&gt;
 &lt;span class="c1"&gt;# not be inherited from (useful for when the user of this is aware that no&lt;/span&gt;
 &lt;span class="c1"&gt;# inheritance is happening)&lt;/span&gt;

 &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;moved_class_inheritable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;new_class&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;old_class_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;old_module_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                             &lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;removal_version&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stacklevel&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;

 &lt;span class="c1"&gt;# Same as moved_class but for classes, returns a new-old class that can&lt;/span&gt;
 &lt;span class="c1"&gt;# be inherited from (useful for when the user of this is unaware if any&lt;/span&gt;
 &lt;span class="c1"&gt;# inheritance is happening)&lt;/span&gt;

 &lt;span class="o"&gt;...&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;debtcollector/renames.py&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="c1"&gt;# Patterns devoted to 'renaming' functions, methods, classes, arguments...&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;renamed_kwarg&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;old_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;new_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                  &lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;removal_version&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stacklevel&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;

&lt;span class="c1"&gt;# Creates a decorator that can be applied to a keyword argument accepting&lt;/span&gt;
&lt;span class="c1"&gt;# method, function, callable that will warn the user of that function&lt;/span&gt;
&lt;span class="c1"&gt;# when they are using the old, to be removed keyword argument; creates&lt;/span&gt;
&lt;span class="c1"&gt;# an appropriate message telling the user this (in a similar format&lt;/span&gt;
&lt;span class="c1"&gt;# as mentioned above).&lt;/span&gt;

&lt;span class="o"&gt;...&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;debtcollector/utils.py&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="c1"&gt;# Generic *internal* library used utils...&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;generate_message&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prefix&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;postfix&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                     &lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;removal_version&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;

&lt;span class="c1"&gt;# Generates the messages for renames or moves in a common (share as much&lt;/span&gt;
&lt;span class="c1"&gt;# as possible manner) so that the messages look and feel like they are&lt;/span&gt;
&lt;span class="c1"&gt;# coming from a common library&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="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;Harlowja&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;You?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="primary-maintainer"&gt;
&lt;h3&gt;Primary maintainer&lt;/h3&gt;
&lt;p&gt;Primary maintainer:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Harlowja (@yahoo)&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;Szhukov (@yahoo)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="security-contact"&gt;
&lt;h3&gt;Security Contact&lt;/h3&gt;
&lt;p&gt;Security Contact: harlowja&lt;/p&gt;
&lt;/section&gt;
&lt;section id="milestones"&gt;
&lt;h3&gt;Milestones&lt;/h3&gt;
&lt;p&gt;Target Milestone for completion: kilo-2&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 owner of Launchpad project (make it part of the Oslo projectgroup)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://launchpad.net/debtcollector"&gt;https://launchpad.net/debtcollector&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Give openstackci Owner permissions on PyPI&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create Initial Repository&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Make the library do something&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update the README.rst&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Publish git repo&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Oslo team review new repository&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Infra project configuration&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update Gerrit Groups and ACLs&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;openstack-infra/devstack-gate adjustments&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;openstack/requirements projects.txt adjustments&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update project list on docs.openstack.org&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Tag a release&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Profit!&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="adoption-notes"&gt;
&lt;h2&gt;Adoption Notes&lt;/h2&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;section id="requirements"&gt;
&lt;h3&gt;Requirements&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;python 2.6 –&amp;gt; 3.4 (and beyond!)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;wrapt (&lt;a class="reference external" href="http://wrapt.readthedocs.org"&gt;http://wrapt.readthedocs.org&lt;/a&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;six (&lt;a class="reference external" href="https://bitbucket.org/gutworth/six"&gt;https://bitbucket.org/gutworth/six&lt;/a&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;All of the currently planned dependencies are in the requirements repository.&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="http://lists.openstack.org/pipermail/openstack-dev/2014-December/052692.html"&gt;http://lists.openstack.org/pipermail/openstack-dev/2014-December/052692.html&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This work is licensed under a Creative Commons Attribution 3.0
Unported License.
&lt;a class="reference external" href="http://creativecommons.org/licenses/by/3.0/legalcode"&gt;http://creativecommons.org/licenses/by/3.0/legalcode&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
</description><pubDate>Thu, 11 Dec 2014 00:00:00 </pubDate></item><item><title>Graduating Policy</title><link>https://specs.openstack.org/openstack/oslo-specs/specs/kilo/graduate-policy.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/oslo-incubator/+spec/graduate-policy"&gt;bp graduate-policy&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Graduate the policy API to a standalone library.&lt;/p&gt;
&lt;p&gt;The policy code is security sensitive and needs to be managed as a library. If
there is a CVE level defect, deploying a fix should require deploying a new
version of the library, not syncing each individual project.&lt;/p&gt;
&lt;section id="library-name"&gt;
&lt;h2&gt;Library Name&lt;/h2&gt;
&lt;p&gt;The new library will be called &lt;cite&gt;oslo.policy&lt;/cite&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="contents"&gt;
&lt;h2&gt;Contents&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;openstack/common/policy.py&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;tests/unit/test_policy.py&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;tests/var/policy.d&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;tests/var/policy.2.d&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;tests/var/policy.json&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="early-adopters"&gt;
&lt;h2&gt;Early Adopters&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Keystone&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="public-api"&gt;
&lt;h2&gt;Public API&lt;/h2&gt;
&lt;div class="highlight-python notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;oslo_policy&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;policy&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;All of the existing public functions and classes will remain public.&lt;/p&gt;
&lt;div class="highlight-python notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Rules&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="sd"&gt;"""A store for rules. Handles the default_rule setting directly."""&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Enforcer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;object&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="sd"&gt;"""Responsible for loading and enforcing rules.&lt;/span&gt;

&lt;span class="sd"&gt;    :param policy_file: Custom policy file to use, if none is&lt;/span&gt;
&lt;span class="sd"&gt;                        specified, `CONF.policy_file` will be&lt;/span&gt;
&lt;span class="sd"&gt;                        used.&lt;/span&gt;
&lt;span class="sd"&gt;    :param rules: Default dictionary / Rules to use. It will be&lt;/span&gt;
&lt;span class="sd"&gt;                considered just in the first instantiation. If&lt;/span&gt;
&lt;span class="sd"&gt;                `load_rules(True)`, `clear()` or `set_rules(True)`&lt;/span&gt;
&lt;span class="sd"&gt;                is called this will be overwritten.&lt;/span&gt;
&lt;span class="sd"&gt;    :param default_rule: Default rule to use, CONF.default_rule will&lt;/span&gt;
&lt;span class="sd"&gt;                        be used if none is specified.&lt;/span&gt;
&lt;span class="sd"&gt;    :param use_conf: Whether to load rules from cache or config file.&lt;/span&gt;
&lt;span class="sd"&gt;    :param overwrite: Whether to overwrite existing rules when reload rules&lt;/span&gt;
&lt;span class="sd"&gt;                    from config file.&lt;/span&gt;
&lt;span class="sd"&gt;    """&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The Rules class has a method to load the rules, currently only via a json file:&lt;/p&gt;
&lt;div class="highlight-python notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;load_json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;default_rule&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="sd"&gt;"""Allow loading of JSON rule data."""&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The Enforcer class handles rules and the enforcement action, which are
performed by the following public methods:&lt;/p&gt;
&lt;div class="highlight-python notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;set_rules&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rules&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;overwrite&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;use_conf&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="sd"&gt;"""Create a new Rules object based on the provided dict of rules.&lt;/span&gt;

&lt;span class="sd"&gt;    :param rules: New rules to use. It should be an instance of dict.&lt;/span&gt;
&lt;span class="sd"&gt;    :param overwrite: Whether to overwrite current rules or update them&lt;/span&gt;
&lt;span class="sd"&gt;                      with the new rules.&lt;/span&gt;
&lt;span class="sd"&gt;    :param use_conf: Whether to reload rules from cache or config file.&lt;/span&gt;
&lt;span class="sd"&gt;    """&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;clear&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="sd"&gt;"""Clears Enforcer rules, policy's cache and policy's path."""&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;load_rules&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;force_reload&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="sd"&gt;"""Loads policy_path's rules.&lt;/span&gt;

&lt;span class="sd"&gt;    Policy file is cached and will be reloaded if modified.&lt;/span&gt;

&lt;span class="sd"&gt;    :param force_reload: Whether to reload rules from config file.&lt;/span&gt;
&lt;span class="sd"&gt;    """&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;enforce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rule&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;creds&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;do_raise&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;exc&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&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="w"&gt;    &lt;/span&gt;&lt;span class="sd"&gt;"""Checks authorization of a rule against the target and credentials.&lt;/span&gt;

&lt;span class="sd"&gt;    :param rule: A string or BaseCheck instance specifying the rule&lt;/span&gt;
&lt;span class="sd"&gt;                to evaluate.&lt;/span&gt;
&lt;span class="sd"&gt;    :param target: As much information about the object being operated&lt;/span&gt;
&lt;span class="sd"&gt;                on as possible, as a dictionary.&lt;/span&gt;
&lt;span class="sd"&gt;    :param creds: As much information about the user performing the&lt;/span&gt;
&lt;span class="sd"&gt;                action as possible, as a dictionary.&lt;/span&gt;
&lt;span class="sd"&gt;    :param do_raise: Whether to raise an exception or not if check&lt;/span&gt;
&lt;span class="sd"&gt;                    fails.&lt;/span&gt;
&lt;span class="sd"&gt;    :param exc: Class of the exception to raise if the check fails.&lt;/span&gt;
&lt;span class="sd"&gt;                Any remaining arguments passed to enforce() (both&lt;/span&gt;
&lt;span class="sd"&gt;                positional and keyword arguments) will be passed to&lt;/span&gt;
&lt;span class="sd"&gt;                the exception class. If not specified, PolicyNotAuthorized&lt;/span&gt;
&lt;span class="sd"&gt;                will be used.&lt;/span&gt;

&lt;span class="sd"&gt;    :return: Returns False if the policy does not allow the action and&lt;/span&gt;
&lt;span class="sd"&gt;            exc is not provided; otherwise, returns a value that&lt;/span&gt;
&lt;span class="sd"&gt;            evaluates to True.  Note: for rules using the "case"&lt;/span&gt;
&lt;span class="sd"&gt;            expression, this True value will be the specified string&lt;/span&gt;
&lt;span class="sd"&gt;            from the expression.&lt;/span&gt;
&lt;span class="sd"&gt;    """&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;A basic check class along with some default extensions: FalseCheck, TrueCheck,
Check, NotCheck, AndCheck, OrCheck, RoleCheck, HttpCheck and GenericCheck. This
checks are used to validate the rules.&lt;/p&gt;
&lt;div class="highlight-python notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BaseCheck&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;object&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="sd"&gt;"""Abstract base class for Check classes."""&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Adam Young  ayoung &lt;a class="reference external" href="mailto:ayoung%40redhat.com"&gt;ayoung&lt;span&gt;@&lt;/span&gt;redhat&lt;span&gt;.&lt;/span&gt;com&lt;/a&gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Rodrigo Duarte rodrigodsousa &lt;a class="reference external" href="mailto:rodrigods%40lsd.ufcg.edu.br"&gt;rodrigods&lt;span&gt;@&lt;/span&gt;lsd&lt;span&gt;.&lt;/span&gt;ufcg&lt;span&gt;.&lt;/span&gt;edu&lt;span&gt;.&lt;/span&gt;br&lt;/a&gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="primary-maintainer"&gt;
&lt;h3&gt;Primary Maintainer&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary Maintainer:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Unknown&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="security-contact"&gt;
&lt;h3&gt;Security Contact&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Security Contact:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;ayoung&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="milestones"&gt;
&lt;h3&gt;Milestones&lt;/h3&gt;
&lt;p&gt;kilo-2&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;The work items are outlined in the &lt;a class="reference external" href="https://wiki.openstack.org/wiki/Oslo/CreatingANewLibrary#Graduating_a_Library_from_the_Incubator"&gt;oslo graduation tutorial.&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The public repository, with the code extracted from the incubation module
can be found &lt;a class="reference external" href="https://github.com/rodrigods/oslo.policy"&gt;here&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="adoption-notes"&gt;
&lt;h2&gt;Adoption Notes&lt;/h2&gt;
&lt;p&gt;Once released, projects using oslo.policy should change the way policy.py is
being imported to use the &lt;cite&gt;oslo_policy&lt;/cite&gt; module instead of the current
&lt;cite&gt;&amp;lt;project&amp;gt;.openstack.common&lt;/cite&gt;. Also, they will need to add the lib as
requirements (add to requirements.txt and/or test-requirements.txt files).&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Library will require its own documentation, but that will be done post
graduation.&lt;/p&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="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/kilo-oslo-library-proposals"&gt;Oslo Graduation Schedule&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This work is licensed under a Creative Commons Attribution 3.0
Unported License.
&lt;a class="reference external" href="http://creativecommons.org/licenses/by/3.0/legalcode"&gt;http://creativecommons.org/licenses/by/3.0/legalcode&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
</description><pubDate>Mon, 08 Dec 2014 00:00:00 </pubDate></item><item><title>oslo.messaging: Notification listener pools</title><link>https://specs.openstack.org/openstack/oslo-specs/specs/kilo/notification-listener-pools.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/oslo.messaging/+spec/notification-listener-pools"&gt;https://blueprints.launchpad.net/oslo.messaging/+spec/notification-listener-pools&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The idea is that you can have multiple groups/pools of listeners
consuming notifications and that each group/pool only receives one
copy of each notification.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Currently if two applications use the oslo.messaging notification listener
and want to subscribe to the same topic, they steal messages from each other.&lt;/p&gt;
&lt;p&gt;The current workaround is to configure the notifier part to publish the message
twice on different topic. This confuses a lot of people and this is
undocumented.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;So part of the purpose of this BP is a bit hardcoded into oslo.messaging and
have bad side effect. The proposal will fix that.&lt;/p&gt;
&lt;p&gt;We need to add a pool parameter for the messaging.get_notification_listener()
API in order to support this.&lt;/p&gt;
&lt;p&gt;In all AMQP drivers, this is implemented by using the pool name as the queue
name for consume from the topic. To keep backward compatibility, by default,
the topic name will continue to be used as the pool/queue name.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Documents the workaround.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="impact-on-existing-apis"&gt;
&lt;h3&gt;Impact on Existing APIs&lt;/h3&gt;
&lt;p&gt;oslo.messaging.get_notification_listener will get a new parameter ‘pool’ to
configure the pool name.&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="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="configuration-impact"&gt;
&lt;h3&gt;Configuration 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="testing-impact"&gt;
&lt;h3&gt;Testing 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;sileht&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="milestones"&gt;
&lt;h3&gt;Milestones&lt;/h3&gt;
&lt;p&gt;K-1&lt;/p&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;p&gt;Works already done: &lt;a class="reference external" href="https://review.openstack.org/125112"&gt;https://review.openstack.org/125112&lt;/a&gt;&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="incubation"&gt;
&lt;h2&gt;Incubation&lt;/h2&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;section id="adoption"&gt;
&lt;h3&gt;Adoption&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="library"&gt;
&lt;h3&gt;Library&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="anticipated-api-stabilization"&gt;
&lt;h3&gt;Anticipated API Stabilization&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;The new pool parameter will be documented.&lt;/p&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="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;Code in review: &lt;a class="reference external" href="https://review.openstack.org/#/c/125112/"&gt;https://review.openstack.org/#/c/125112/&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 work is licensed under a Creative Commons Attribution 3.0
Unported License.
&lt;a class="reference external" href="http://creativecommons.org/licenses/by/3.0/legalcode"&gt;http://creativecommons.org/licenses/by/3.0/legalcode&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
</description><pubDate>Tue, 02 Dec 2014 00:00:00 </pubDate></item><item><title>Notification Dispatcher Filter</title><link>https://specs.openstack.org/openstack/oslo-specs/specs/kilo/notification-dispatcher-filter.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/oslo?searchtext=notification-dispatcher-filter"&gt;https://blueprints.launchpad.net/oslo?searchtext=notification-dispatcher-filter&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Oslo.messaging lacks the ability to filter out notifications it sends to
endpoints. This spec proposes to enable filtering process before messages are
dispatched to endpoints.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Currently, oslo.messaging blindly dispatches notifications to all registered
endpoints. It is after the endpoints receive the messages are we able to filter
and decide whether the endpoint should process the notifications. This decision
can be made earlier before it dispatches messages to the endpoints to avoid
the overhead of sending messages to endpoints which will ignore them.&lt;/p&gt;
&lt;p&gt;For example, in Ceilometer, multiple endpoints are connected to the
notification listener. Each endpoint may only process a subset of the
notifications that are picked up. It is at the endpoint level where we
currently filter whether to continue processing the notification but this
filtering can easily be done before it’s even dispatched to the endpoint.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;The proposed solution is to add a NotificationFilter to the dispatcher. When
oslo.messaging dispatches messages to the endpoints, it will first pass through
the filter and check if the messages fits the criteria defined in filter.
Messages can be filtered using regex against all first level attributes of a
message: context, publisher_id, event_type, metadata, and payload. As context,
metadata, and payload are dictionary values, multiple contraints can be
defined for them.&lt;/p&gt;
&lt;p&gt;An example filter is 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="nb"&gt;filter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;  &lt;span class="n"&gt;NotificationFilter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;publisher_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'^compute.*'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;'tenant_id'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'^5f643cfc-664b-4c69-8000-ce2ed7b08216$'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
             &lt;span class="s1"&gt;'roles'&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="n"&gt;event_type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'^compute\.instance\..*'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;metadata&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;'timestamp'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'Aug'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
    &lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;'state'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'^active$'&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;We continue to filter at the endpoint level.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="impact-on-existing-apis"&gt;
&lt;h3&gt;Impact on Existing APIs&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="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None, but it does offer potential to reduce load dispatched.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="configuration-impact"&gt;
&lt;h3&gt;Configuration 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 nowi have ability to add a filter when they defined Endpoints.&lt;/p&gt;
&lt;div class="highlight-python notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;NotificationEndpoint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;object&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="nb"&gt;filter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;NotificationFilter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;publisher_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'^compute.*'&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="testing-impact"&gt;
&lt;h3&gt;Testing Impact&lt;/h3&gt;
&lt;p&gt;Unit tests are sufficient as the functionality is limited to dispatcher.
Indirectly, when implemented in Ceilometer, this will be tested via tempest.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;sileht&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;gordc&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="milestones"&gt;
&lt;h3&gt;Milestones&lt;/h3&gt;
&lt;p&gt;Target Milestone for completion: kilo-1&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 filter to dispatcher with unit tests&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;change filters in Ceilometer to use new filters.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="incubation"&gt;
&lt;h2&gt;Incubation&lt;/h2&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;section id="adoption"&gt;
&lt;h3&gt;Adoption&lt;/h3&gt;
&lt;p&gt;Ceilometer but it seems like common functionality that other listeners
would use.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="library"&gt;
&lt;h3&gt;Library&lt;/h3&gt;
&lt;p&gt;oslo.messaging.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="anticipated-api-stabilization"&gt;
&lt;h3&gt;Anticipated API Stabilization&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&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="dependencies"&gt;
&lt;h2&gt;Dependencies&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;code review: &lt;a class="reference external" href="http://review.openstack.org/#/c/77886/"&gt;http://review.openstack.org/#/c/77886/&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 work is licensed under a Creative Commons Attribution 3.0
Unported License.
&lt;a class="reference external" href="http://creativecommons.org/licenses/by/3.0/legalcode"&gt;http://creativecommons.org/licenses/by/3.0/legalcode&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
</description><pubDate>Tue, 18 Nov 2014 00:00:00 </pubDate></item><item><title>Provide application-agnostic logging parameters in format strings</title><link>https://specs.openstack.org/openstack/oslo-specs/specs/kilo/app-agnostic-logging-parameters.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/oslo.log/+spec/app-agnostic-logging-parameters"&gt;https://blueprints.launchpad.net/oslo.log/+spec/app-agnostic-logging-parameters&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;We still have some nova-specific names in the default logging format
string, and we want to eliminate those to make oslo.log more generally
useful across projects.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;The default &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;logging_context_format_string&lt;/span&gt;&lt;/code&gt; and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;logging_default_format_string&lt;/span&gt;&lt;/code&gt; option values include
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;%(instance)s&lt;/span&gt;&lt;/code&gt;, which is not useful in all projects. We should do
something like what we did with “user_identity” and provide a generic
name, which the projects can fill in with their desired value.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Make &lt;code class="xref py py-class docutils literal notranslate"&gt;&lt;span class="pre"&gt;RequestContext&lt;/span&gt;&lt;/code&gt; from &lt;code class="xref py py-mod docutils literal notranslate"&gt;&lt;span class="pre"&gt;openstack.common.context&lt;/span&gt;&lt;/code&gt; into
an abstract base class for other applications to use for their own
application-specific request contexts. In the new base class, define
some abstract properties with generic names like &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;user_identity&lt;/span&gt;&lt;/code&gt;,
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;resource_id&lt;/span&gt;&lt;/code&gt;, the chain of request ids, etc. that the subclass
can override.&lt;/p&gt;
&lt;p&gt;Change the default for the logging format strings to refer to these
generic names.&lt;/p&gt;
&lt;p&gt;Add a new method to the base class to return values useful for
logging. We cannot use the existing &lt;code class="xref py py-meth docutils literal notranslate"&gt;&lt;span class="pre"&gt;to_dict()&lt;/span&gt;&lt;/code&gt; because we expect
the logging values to contain generated properties not used for things
like reconstructing the context when it passes through RPC calls.&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_logging_values&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="sd"&gt;"""Return a dict containing values for logging using this context.&lt;/span&gt;
&lt;span class="sd"&gt;    """&lt;/span&gt;
    &lt;span class="n"&gt;values&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;to_dict&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;values&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="s1"&gt;'user_identity'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;user_identity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="s1"&gt;'resource_id'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;resource_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="s1"&gt;'request_chain'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;' '&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;request_ids&lt;/span&gt;&lt;span class="p"&gt;),&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;values&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Remove the other functions in the &lt;code class="xref py py-mod docutils literal notranslate"&gt;&lt;span class="pre"&gt;context&lt;/span&gt;&lt;/code&gt; module for creating
and testing contexts. The applications all have their own version of
these functions and the versions provided in &lt;code class="xref py py-mod docutils literal notranslate"&gt;&lt;span class="pre"&gt;context&lt;/span&gt;&lt;/code&gt; are not
useful when subclasses of &lt;code class="xref py py-class docutils literal notranslate"&gt;&lt;span class="pre"&gt;RequestContext&lt;/span&gt;&lt;/code&gt; are used.&lt;/p&gt;
&lt;p&gt;Update the logging code to use &lt;code class="xref py py-meth docutils literal notranslate"&gt;&lt;span class="pre"&gt;get_logging_values()&lt;/span&gt;&lt;/code&gt; instead of
&lt;code class="xref py py-meth docutils literal notranslate"&gt;&lt;span class="pre"&gt;to_dict()&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 had previously talked about removing this module entirely, but
given changes to logging to make the user identity parameters log
consistently across projects, I think making it a useful base class is
a better approach.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="impact-on-existing-apis"&gt;
&lt;h3&gt;Impact on Existing APIs&lt;/h3&gt;
&lt;p&gt;Existing context classes will be updated to be subclasses of the base
class, which may allow us to save some repeated code in the
constructor.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;When we talk about logging and contexts together we typically worry
about exposing secret details. I don’t think any of these proposed
changes expose any information beyond what we are exposing already.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;Possibly a slight impact creating &lt;code class="xref py py-class docutils literal notranslate"&gt;&lt;span class="pre"&gt;RequestContext&lt;/span&gt;&lt;/code&gt; instances in
the application. If an app sees that as a problem, they could opt to
simply copy the base class API into their local class rather than
using a subclass, but it would be up to them to keep up with API
changes at that point. I don’t think this is a significant performance
issue.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="configuration-impact"&gt;
&lt;h3&gt;Configuration Impact&lt;/h3&gt;
&lt;p&gt;The defaults for the configuration options might change, but the
&lt;em&gt;output&lt;/em&gt; should be the same and the old values will still work as well
as they did before.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer Impact&lt;/h3&gt;
&lt;p&gt;The idea is for the other projects to define their context as a
subclass of the &lt;code class="xref py py-class docutils literal notranslate"&gt;&lt;span class="pre"&gt;RequestContext&lt;/span&gt;&lt;/code&gt; in Oslo, implementing or
overriding private methods or properties in order to meet the API
needed by the logging module.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Doug Hellmann (doug-hellmann)&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="milestones"&gt;
&lt;h3&gt;Milestones&lt;/h3&gt;
&lt;p&gt;Target Milestone for completion: Kilo-2&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;Remove unused functions from &lt;code class="xref py py-mod docutils literal notranslate"&gt;&lt;span class="pre"&gt;context&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add new &lt;code class="xref py py-meth docutils literal notranslate"&gt;&lt;span class="pre"&gt;get_logging_values()&lt;/span&gt;&lt;/code&gt; to &lt;code class="xref py py-class docutils literal notranslate"&gt;&lt;span class="pre"&gt;RequestContext&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add abstract properties to &lt;code class="xref py py-class docutils literal notranslate"&gt;&lt;span class="pre"&gt;RequestContext&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update default format strings in &lt;code class="xref py py-mod docutils literal notranslate"&gt;&lt;span class="pre"&gt;log&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update &lt;code class="xref py py-mod docutils literal notranslate"&gt;&lt;span class="pre"&gt;log&lt;/span&gt;&lt;/code&gt; to use &lt;code class="xref py py-meth docutils literal notranslate"&gt;&lt;span class="pre"&gt;get_logging_values()&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="incubation"&gt;
&lt;h2&gt;Incubation&lt;/h2&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;section id="adoption"&gt;
&lt;h3&gt;Adoption&lt;/h3&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;section id="library"&gt;
&lt;h3&gt;Library&lt;/h3&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;section id="anticipated-api-stabilization"&gt;
&lt;h3&gt;Anticipated API Stabilization&lt;/h3&gt;
&lt;p&gt;I expect &lt;code class="xref py py-meth docutils literal notranslate"&gt;&lt;span class="pre"&gt;get_logging_values()&lt;/span&gt;&lt;/code&gt; to be stable.&lt;/p&gt;
&lt;p&gt;We may add more generated properties to &lt;code class="xref py py-class docutils literal notranslate"&gt;&lt;span class="pre"&gt;RequestContext&lt;/span&gt;&lt;/code&gt; over
time, but we will have to add those as normal properties (not
abstract) to provide backwards compatibility.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;The defaults for the config options will need to be updated in any
documentation generated from the option definitions.&lt;/p&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="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Discussion at the juno summit:
&lt;a class="reference external" href="https://etherpad.openstack.org/p/juno-oslo-release-plan"&gt;https://etherpad.openstack.org/p/juno-oslo-release-plan&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Mailing list thread that mentions the domain support in Oslo’s
context as a potential issue for nova:
&lt;a class="reference external" href="http://lists.openstack.org/pipermail/openstack-dev/2014-February/027634.html"&gt;http://lists.openstack.org/pipermail/openstack-dev/2014-February/027634.html&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This work is licensed under a Creative Commons Attribution 3.0
Unported License.
&lt;a class="reference external" href="http://creativecommons.org/licenses/by/3.0/legalcode"&gt;http://creativecommons.org/licenses/by/3.0/legalcode&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
</description><pubDate>Mon, 03 Nov 2014 00:00:00 </pubDate></item><item><title>Graduating oslo.context</title><link>https://specs.openstack.org/openstack/oslo-specs/specs/kilo/graduate-oslo-context.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/oslo-incubator/+spec/graduate-oslo-context"&gt;https://blueprints.launchpad.net/oslo-incubator/+spec/graduate-oslo-context&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;oslo.context holds the context base class, which defines APIs used by
oslo.messaging and oslo.log.&lt;/p&gt;
&lt;section id="library-name"&gt;
&lt;h2&gt;Library Name&lt;/h2&gt;
&lt;p&gt;What is the name of the new library?: oslo.context&lt;/p&gt;
&lt;/section&gt;
&lt;section id="contents"&gt;
&lt;h2&gt;Contents&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;openstack/common/context.py&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;tests/unit/test_context.py&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="early-adopters"&gt;
&lt;h2&gt;Early Adopters&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;oslo.log&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;oslo.messaging&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="public-api"&gt;
&lt;h2&gt;Public API&lt;/h2&gt;
&lt;div class="highlight-default 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="nn"&gt;oslo_context&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;All of the existing public functions and classes will remain public.&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;generate_request_id&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="s2"&gt;"Return a unique request identifier."&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;RequestContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;object&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="sd"&gt;"""Helper class to represent useful information about a request context.&lt;/span&gt;

&lt;span class="sd"&gt;    Stores information about the security context under which the user&lt;/span&gt;
&lt;span class="sd"&gt;    accesses the system, as well as additional request information.&lt;/span&gt;
&lt;span class="sd"&gt;    """&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_admin_context&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;show_deleted&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="s2"&gt;"Return a RequestContext configured as an admin user"&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_context_from_function_and_args&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;function&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="sd"&gt;"""Find an arg of type RequestContext and return it.&lt;/span&gt;

&lt;span class="sd"&gt;       This is useful in a couple of decorators where we don't&lt;/span&gt;
&lt;span class="sd"&gt;       know much about the function we're wrapping.&lt;/span&gt;
&lt;span class="sd"&gt;    """&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;is_user_context&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="sd"&gt;"""Indicates if the request context is a normal user."""&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;A private registry of context objects will be kept using a
threading.local() instance and logic based on
nova.context.RequestContext. A new public API for accessing the
context will be added:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_current&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="s2"&gt;"Return this thread's current context"&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;doug-hellmann&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="primary-maintainer"&gt;
&lt;h3&gt;Primary Maintainer&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary Maintainer:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Unknown&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="security-contact"&gt;
&lt;h3&gt;Security Contact&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Security Contact:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;doug-hellmann&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="milestones"&gt;
&lt;h3&gt;Milestones&lt;/h3&gt;
&lt;p&gt;Target Milestone for completion: kilo-1&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;&lt;a class="reference external" href="https://wiki.openstack.org/wiki/Oslo/CreatingANewLibrary#Checklist"&gt;https://wiki.openstack.org/wiki/Oslo/CreatingANewLibrary#Checklist&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add registry management logic.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We will evolve the API for RequestContext after exporting it, based
on needs for oslo.messaging and oslo.log. Those changes have not yet
been worked out, and will come in another spec.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="adoption-notes"&gt;
&lt;h2&gt;Adoption Notes&lt;/h2&gt;
&lt;p&gt;Projects using oslo.context should subclass
oslo_context.RequestContext and create their own application-specific
context class.&lt;/p&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="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/kilo-oslo-library-proposals"&gt;https://etherpad.openstack.org/p/kilo-oslo-library-proposals&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/oslo.log/+spec/remove-context-adapter"&gt;https://blueprints.launchpad.net/oslo.log/+spec/remove-context-adapter&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/oslo.log/+spec/app-agnostic-logging-parameters"&gt;https://blueprints.launchpad.net/oslo.log/+spec/app-agnostic-logging-parameters&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This work is licensed under a Creative Commons Attribution 3.0
Unported License.
&lt;a class="reference external" href="http://creativecommons.org/licenses/by/3.0/legalcode"&gt;http://creativecommons.org/licenses/by/3.0/legalcode&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
</description><pubDate>Tue, 28 Oct 2014 00:00:00 </pubDate></item><item><title>Drop our use of namespace packages</title><link>https://specs.openstack.org/openstack/oslo-specs/specs/kilo/drop-namespace-packages.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/oslo-incubator/+spec/drop-namespace-packages"&gt;https://blueprints.launchpad.net/oslo-incubator/+spec/drop-namespace-packages&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Installing our libraries into a namespace package has caused several
types of errors. Rather than continuing to fight with them, I propose
that we phase them out.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;The namespace package support in setuptools is fragile, and some of
the ways we use code regularly within OpenStack expose the issues in
ways that are hard to debug.&lt;/p&gt;
&lt;p&gt;The main issue we have seen is with installing two separate libraries
into the same python namespace package using different installation
“modes”. If one library installed with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;pip&lt;/span&gt; &lt;span class="pre"&gt;install&lt;/span&gt; &lt;span class="pre"&gt;-e&lt;/span&gt;&lt;/code&gt; to enable
“editable” mode, and another is installed without the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;-e&lt;/span&gt;&lt;/code&gt; option as
a regular library, then the import path for the package is broken and
some of the installed components are not importable. This happened a
lot when devstack installed Oslo libraries editable, and we have
changed devstack to stop doing that by default. It also happens when a
developer installs something using a system package and then installs
another library from source. We have no real way to control that
behavior, so it still crops up from time to time.&lt;/p&gt;
&lt;p&gt;We also see trouble with virtualenvs configured to allow access to the
global site-packages directory, as nova needs for libvirt access. If
anything from the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo&lt;/span&gt;&lt;/code&gt; namespace package is installed globally, it
will shadow the versions visible in the virtualenv. That would
normally lead to a version error if some old version is installed
globally, but in this case it can also lead to import errors because
the namespace package doesn’t not properly span the two site-packages
directories.&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 that we move all current Oslo libraries out of the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo&lt;/span&gt;&lt;/code&gt;
namespace and create simple packages that can be imported
independently. For example, we would change:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;oslo.foo&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;bar&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;to:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;oslo_foo&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;bar&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;To avoid issues with distros, we should not rename the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo.foo&lt;/span&gt;&lt;/code&gt;
library to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo_foo&lt;/span&gt;&lt;/code&gt;. This may be a little confusing for
developers, so we might look at the decision again in the future, but
as a first step this is less obtrusive because it means we don’t need
to change our requirements lists, repository names, and distro package
names.&lt;/p&gt;
&lt;p&gt;To support backwards compatibility, we will provide shadow-packages
for the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo&lt;/span&gt;&lt;/code&gt; namespace so that the old import form still works for
the Kilo releases of the libraries. That will give us time to update
all of the applications and let them cycle out of the long-term
support window before dropping the namespace packages entirely during
the M release.&lt;/p&gt;
&lt;p&gt;Moving to regular packages will also let us move our unit tests inside
the library, so they are delivered and installed under &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo_foo&lt;/span&gt;&lt;/code&gt;,
so we should do that at the same time, retaining just enough of the
test suite to ensure that the public API exposed through the namespace
package still works.&lt;/p&gt;
&lt;p&gt;The distribution names of existing libraries won’t change, and the
same pattern will be used to create new libraries to avoid
confusion. That means one would &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;pip&lt;/span&gt; &lt;span class="pre"&gt;install&lt;/span&gt; &lt;span class="pre"&gt;oslo.foo&lt;/span&gt;&lt;/code&gt; and then
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;from&lt;/span&gt; &lt;span class="pre"&gt;oslo_foo&lt;/span&gt; &lt;span class="pre"&gt;import&lt;/span&gt; &lt;span class="pre"&gt;bar&lt;/span&gt;&lt;/code&gt;.&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;lifeless has a patch to oslo.db that sets up the namespace package
using pkgutils instead of setuptools:&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;&lt;a class="reference external" href="https://review.openstack.org/#/c/123604/3/oslo/__init__.py"&gt;https://review.openstack.org/#/c/123604/3/oslo/__init__.py&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;This retains the ability to use namespace packages, with the extra
cost of shipping a real &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo&lt;/span&gt;&lt;/code&gt; library
(&lt;a class="reference external" href="https://github.com/rbtcollins/oslo"&gt;https://github.com/rbtcollins/oslo&lt;/a&gt;) and maintaining the override
code ourselves. We don’t know what other issues we might find with
namespace packages, though, so I’m more comfortable with just
dropping them entirely.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Python 3 has better native namespace package support, so we could
review the decision when we move to Python 3.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Do nothing, and continue to help developers debug problems on their
systems when they come up. If we choose this option, we might want
to write a script “why_is_oslo_broken.sh” to put in the incubator.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The “oslo_” name prefix was selected to distinguish the libs from the
non-production libraries like oslotest and oslosphinx. We could
theoretially rename those as well so that all of our branded libraries
have the same naming convention. I don’t know if that’s worth doing or
not.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="impact-on-existing-apis"&gt;
&lt;h3&gt;Impact on Existing APIs&lt;/h3&gt;
&lt;p&gt;The imports will change, but we should not need to change other
aspects of the libraries’ APIs.&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="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="configuration-impact"&gt;
&lt;h3&gt;Configuration 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 need to be aware of the import changes. We have a few
options for communicating that widely:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Add a deprecation warning to the oslo namespace packages so
importing them reports a warning.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add a hacking rule to make importing “from oslo.” illegal.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Rely on reviewers to catch it.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Option 1 is easy for us to do ourselves.&lt;/p&gt;
&lt;p&gt;Option 2 has to wait until we have converted all of our own libraries,
and updated all the apps, but it would then prevent improper imports
being restored.&lt;/p&gt;
&lt;p&gt;Option 3 is brittle, so I don’t think we want to rely on it alone.&lt;/p&gt;
&lt;p&gt;To ease the transition, we should be able to prepare a bash/sed script
to make the required edits to a project.  I don’t think we’ll have
more than a handful of different types of import statements, but we
can update the script as we find new patterns&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing-impact"&gt;
&lt;h3&gt;Testing Impact&lt;/h3&gt;
&lt;p&gt;The unit tests will be updated in each library so that all of them run
against the new module name. Then some of the public API tests will be
duplicated to use the namespace package to ensure that we don’t break
that.&lt;/p&gt;
&lt;p&gt;The existing unit tests in applications should cover the uses of the
libraries in the applications. We will need to update any mocks in
those tests.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Doug Hellmann&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="milestones"&gt;
&lt;h3&gt;Milestones&lt;/h3&gt;
&lt;p&gt;Target Milestone for completion: K-2 (I hope early)&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;Rearrange all of our library code, including tests and
documentation. See &lt;a class="reference external" href="https://review.openstack.org/#/c/127323/"&gt;https://review.openstack.org/#/c/127323/&lt;/a&gt; for an
example.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Write helper script for liaisons (maybe a liaison can do this?).&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="incubation"&gt;
&lt;h2&gt;Incubation&lt;/h2&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;section id="adoption"&gt;
&lt;h3&gt;Adoption&lt;/h3&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;section id="library"&gt;
&lt;h3&gt;Library&lt;/h3&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;section id="anticipated-api-stabilization"&gt;
&lt;h3&gt;Anticipated API Stabilization&lt;/h3&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&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="dependencies"&gt;
&lt;h2&gt;Dependencies&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&gt;
&lt;li&gt;&lt;p&gt;setuptools bug 250, “develop and
&lt;cite&gt;–install-single-version-externally-managed&lt;/cite&gt; are not compatible
with each other for namespace packages” -
&lt;a class="reference external" href="https://bitbucket.org/pypa/setuptools/issue/250/develop-and-install-single-version"&gt;https://bitbucket.org/pypa/setuptools/issue/250/develop-and-install-single-version&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;lifeless has a patch to oslo.db that sets up the namespace package
using pkgutils instead of setuptools:&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://review.openstack.org/#/c/123604/3/oslo/__init__.py"&gt;https://review.openstack.org/#/c/123604/3/oslo/__init__.py&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;it uses a real oslo package: &lt;a class="reference external" href="https://github.com/rbtcollins/oslo"&gt;https://github.com/rbtcollins/oslo&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;PEP-420 spec: &lt;a class="reference external" href="http://legacy.python.org/dev/peps/pep-0420/"&gt;http://legacy.python.org/dev/peps/pep-0420/&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;My WIP patch for oslo.i18n to move it out of the namespace package:
&lt;a class="reference external" href="https://review.openstack.org/#/c/127323/"&gt;https://review.openstack.org/#/c/127323/&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Notes from the Kilo summit session:
&lt;a class="reference external" href="https://etherpad.openstack.org/p/kilo-oslo-namespace-packages"&gt;https://etherpad.openstack.org/p/kilo-oslo-namespace-packages&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Mailing list thread following up after the Kilo summit:
&lt;a class="reference external" href="http://lists.openstack.org/pipermail/openstack-dev/2014-November/050313.html"&gt;http://lists.openstack.org/pipermail/openstack-dev/2014-November/050313.html&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This work is licensed under a Creative Commons Attribution 3.0
Unported License.
&lt;a class="reference external" href="http://creativecommons.org/licenses/by/3.0/legalcode"&gt;http://creativecommons.org/licenses/by/3.0/legalcode&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
</description><pubDate>Wed, 15 Oct 2014 00:00:00 </pubDate></item><item><title>Make EngineFacade into a Facade</title><link>https://specs.openstack.org/openstack/oslo-specs/specs/kilo/make-enginefacade-a-facade.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/oslo.db/+spec/make-enginefacade-a-facade"&gt;https://blueprints.launchpad.net/oslo.db/+spec/make-enginefacade-a-facade&lt;/a&gt;&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;The oslo.db.sqlalchemy.session.EngineFacade class serves as the gateway
to the SQLAlchemy Engine and Session objects within many OpenStack projects,
including Ceilometer, Glance, Heat, Ironic, Keystone, Neutron, Nova, and
Sahara.  However, the object is severely under-functional; while it provides
a function call that ultimately calls &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;create_engine()&lt;/span&gt;&lt;/code&gt; and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;sessionmaker()&lt;/span&gt;&lt;/code&gt;, consuming projects receive no other utility from this
object, and in order to solve closely related problems that all of them
share, each invent their own systems, all of which are different,
verbose, and error prone, with various performance, stability,
and scalability issues.&lt;/p&gt;
&lt;section id="registry-functionality"&gt;
&lt;h3&gt;Registry Functionality&lt;/h3&gt;
&lt;p&gt;In the first case, EngineFacade as used by projects needs to act as a
thread-safe registry, a feature which it does not provide and for
which each consuming project has had to invent directly.   These
inventions are verbose and inconsistent.&lt;/p&gt;
&lt;p&gt;For example, in Keystone, the EngineFacade is created thusly in
keystone/common/sql/core.py:&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;_engine_facade&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;_get_engine_facade&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;global&lt;/span&gt; &lt;span class="n"&gt;_engine_facade&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;_engine_facade&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;_engine_facade&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;db_session&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EngineFacade&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;from_config&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CONF&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;_engine_facade&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;In Ironic we have this; Sahara contains something similar:&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;_FACADE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;_create_facade_lazily&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;global&lt;/span&gt; &lt;span class="n"&gt;_FACADE&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;_FACADE&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;_FACADE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;db_session&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EngineFacade&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;CONF&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;database&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CONF&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;database&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;iteritems&lt;/span&gt;&lt;span class="p"&gt;())&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;_FACADE&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;However in Nova, we get a similar pattern but with one very critical twist:&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;_ENGINE_FACADE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;
&lt;span class="n"&gt;_LOCK&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;threading&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Lock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;_create_facade_lazily&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;global&lt;/span&gt; &lt;span class="n"&gt;_LOCK&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_ENGINE_FACADE&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;_ENGINE_FACADE&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="kc"&gt;None&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;_LOCK&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;_ENGINE_FACADE&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;_ENGINE_FACADE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;db_session&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EngineFacade&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;from_config&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CONF&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;_ENGINE_FACADE&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Each library invents their own system of establishing EngineFacade as a
singleton, and providing CONF into it; none of which are alike.
Nova happened to discover that this singleton pattern isn’t threadsafe,
and added a mutex, however the lack of this critical improvement remains a
bug in all the other systems.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="transactional-resource-functionality"&gt;
&lt;h3&gt;Transactional Resource Functionality&lt;/h3&gt;
&lt;p&gt;Adding a fully functional creational pattern is an easy win,
but the problem goes beyond that.  EngineFacade ends its work at &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;get_engine()&lt;/span&gt;&lt;/code&gt;
or &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;get_session()&lt;/span&gt;&lt;/code&gt;; the former returns a SQLAlchemy Engine object, which
itself is only a factory for connections, and the latter returns a
SQLAlchemy Session object, ready for use but otherwise unassociated with
any specific connection or transactional context.&lt;/p&gt;
&lt;p&gt;The definition of “facade” is a layer that conceals the use of fine-
grained APIs behind a layer that is coarse-grained and tailored to the
use case at hand.   By this definition, the EngineFacade currently is
only a factory, and not a facade.&lt;/p&gt;
&lt;p&gt;The harm caused by this lack of guidance on EngineFacade’s part is widespread.
While the failure to provide an adequate creational pattern leads
each Openstack project to invent its own workaround,
the failure to provide any guidance on connectivity or transactional
scope gives rise to a much more significant pattern of poor implementations
on the part of all Openstack projects.   Each project observed illustrates
mis-use of engines, sessions and transactions to a greater or lesser degree,
more often than not having direct consequences for performance, stability,
and maintainability.&lt;/p&gt;
&lt;p&gt;The general theme among all projects is that while they are all
presented as web services, there is no structure in place which
establishes connectivity and transactional scope for a service method
as a whole.  Individual methods include explicit boilerplate which
establishes some kind of connectivity, either within a transaction or
not.  The format of this boilerplate alone is not only inconsistent
between projects, it’s inconsistent within a single project and even
in a single module, sometimes intentionally and sometimes not.
Equally if not more seriously, individual API methods very frequently
proceed across a span of multiple connections and non-connected
transactions within the scope of a single operation, and in some cases
the multiple transactions are even nested. The use of multiple
connections and transactions is in the first place a major performance
impediment, and in the second place dilutes the usefulness of
transactional logic in the first place as an API method is not
actually atomic.   When transactions are actually nested, the risk surface
for deadlocks increases significantly.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="transactional-scoping-examples"&gt;
&lt;h3&gt;Transactional Scoping Examples&lt;/h3&gt;
&lt;p&gt;This section will detail some specific examples of the issues just described,
for those who are curious.&lt;/p&gt;
&lt;p&gt;We first show Neutron’s system, which is the most
organized and probably has the fewest issues of this nature.
Neutron has a system where all database operations proceed
where a neutron.context.Context object is passed; the Context object serves
as home base to a SQLAlchemy Session that was ultimately retrieved
from EngineFacade.   A method excerpt looks 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="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;add_resource_association&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;service_type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;provider_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                             &lt;span class="n"&gt;resource_id&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;

    &lt;span class="c1"&gt;# ...&lt;/span&gt;

    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;begin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;subtransactions&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;assoc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ProviderResourceAssociation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;provider_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;provider_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                            &lt;span class="n"&gt;resource_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;resource_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;assoc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;We see that while the Context object at least allows that all operations
are given access to the same Session, the method still has to state
that it wishes to begin a transaction, and that it needs to support the
fact that the Session may already be within a transaction.   Neutron’s system
is a little verbose, and suffers from the issue that individual methods called
in series may invoke their work within distinct transactions on new
connections each time,  but at least ensures that just one Session is in
play for a given API method from start to finish; this prevents the issue
of inadvertent multiple transaction nesting, as the Session’s &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;begin()&lt;/span&gt;&lt;/code&gt;
method will disallow a nested call from opening a new connection.&lt;/p&gt;
&lt;p&gt;Next we look at Keystone.  Keystone has some database-related helper functions
but they don’t serve any functional purpose other than some naming abstraction.
Keystone has a lot of short “lookup” methods, so many of them
look like this:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="nd"&gt;@sql&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;handle_conflicts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;conflict_type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'trust'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;list_trusts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;session&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sql&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_session&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;trusts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TrustModel&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;filter_by&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;deleted_at&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;trust_ref&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;to_dict&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;trust_ref&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;trusts&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Above, the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;sql.get_session()&lt;/span&gt;&lt;/code&gt; call is just another call to
EngineFacade.get_session(), and that’s where the connectivity is set up.
The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;sql.handle_conflicts()&lt;/span&gt;&lt;/code&gt; call doesn’t have any role in establishing
this session.&lt;/p&gt;
&lt;p&gt;The above call uses the SQLAlchemy Session in “autocommit” mode; in
this mode, SQLAlchemy essentially creates connection/transaction
context on a per-query basis, and discards it when the query is complete;
using the Python Database API (DBAPI), there is no cross-platform option to
prevent a transaction from ultimately being present; hence “autocommit”
doesn’t mean, “no transaction”.&lt;/p&gt;
&lt;p&gt;In all but the most minimal cases, using the Session in “autocommit”
mode is not a good approach to take, and is discouraged in SQLAlchemy’s
own documentation (see
&lt;a class="reference external" href="http://docs.sqlalchemy.org/en/rel_0_9/orm/session.html#autocommit-mode"&gt;http://docs.sqlalchemy.org/en/rel_0_9/orm/session.html#autocommit-mode&lt;/a&gt;),
as it means a series of queries will each proceed upon a brand new connection
and transaction per query, wasting database resources with expensive rollbacks
and even creating a new database connection per query under slight
load, where the connection pool is in overflow mode.  oslo.db
itself also emits a “pessimistic ping” on each connection, where a
“SELECT 1” is emitted in order to ensure the connection is alive, so emitting
three queries in “autocommit” mode means you’re actually emitting &lt;em&gt;six&lt;/em&gt;
queries.&lt;/p&gt;
&lt;p&gt;It’s true that for a method like the above where exactly one SELECT is
emitted and definitely nothing else, there is a little less Python
overhead in that the Session does not build up an internal state
object for the transaction, but this is only a tiny optimization; if
optimization at that scale is needed, there are other ways to make the
above system vastly more performant (e.g. use baked queries, column-
based queries, or Core queries).&lt;/p&gt;
&lt;p&gt;While both Keystone and Neutron have the issue of implicit use of
“autocommit” mode, Nova has more significant issues, both because
it is more complex at the database level and is also more performance
critical regarding persistence.&lt;/p&gt;
&lt;p&gt;Within Nova, the connectivity system is more or less equivalent to
that of Keystone; many explicit calls to get_session() and heavy use of
the session in “autocommit” mode, most commonly through the model_query()
function.   But more critical is that the complexity of Nova’s API without a
foolproof system of maintaining transaction scope leads to
a widespread use of multiple transactions per API call, in some cases
concurrently, which has definite stability and performance implications.&lt;/p&gt;
&lt;p&gt;A typical Nova method looks 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="nd"&gt;@require_admin_context&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;cell_update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cell_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;values&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;session&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;get_session&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;session&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;begin&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="n"&gt;cell_query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_cell_get_by_name_query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cell_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                             &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;cell_query&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;values&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="n"&gt;exception&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CellNotFound&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cell_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;cell_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;cell&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cell_query&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;first&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;cell&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;In the above call, the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;get_session()&lt;/span&gt;&lt;/code&gt; call returns a brand new session
upon which a transaction is begun; the method then calls into
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;_cell_get_by_name_query&lt;/span&gt;&lt;/code&gt;, passing in the Session in an effort to
ensure this sub-method uses the same transaction.   The intent here is
good, that the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;cell_update()&lt;/span&gt;&lt;/code&gt; method knows it should share its
transactional context with a sub-method.&lt;/p&gt;
&lt;p&gt;However, this is a burdensome and verbose coding pattern which is
inconsistently applied.   In those areas where it fails to be applied,
the end result is that a single operation invokes several new
connections and transactions, sometimes within a nested set of calls;
this is wasteful and slow and is a key risk factor for deadlocks.
Examples of non-nested, multiple connection/session use within a
single call are easy to find.   Truly nested transactions are less
frequent; one is nova/db/api.py -&amp;gt; floating_ip_bulk_destroy. In this
method, we see:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="nd"&gt;@require_context&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;floating_ip_bulk_destroy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ips&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;session&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;get_session&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;session&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;begin&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="n"&gt;project_id_to_quota_count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;collections&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;defaultdict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;ip_block&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;_ip_range_splitter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ips&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="n"&gt;query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;model_query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FloatingIp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;\
                &lt;span class="nb"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FloatingIp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;in_&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ip_block&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;\
                &lt;span class="n"&gt;filter_by&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;auto_assigned&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;rows&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;all&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;row&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;project_id_to_quota_count&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'project_id'&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
            &lt;span class="n"&gt;model_query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FloatingIp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;\
                &lt;span class="nb"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FloatingIp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;in_&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ip_block&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;\
                &lt;span class="n"&gt;soft_delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;synchronize_session&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'fetch'&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;project_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;project_id_to_quota_count&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;iteritems&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
            &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;reservations&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;quota&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;QUOTAS&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reserve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                                    &lt;span class="n"&gt;project_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;project_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                                    &lt;span class="n"&gt;floating_ips&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="n"&gt;quota&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;QUOTAS&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;commit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                    &lt;span class="n"&gt;reservations&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                    &lt;span class="n"&gt;project_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;project_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="ne"&gt;Exception&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;excutils&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;save_and_reraise_exception&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
                    &lt;span class="n"&gt;LOG&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exception&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="s2"&gt;"Failed to update usages bulk "&lt;/span&gt;
                                    &lt;span class="s2"&gt;"deallocating floating IP"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The entire method is within &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;session.begin()&lt;/span&gt;&lt;/code&gt;.  But within that, we
first see a two calls to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;model_query()&lt;/span&gt;&lt;/code&gt;, each of which forget to pass the
session along, so &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;model_query()&lt;/span&gt;&lt;/code&gt; makes it’s own session and transaction
for each.   But more seriously, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;get_session()&lt;/span&gt;&lt;/code&gt; is called many times again, without
any way of passing a session through, down below when &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;quota.QUOTAS.commit&lt;/span&gt;&lt;/code&gt;
is called within a loop.  The interface for this starts outside of the
database API, in nova/quota.py, where no &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;session&lt;/span&gt;&lt;/code&gt; argument is available:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;commit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;reservations&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;project_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="sd"&gt;"""Commit reservations."""&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;project_id&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;project_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;project_id&lt;/span&gt;
    &lt;span class="c1"&gt;# If user_id is None, then we use the user_id in context&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;user_id&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;user_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;user_id&lt;/span&gt;

    &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reservation_commit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;reservations&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;project_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;project_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                          &lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;db.reservation_commit&lt;/span&gt;&lt;/code&gt; is back in nova/db/api.py, where we
see a whole new call to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;get_session()&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;begin()&lt;/span&gt;&lt;/code&gt;, calling a second
time through the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;@_retry_on_deadlock&lt;/span&gt;&lt;/code&gt; decorator which also would best
know how to manage its scope at the topmost-level:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="nd"&gt;@require_context&lt;/span&gt;
&lt;span class="nd"&gt;@_retry_on_deadlock&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;reservation_commit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;reservations&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;project_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;session&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;get_session&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;session&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;begin&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="n"&gt;_project_usages&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user_usages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_get_project_user_quota_usages&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;project_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;reservation_query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_quota_reservations_query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                                      &lt;span class="n"&gt;reservations&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;reservation&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;reservation_query&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;all&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
            &lt;span class="n"&gt;usage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;user_usages&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;reservation&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;resource&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;reservation&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;delta&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;usage&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reserved&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="n"&gt;reservation&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;delta&lt;/span&gt;
            &lt;span class="n"&gt;usage&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;in_use&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;reservation&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;delta&lt;/span&gt;
        &lt;span class="n"&gt;reservation_query&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;soft_delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;synchronize_session&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;In the above example, we first see that the “ad-hoc-session” system and
“more than one way to do it” approach of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;model_query()&lt;/span&gt;&lt;/code&gt; leads
to coding errors that are silently masked, but in the case of
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;reservation_commit()&lt;/span&gt;&lt;/code&gt;, the architecture itself disallows this coding
error to even be corrected.&lt;/p&gt;
&lt;p&gt;Examples of non-nested multiple sessions and transactions in one API call can
be found by using an assertion within the test suite.    The two main
areas this occurs in the current code are:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;instance_create() calls get_session(),
then ec2_instance_create() -&amp;gt; models.save() -&amp;gt; get_session()&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;aggregate_create() calls get_session(),
then aggregate_get() -&amp;gt; model_query() -&amp;gt; get_session()&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The above examples can be fixed manually, but rather than adding
more boilerplate, decorators, and imperative arguments to solve the problem
as individual cases are identified, the solution should instead be to replace
all imperative database code involving transaction scope with a purely
declarative facade that handles connectivity, transaction scoping and
related features like method retrying in a consistent and context-aware
fashion across all projects.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;The change is to replace the use of get_session(), get_engine(), and
special context managers with a new set of decorators and
context managers, which themselves are invoked from a
simple import that replaces the usual EngineFacade logic.&lt;/p&gt;
&lt;p&gt;The import will essentially allow a single symbol that handles the work
of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;EngineFacade&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CONF&lt;/span&gt;&lt;/code&gt; behind the scenes:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;oslo.db&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;enginefacade&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;sql&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;This symbol will provide two key decorators, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;reader()&lt;/span&gt;&lt;/code&gt; and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;writer()&lt;/span&gt;&lt;/code&gt;, as well as context managers which
mirror their behavior, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;using_reader()&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;using_writer()&lt;/span&gt;&lt;/code&gt;.
The decorators deliver a SQLAlchemy Session object to
the existing &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;context&lt;/span&gt;&lt;/code&gt; argument of API methods:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="nd"&gt;@sql&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reader&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;some_api_method&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# work with context.session&lt;/span&gt;

&lt;span class="nd"&gt;@sql&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;writer&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;some_other_api_method&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# work with context.session&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Whereas the context managers receive this &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;context&lt;/span&gt;&lt;/code&gt; argument locally:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;some_api_method&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;sql&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;using_reader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# work with session&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;some_other_api_method&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;sql&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;using_writer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# work with session&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;section id="transaction-scope"&gt;
&lt;h3&gt;Transaction Scope&lt;/h3&gt;
&lt;p&gt;These decorators and context managers will acquire a new Session using
methods similar to that of the current &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;get_session()&lt;/span&gt;&lt;/code&gt; function if
one is not already scoped, or if one is already scoped, will return
that existing Session.   The Session will then unconditionally be
within a transaction using &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;begin()&lt;/span&gt;&lt;/code&gt;, or we may better yet switch to
the default mode of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Session&lt;/span&gt;&lt;/code&gt; which is that of “autocommit=False”.
The state of this transaction will be to remain open until the method
ends, either by raising an exception (unconditional rollback) or by
completing (either a commit() or a close(), depending on reader/writer
semantics).&lt;/p&gt;
&lt;p&gt;The goal is that any level of nested calls can all call upon
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;reader()&lt;/span&gt;&lt;/code&gt; or &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;writer()&lt;/span&gt;&lt;/code&gt; and participate in an already ongoing
transaction.  Only the outermost call within the scope actually ends
the transaction except in the case of an exception; the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;writer()&lt;/span&gt;&lt;/code&gt;
method will  emit a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;commit()&lt;/span&gt;&lt;/code&gt; and the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;reader()&lt;/span&gt;&lt;/code&gt; method will
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;close()&lt;/span&gt;&lt;/code&gt; the session, ensuring that the underlying connection is
rolled back in a lightweight way.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="context-and-thread-locals"&gt;
&lt;h3&gt;Context and Thread Locals&lt;/h3&gt;
&lt;p&gt;The proposal at the moment expects a “context” object, which can be
any Python object, to be present in order to provide some object that
bridges all elements of a call stack together.   Most APIs with the notable
exception of Keystone appear to already include a context argument.&lt;/p&gt;
&lt;p&gt;To support a pattern that does not include a “context” argument, the only
alternative is to use thread locals.  In discussions with the community,
the use of thread locals has the two concerns of: 1. it requires early patching
at the eventlet level and 2. thread locals are seen as “action at a distance”,
more “implicit” than “explicit”.&lt;/p&gt;
&lt;p&gt;The proposal as stated here can be made to work with thread locals using
this recipe:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="c1"&gt;# at the top of the api module&lt;/span&gt;
&lt;span class="n"&gt;GLOBAL_CONTEXT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;threading&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;local&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;some_api_method&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;sql&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;using_writer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;GLOBAL_CONTEXT&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;session&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# work with session&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Whether or not we build in the above pattern, or we get Keystone to use
an explicit context object, is not yet decided.  See “Alternatives” for
a listing of various options.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="reader-vs-writer"&gt;
&lt;h3&gt;Reader vs. Writer&lt;/h3&gt;
&lt;p&gt;At the outset, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;reader()&lt;/span&gt;&lt;/code&gt; vs. &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;writer()&lt;/span&gt;&lt;/code&gt; only intend to allow a block
of functionality to mark itself as only requiring read-only access, or
involving write access.   At the very least, it can indicate if the outermost
block need to be concerned about committing a transaction.   Beyond that,
this declaration can be used to determine if a particular method or block
is suitable for “retry on deadlock”, and also allows systems that attempt
to split logic between “reader” and “writer” database links to know upfront
which blocks should be routed where.&lt;/p&gt;
&lt;p&gt;While a fully specified description for open-ended support of multiple
databases is out of scope for this spec, as part of the
implementation here we will necessarily implement at least what is already
present.  The existing EngineFacade features a “slave_engine” attribute
as well as a “use_slave” flag on &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;get_session()&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;get_engine()&lt;/span&gt;&lt;/code&gt;;
at least the Nova project and possibly others currently make use of this
flag.  So we will carry over an equivalent level of functionality into
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;reader()&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;writer()&lt;/span&gt;&lt;/code&gt; to start.&lt;/p&gt;
&lt;p&gt;Beyond maintaining existing functionality, more comprehensive and
potentially elaborate systems of multiple database support will be
made easier to specify and implement subsequent to the rollout
of this specification.  This is because consuming projects will greatly reduce
their verbosity down to a simple declarative level, leaving oslo.db
free to expand upon the underlying machinery without incurring additional
across-the-board changes in projects (hence one of the main reasons “facades”
are used).&lt;/p&gt;
&lt;p&gt;The behavior for nesting of readers and writers is as follows:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;A &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;reader()&lt;/span&gt;&lt;/code&gt; block that ultimately calls upon methods that then invoke
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;writer()&lt;/span&gt;&lt;/code&gt; should raise an exception; it means this &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;reader()&lt;/span&gt;&lt;/code&gt; is not
really a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;reader()&lt;/span&gt;&lt;/code&gt; at all.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;writer()&lt;/span&gt;&lt;/code&gt; block that ultimately
calls upon methods that invoke &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;reader()&lt;/span&gt;&lt;/code&gt; should pass successfully;
those &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;reader()&lt;/span&gt;&lt;/code&gt; blocks will in fact be made to act as a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;writer()&lt;/span&gt;&lt;/code&gt;
if they are called within the context of a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;writer()&lt;/span&gt;&lt;/code&gt; block.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
&lt;section id="core-connection-methods"&gt;
&lt;h3&gt;Core Connection Methods&lt;/h3&gt;
&lt;p&gt;For those methods that use Core only, corresponding methods
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;reader_connection()&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;writer_connection()&lt;/span&gt;&lt;/code&gt; are supplied,
which instead of returning a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;sqlalchemy.orm.Session&lt;/span&gt;&lt;/code&gt;, return a
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;sqlalchemy.engine.Connection&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="nd"&gt;@sql&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;writer_connection&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;some_core_api_method&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;connection&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;execute&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;statement&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;some_core_api_method&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;sql&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;using_writer_connection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&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;execute&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;statement&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;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;reader_connection()&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;writer_connection()&lt;/span&gt;&lt;/code&gt; will integrate with
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;reader()&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;writer()&lt;/span&gt;&lt;/code&gt;, such that the outermost context will establish
the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;sqlalchemy.engine.Connection&lt;/span&gt;&lt;/code&gt; that is to be used for the full
context, whether or not it is associated with a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Session&lt;/span&gt;&lt;/code&gt;.  This means
the following:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;If a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;reader_connection()&lt;/span&gt;&lt;/code&gt; or &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;writer_connection()&lt;/span&gt;&lt;/code&gt; manager is invoked
first, a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;sqlalchemy.engine.Connection&lt;/span&gt;&lt;/code&gt;
is associated with the context, and not a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Session&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;reader()&lt;/span&gt;&lt;/code&gt; or &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;writer()&lt;/span&gt;&lt;/code&gt; manager is invoked first, a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Session&lt;/span&gt;&lt;/code&gt;
is associated with the context, which will contain within it a
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;sqlalchemy.engine.Connection&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;reader_connection()&lt;/span&gt;&lt;/code&gt; or &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;writer_connection()&lt;/span&gt;&lt;/code&gt; manager is invoked
and there is already a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Session&lt;/span&gt;&lt;/code&gt; present, the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Session.connection()&lt;/span&gt;&lt;/code&gt;
method of that &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Session&lt;/span&gt;&lt;/code&gt; is used to get at the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Connection&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;reader()&lt;/span&gt;&lt;/code&gt; or &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;writer()&lt;/span&gt;&lt;/code&gt; manager is invoked and there is already
a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Connection&lt;/span&gt;&lt;/code&gt; present, the new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Session&lt;/span&gt;&lt;/code&gt; is created, and it is
bound directly to this existing &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Connection&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
&lt;section id="integration-with-configuration-startup"&gt;
&lt;h3&gt;Integration with Configuration / Startup&lt;/h3&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;reader()&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;writer()&lt;/span&gt;&lt;/code&gt; and other methods will be calling upon
functional equivalents of the current &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;get_session()&lt;/span&gt;&lt;/code&gt; and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;get_engine()&lt;/span&gt;&lt;/code&gt; methods within oslo.db, as well as handling the logic
that currently consists of invoking an &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;EngineFacade&lt;/span&gt;&lt;/code&gt; and combining
it with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CONF&lt;/span&gt;&lt;/code&gt;.  That is, the consuming application does not refer
to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;EngineFacade&lt;/span&gt;&lt;/code&gt; or &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CONF&lt;/span&gt;&lt;/code&gt; at all; the interaction with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CONF&lt;/span&gt;&lt;/code&gt;
is performed similarly as it is now within oslo.db only, and is done
under a mutex so that it is thread safe, in the way that Nova performs
this task.&lt;/p&gt;
&lt;p&gt;For applications that currently have special logic to add keys to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;CONF&lt;/span&gt;&lt;/code&gt;
or &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;EngineFacade&lt;/span&gt;&lt;/code&gt;, additional API methods will be provided.  For example,
Sahara wants to ensure the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;sqlite_fk&lt;/span&gt;&lt;/code&gt; flag is set to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;True&lt;/span&gt;&lt;/code&gt;.  The
pattern will look like:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;oslo.db&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;enginefacade&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;sql&lt;/span&gt;

&lt;span class="n"&gt;sql&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;configure&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sqlite_fk&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="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;some_api_method&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;sql&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reader&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;session&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# work with session&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="retry-on-deadlock-other-failures"&gt;
&lt;h3&gt;Retry on Deadlock / Other failures&lt;/h3&gt;
&lt;p&gt;Oslo.db provides the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;@wrap_db_retry()&lt;/span&gt;&lt;/code&gt; decorator, which allows an API
method to replay itself on failure.  Per
&lt;a class="reference external" href="https://review.openstack.org/#/c/109549/"&gt;https://review.openstack.org/#/c/109549/&lt;/a&gt;, we will be adding specificity
to this decorator, which allows it to explicitly indicate that a method
should be retried when a deadlock condition occurs.   We can look into
integrating this feature into the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;reader()&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;writer()&lt;/span&gt;&lt;/code&gt; decorators
as well.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;A key decision here is that of the decorator vs. the context manager,
as well as the use of thread locals.&lt;/p&gt;
&lt;p&gt;Example forms:&lt;/p&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;&lt;p&gt;Decorator, using context:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="nd"&gt;@sql&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reader&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;some_api_method&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# work with context.session&lt;/span&gt;

&lt;span class="nd"&gt;@sql&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;writer&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;some_other_api_method&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# work with context.session&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Decorator, using thread local; here, the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;session&lt;/span&gt;&lt;/code&gt; argument is injected
into the argument list of the API method within the scope of the decorator,
it is &lt;em&gt;not&lt;/em&gt; present in the outer call to the API method:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="nd"&gt;@sql&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reader&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;some_api_method&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# work with session&lt;/span&gt;

&lt;span class="nd"&gt;@sql&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;writer&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;some_other_api_method&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# work with session&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Context manager, using context:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;some_api_method&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;sql&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;using_reader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# work with session&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;some_other_api_method&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;sql&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;using_writer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# work with session&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Context manager, using implicit thread local:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;some_api_method&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;sql&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;using_reader&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;session&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# work with session&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;some_other_api_method&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;sql&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;using_writer&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;session&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# work with session&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Context manager, using explicit thread local:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;some_api_method&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;sql&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;using_reader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;GLOBAL_CONTEXT&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;session&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# work with session&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;some_other_api_method&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;sql&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;using_writer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;GLOBAL_CONTEXT&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;session&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# work with session&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The author favors approach #1.   It should be noted that &lt;em&gt;all&lt;/em&gt; the above
approaches can be supported at the same time, if projects cannot agree
on an approach.&lt;/p&gt;
&lt;p&gt;Advantages to using a decorator only with an explicit context are:&lt;/p&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;&lt;p&gt;The need for thread locals or any issues with eventlet is removed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The “Retry on deadlock” and other “retry” features could be
integrated into the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;reader()&lt;/span&gt;&lt;/code&gt; / &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;writer()&lt;/span&gt;&lt;/code&gt; decorators, such that
all API methods automatically gain this feature.   As it stands,
applications need to constantly push out new changes each time an
unavoidable deadlock situation is detected in the wild, adding their
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;@_retry_on_deadlock()&lt;/span&gt;&lt;/code&gt; decorators to ever more API methods.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The decorator reduces nesting depth compared to context managers, and
is ultimately less verbose, save for the need to have a “context”
argument.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Decorators eliminate the possibility of this already-present
antipattern:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;some_api_method&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;sql&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;writer&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;session&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# do something with session&lt;/span&gt;

    &lt;span class="c1"&gt;# transaction completes here&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;element&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;stuff&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# new transaction per element&lt;/span&gt;
        &lt;span class="n"&gt;some_other_api_method_with_db&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;element&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Above, we are inadvertently performing any number of distinct
transactions, first with the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;sql.writer()&lt;/span&gt;&lt;/code&gt;, then with each call to
some_other_api_method_with_db().  This antipattern can already be seen
in methods like Nova’s &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;instance_create()&lt;/span&gt;&lt;/code&gt; method, paraphrased
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="nd"&gt;@require_context&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;instance_create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;values&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;

    &lt;span class="c1"&gt;# ...  about halfway through&lt;/span&gt;

    &lt;span class="n"&gt;session&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;get_session&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="c1"&gt;# session / connection / transaction #1&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;begin&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="c1"&gt;# does some things with instnace_ref&lt;/span&gt;

    &lt;span class="c1"&gt;# session / connection / transaction #2&lt;/span&gt;
    &lt;span class="n"&gt;ec2_instance_create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;instance_ref&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'uuid'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

    &lt;span class="c1"&gt;# session / connection / transaction #3&lt;/span&gt;
    &lt;span class="n"&gt;_instance_extra_create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;'instance_uuid'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;instance_ref&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'uuid'&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;instance_ref&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Because the context manager allows unnecessary choices about when a
transaction can begin and end within a method, we open ourselves up to make
the wrong choice, as is already occurring in current code.  Using a decorator,
this antipattern is impossible:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="nd"&gt;@sql&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;writer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;some_api_method&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# do something with context.session&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;element&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;stuff&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# uses same session / transaction guaranteed&lt;/span&gt;
        &lt;span class="n"&gt;some_other_api_method_with_db&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;element&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# transaction completes here&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;One advantage to using an implicit “thread local” context is that it is impossible
to inadvertently switch contexts in the middle of a call-chain, which would
again lead to the nested-transaction issue.&lt;/p&gt;
&lt;p&gt;An advantage of using context managers with implicit threadlocals is that
it would be easier for Keystone to migrate to this system.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="impact-on-existing-apis"&gt;
&lt;h3&gt;Impact on Existing APIs&lt;/h3&gt;
&lt;p&gt;Existing projects would need to integrate into some form of the
patterns given.&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="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;Performance will be dramatically improved as the current use of many
redundant and disconnected sessions and transactions will be joined together.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="configuration-impact"&gt;
&lt;h3&gt;Configuration Impact&lt;/h3&gt;
&lt;p&gt;none.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer Impact&lt;/h3&gt;
&lt;p&gt;new patterns for developers to be aware of.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing-impact"&gt;
&lt;h3&gt;Testing Impact&lt;/h3&gt;
&lt;p&gt;As most test suites currently make the simple decision of working with
SQLite and allowing API methods to make use of their usual get_session() /
get_engine() logic without any change or injection, little to no changes
should be needed at first.   Within oslo.db, the “opportunistic” fixtures
as well as the DbTestCase system will be made to integrate with the
new context manager/decorator system.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="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;Mike Bayer&lt;/p&gt;
&lt;/section&gt;
&lt;section id="milestones"&gt;
&lt;h3&gt;Milestones&lt;/h3&gt;
&lt;p&gt;Target Milestone for completion:&lt;/p&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="incubation"&gt;
&lt;h2&gt;Incubation&lt;/h2&gt;
&lt;section id="adoption"&gt;
&lt;h3&gt;Adoption&lt;/h3&gt;
&lt;/section&gt;
&lt;section id="library"&gt;
&lt;h3&gt;Library&lt;/h3&gt;
&lt;/section&gt;
&lt;section id="anticipated-api-stabilization"&gt;
&lt;h3&gt;Anticipated API Stabilization&lt;/h3&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This work is licensed under a Creative Commons Attribution 3.0
Unported License.
&lt;a class="reference external" href="http://creativecommons.org/licenses/by/3.0/legalcode"&gt;http://creativecommons.org/licenses/by/3.0/legalcode&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
</description><pubDate>Tue, 30 Sep 2014 00:00:00 </pubDate></item><item><title>Fix the Import Cycle Between log and versionutils</title><link>https://specs.openstack.org/openstack/oslo-specs/specs/kilo/fix-import-cycle-log-and-versionutils.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/oslo-incubator/+spec/fix-import-cycle-log-and-versionutils"&gt;https://blueprints.launchpad.net/oslo-incubator/+spec/fix-import-cycle-log-and-versionutils&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Break the import cycle so we can release oslo.log.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;There is a circular dependency between versionutils and the logging
code, which are slated to be released in separate libraries. We need
to break the cycle to allow oslo.log to graduate this cycle.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;section id="oslo-incubator"&gt;
&lt;h3&gt;oslo-incubator&lt;/h3&gt;
&lt;p&gt;Move the &lt;code class="xref py py-meth docutils literal notranslate"&gt;&lt;span class="pre"&gt;ContextAdapter.deprecated()&lt;/span&gt;&lt;/code&gt; method to a function in
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;versionutils&lt;/span&gt;&lt;/code&gt; with the other deprecation-related code. That means
moving the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;fatal_deprecations&lt;/span&gt;&lt;/code&gt; configuration option, and updating
all callers.&lt;/p&gt;
&lt;p&gt;The proposed function signature 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="c1"&gt;# versionutils.py&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;report_deprecated_feature&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;msg&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;kwds&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="sd"&gt;"""Call this function when a deprecated feature is used.&lt;/span&gt;

&lt;span class="sd"&gt;     If the system is configured for fatal deprecations then the message&lt;/span&gt;
&lt;span class="sd"&gt;     is logged at the 'critical' level and :class:`DeprecatedConfig` will&lt;/span&gt;
&lt;span class="sd"&gt;     be raised.&lt;/span&gt;

&lt;span class="sd"&gt;     Otherwise, the message will be logged (once) at the 'warn' level.&lt;/span&gt;

&lt;span class="sd"&gt;     :param logger: The Python logger to use to generate the message.&lt;/span&gt;
&lt;span class="sd"&gt;     :type logger: logging.Logger&lt;/span&gt;
&lt;span class="sd"&gt;     :param msg: The message to emit.&lt;/span&gt;
&lt;span class="sd"&gt;     :type msg: unicode&lt;/span&gt;
&lt;span class="sd"&gt;     :raises: :class:`DeprecatedConfig` if the system is configured for&lt;/span&gt;
&lt;span class="sd"&gt;              fatal deprecations.&lt;/span&gt;

&lt;span class="sd"&gt;     """&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;To maintain the current logging behavior,
&lt;code class="xref py py-func docutils literal notranslate"&gt;&lt;span class="pre"&gt;report_deprecated_feature()&lt;/span&gt;&lt;/code&gt; will take a logger as argument and
use it to emit the message (instead of having a single logger with the
name of the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;versionutils&lt;/span&gt;&lt;/code&gt; module).&lt;/p&gt;
&lt;p&gt;Move &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;fatal_deprecations&lt;/span&gt;&lt;/code&gt; out of the default option group to the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;deprecation&lt;/span&gt;&lt;/code&gt; group, with appropriate deprecation settings to honor
the old name if it is found.&lt;/p&gt;
&lt;p&gt;Update &lt;code class="xref py py-func docutils literal notranslate"&gt;&lt;span class="pre"&gt;versionutils.deprecated()&lt;/span&gt;&lt;/code&gt; to call
&lt;code class="xref py py-func docutils literal notranslate"&gt;&lt;span class="pre"&gt;report_deprecated_feature()&lt;/span&gt;&lt;/code&gt; instead of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LOG.deprecated()&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="oslo-log"&gt;
&lt;h3&gt;oslo.log&lt;/h3&gt;
&lt;p&gt;Remove all of the deprecation-related code from oslo.log entirely. It
will stay in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;versionutils&lt;/span&gt;&lt;/code&gt;, either in the incubator or in a new
library to be discussed in another blueprint.&lt;/p&gt;
&lt;/section&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;Change the implementation of the deprecated() decorator in
versionutils to not call LOG.deprecated(). That might mean
duplicating the logic from LOG.deprecated().&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Move most of the body of LOG.deprecated() to versionutils but
keep the method. This limits the number of changes we have to make
in the callers, but means that oslo.log depends on
oslo.versionutils. We can eliminate the circular dependency by
having the function in versionutils use python’s standard logger
instead of oslo.log.  This seems to be in keeping with the API
changes for oslo.log above.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Both alternative solutions fix the cycle, but require that we keep
LOG.deprecated() and our special ContextAdapter. We are trying to
remove that class in another blueprint related to graduating oslo.log.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="impact-on-existing-apis"&gt;
&lt;h3&gt;Impact on Existing APIs&lt;/h3&gt;
&lt;p&gt;Callers of LOG.deprecated() will need to be updated to use
&lt;code class="xref py py-func docutils literal notranslate"&gt;&lt;span class="pre"&gt;versionutils.report_deprecated_feature()&lt;/span&gt;&lt;/code&gt; instead.&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="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="configuration-impact"&gt;
&lt;h3&gt;Configuration Impact&lt;/h3&gt;
&lt;p&gt;Move &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;fatal_deprecations&lt;/span&gt;&lt;/code&gt; out of the default option group to the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;versionutils&lt;/span&gt;&lt;/code&gt; group.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer Impact&lt;/h3&gt;
&lt;p&gt;The API for reporting deprecated code and features will be moving to a
new place, so we will need to publicize the change. The apps can be
updated when syncing changes to the logging and versionutils code from
the incubator.&lt;/p&gt;
&lt;p&gt;Most callers use the &lt;code class="xref py py-func docutils literal notranslate"&gt;&lt;span class="pre"&gt;deprecated()&lt;/span&gt;&lt;/code&gt; decorator instead anyway.&lt;/p&gt;
&lt;p&gt;Calls to update:&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;oslo&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;incubator&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;tests&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;unit&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;test_deprecated&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;py&lt;/span&gt;
&lt;span class="mi"&gt;38&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_deprecated&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="mi"&gt;39&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;        &lt;span class="n"&gt;LOG&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;deprecated&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'test'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mi"&gt;54&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;        &lt;span class="n"&gt;LOG&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;deprecated&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'only once!'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mi"&gt;55&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;        &lt;span class="n"&gt;LOG&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;deprecated&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'only once!'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mi"&gt;56&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;        &lt;span class="n"&gt;LOG&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;deprecated&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'only once!'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mi"&gt;65&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;        &lt;span class="n"&gt;LOG&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;deprecated&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mi"&gt;66&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;        &lt;span class="n"&gt;LOG&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;deprecated&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mi"&gt;67&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;        &lt;span class="n"&gt;LOG&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;deprecated&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mi"&gt;68&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;        &lt;span class="n"&gt;LOG&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;deprecated&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mi"&gt;69&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;        &lt;span class="n"&gt;LOG&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;deprecated&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mi"&gt;70&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;        &lt;span class="n"&gt;LOG&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;deprecated&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mi"&gt;83&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;        &lt;span class="n"&gt;LOG&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;deprecated&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'only once! &lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'arg1'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mi"&gt;84&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;        &lt;span class="n"&gt;LOG&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;deprecated&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'only once! &lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'arg1'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mi"&gt;85&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;        &lt;span class="n"&gt;LOG&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;deprecated&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'only once! &lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'arg2'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mi"&gt;86&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;        &lt;span class="n"&gt;LOG&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;deprecated&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'only once! &lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'arg2'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mi"&gt;108&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;        &lt;span class="n"&gt;LOG&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;deprecated&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg_fmt_1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;msg_fmt_1_arg_1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mi"&gt;109&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;        &lt;span class="n"&gt;LOG&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;deprecated&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg_fmt_1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;msg_fmt_1_arg_2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# logged: args different&lt;/span&gt;
&lt;span class="mi"&gt;110&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;        &lt;span class="n"&gt;LOG&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;deprecated&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg_fmt_1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;msg_fmt_1_arg_1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# no log: same msg+args&lt;/span&gt;
&lt;span class="mi"&gt;112&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;        &lt;span class="n"&gt;LOG&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;deprecated&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg_fmt_2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;msg_fmt_2_arg_1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mi"&gt;113&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;        &lt;span class="n"&gt;LOG&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;deprecated&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg_fmt_2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;msg_fmt_2_arg_2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# logged: args different&lt;/span&gt;
&lt;span class="mi"&gt;114&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;        &lt;span class="n"&gt;LOG&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;deprecated&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg_fmt_2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;msg_fmt_2_arg_3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# logged: args different&lt;/span&gt;
&lt;span class="mi"&gt;115&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;        &lt;span class="n"&gt;LOG&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;deprecated&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg_fmt_2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;msg_fmt_2_arg_3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# no log: same msg+args&lt;/span&gt;
&lt;span class="mi"&gt;116&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;        &lt;span class="n"&gt;LOG&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;deprecated&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg_fmt_2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;msg_fmt_2_arg_2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# no log: same msg+args&lt;/span&gt;

&lt;span class="n"&gt;cinder&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;cinder&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;contrib&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;services&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;py&lt;/span&gt;
&lt;span class="mi"&gt;91&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;            &lt;span class="n"&gt;LOG&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;deprecated&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="s2"&gt;"Query by service parameter is deprecated. "&lt;/span&gt;

&lt;span class="n"&gt;cinder&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;cinder&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;quota&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;py&lt;/span&gt;
&lt;span class="mi"&gt;106&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;                &lt;span class="n"&gt;LOG&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;deprecated&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="s2"&gt;"Default quota for resource: &lt;/span&gt;&lt;span class="si"&gt;%(res)s&lt;/span&gt;&lt;span class="s2"&gt; is set "&lt;/span&gt;

&lt;span class="n"&gt;cinder&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;cinder&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;scheduler&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;manager&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;py&lt;/span&gt;
&lt;span class="mi"&gt;66&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;            &lt;span class="n"&gt;LOG&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;deprecated&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;'ChanceScheduler and SimpleScheduler have been '&lt;/span&gt;

&lt;span class="n"&gt;neutron&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;neutron&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;plugins&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;vmware&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;nsx_cluster&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;py&lt;/span&gt;
&lt;span class="mi"&gt;49&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;            &lt;span class="n"&gt;LOG&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;deprecated&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="s2"&gt;"Attribute '&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s2"&gt;' has been deprecated or moved "&lt;/span&gt;

&lt;span class="n"&gt;neutron&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;neutron&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;agent&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;common&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;py&lt;/span&gt;
&lt;span class="mi"&gt;104&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;        &lt;span class="n"&gt;LOG&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;deprecated&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;'DEFAULT.root_helper is deprecated! Please move '&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;glance&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;store&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="fm"&gt;__init__&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;py&lt;/span&gt;
&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;                &lt;span class="n"&gt;LOG&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;deprecated&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="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s2"&gt; not found in `known_store`. "&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Searching for uses:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;$ ack --ignore-dir=.tox --ignore-dir=build --ignore-dir=.venv \
--ignore-dir=.update-venv --ignore-dir=openstack 'deprecated\('

python-keystoneclient/keystoneclient/tests/test_discovery.py
673:    def test_allow_deprecated(self):

python-keystoneclient/keystoneclient/tests/test_http.py
136:    def test_client_deprecated(self):

keystone/keystone/catalog/backends/templated.py
128:@versionutils.deprecated(

keystone/keystone/contrib/stats/core.py
130:    @versionutils.deprecated(

keystone/keystone/contrib/access/core.py
35:    @versionutils.deprecated(

keystone/keystone/middleware/s3_token.py
50:    @versionutils.deprecated(

keystone/keystone/middleware/core.py
148:    @versionutils.deprecated(

keystone/keystone/auth/plugins/external.py
102:    @versionutils.deprecated(
113:    @versionutils.deprecated(
130:    @versionutils.deprecated(
151:    @versionutils.deprecated(

keystone/keystone/token/core.py
263:    @versionutils.deprecated(versionutils.deprecated.ICEHOUSE, remove_in=+1)

keystone/keystone/common/controller.py
33:def v2_deprecated(f):
42:        v2_deprecated = versionutils.deprecated(

keystone/keystone/common/kvs/legacy.py
49:    @versionutils.deprecated(versionutils.deprecated.ICEHOUSE,

keystone/vendor/python-keystoneclient-master/keystoneclient/tests/test_http.py
136:    def test_client_deprecated(self):

oslo-incubator/tests/unit/test_versionutils.py
24:    def assert_deprecated(self, mock_log, **expected_details):
35:        @versionutils.deprecated(as_of=versionutils.deprecated.ICEHOUSE)
48:            @versionutils.deprecated(as_of=versionutils.deprecated.ICEHOUSE)
59:        @versionutils.deprecated(as_of=versionutils.deprecated.ICEHOUSE,
66:        self.assert_deprecated(mock_log,
75:        @versionutils.deprecated(as_of=versionutils.deprecated.GRIZZLY,
82:        self.assert_deprecated(mock_log,
91:        @versionutils.deprecated(as_of=versionutils.deprecated.GRIZZLY)
97:        self.assert_deprecated(mock_log,
105:        @versionutils.deprecated(as_of=versionutils.deprecated.GRIZZLY,
113:        self.assert_deprecated(mock_log,
122:        @versionutils.deprecated(as_of=versionutils.deprecated.GRIZZLY,
129:        self.assert_deprecated(mock_log,
137:        @versionutils.deprecated(as_of=versionutils.deprecated.GRIZZLY,
144:        self.assert_deprecated(mock_log,

oslo-incubator/tests/unit/test_log.py
600:    def test_logfile_deprecated(self):
610:    def test_logdir_deprecated(self):

oslo-incubator/tests/unit/test_deprecated.py
38:    def test_deprecated(self):
39:        LOG.deprecated('test')
54:        LOG.deprecated('only once!')
55:        LOG.deprecated('only once!')
56:        LOG.deprecated('only once!')
65:        LOG.deprecated(msg1)
66:        LOG.deprecated(msg2)
67:        LOG.deprecated(msg1)
68:        LOG.deprecated(msg1)
69:        LOG.deprecated(msg2)
70:        LOG.deprecated(msg2)
83:        LOG.deprecated('only once! %s', 'arg1')
84:        LOG.deprecated('only once! %s', 'arg1')
85:        LOG.deprecated('only once! %s', 'arg2')
86:        LOG.deprecated('only once! %s', 'arg2')
108:        LOG.deprecated(msg_fmt_1, msg_fmt_1_arg_1)
109:        LOG.deprecated(msg_fmt_1, msg_fmt_1_arg_2)  # logged: args different
110:        LOG.deprecated(msg_fmt_1, msg_fmt_1_arg_1)  # no log: same msg+args
112:        LOG.deprecated(msg_fmt_2, msg_fmt_2_arg_1)
113:        LOG.deprecated(msg_fmt_2, *msg_fmt_2_arg_2)  # logged: args different
114:        LOG.deprecated(msg_fmt_2, *msg_fmt_2_arg_3)  # logged: args different
115:        LOG.deprecated(msg_fmt_2, *msg_fmt_2_arg_3)  # no log: same msg+args
116:        LOG.deprecated(msg_fmt_2, *msg_fmt_2_arg_2)  # no log: same msg+args

cinder/cinder/api/contrib/services.py
91:            LOG.deprecated(_("Query by service parameter is deprecated. "

cinder/cinder/quota.py
106:                LOG.deprecated(_("Default quota for resource: %(res)s is set "

cinder/cinder/scheduler/manager.py
66:            LOG.deprecated(_('ChanceScheduler and SimpleScheduler have been '

oslo.config/tests/test_cfg.py
654:    def test_conf_file_str_value_override_use_deprecated(self):
1086:    def test_conf_file_dict_values_override_deprecated(self):
1106:    def test_conf_file_dict_deprecated(self):
1232:    def test_conf_file_multistr_values_append_deprecated(self):
1271:    def test_conf_file_multistr_deprecated(self):

neutron/neutron/plugins/vmware/nsx_cluster.py
49:            LOG.deprecated(_("Attribute '%s' has been deprecated or moved "

neutron/neutron/agent/common/config.py
104:        LOG.deprecated(_('DEFAULT.root_helper is deprecated! Please move '

heat/heat/tests/test_neutron_loadbalancer.py
429:    def test_create_deprecated(self):

heat/heat/tests/test_neutron_vpnservice.py
201:    def test_create_deprecated(self):

heat/heat/tests/test_parser.py
759:    def test_stack_resolve_runtime_data_deprecated(self):

heat/heat/tests/test_engine_service.py
1950:    def test_list_resource_types_deprecated(self):

heat/heat/tests/test_neutron.py
914:    def test_subnet_deprecated(self):
1387:    def test_router_interface_deprecated(self):
1801:    def test_floating_ip_deprecated(self):

heat/heat/tests/test_neutron_network_gateway.py
233:    def test_network_gateway_create_deprecated(self):

os-refresh-config/os_refresh_config/tests/test_os_refresh_config.py
27:    def test_default_base_dir_deprecated(self):

glance/glance/store/__init__.py
200:                LOG.deprecated(_("%s not found in `known_store`. "

os-apply-config/os_apply_config/tests/test_apply_config.py
293:    def test_default_templates_dir_deprecated(self):
298:    def test_default_templates_dir_old_deprecated(self):
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Doug Hellmann (doug-hellmann)&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="milestones"&gt;
&lt;h3&gt;Milestones&lt;/h3&gt;
&lt;p&gt;Target Milestone for completion: Juno-1&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;Move &lt;code class="xref py py-meth docutils literal notranslate"&gt;&lt;span class="pre"&gt;ContextAdapter.deprecated()&lt;/span&gt;&lt;/code&gt; to
&lt;code class="xref py py-func docutils literal notranslate"&gt;&lt;span class="pre"&gt;log_deprecated_feature()&lt;/span&gt;&lt;/code&gt; and update the implementation.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Move location of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;fatal_deprecations&lt;/span&gt;&lt;/code&gt; option definition and the
group where it is registered.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update Cinder.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update Neutron.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update Glance.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="incubation"&gt;
&lt;h2&gt;Incubation&lt;/h2&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;section id="adoption"&gt;
&lt;h3&gt;Adoption&lt;/h3&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;section id="library"&gt;
&lt;h3&gt;Library&lt;/h3&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;section id="anticipated-api-stabilization"&gt;
&lt;h3&gt;Anticipated API Stabilization&lt;/h3&gt;
&lt;p&gt;This new API should be stable enough that oslo.versionutils can
graduate. That work will be tracked by a separate spec/blueprint.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;The configuration option is moving to a new group, so the sample
config files and config tables generated in the documentation will
need to be updated.&lt;/p&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="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Discussion at Juno summit: &lt;a class="reference external" href="https://etherpad.openstack.org/p/juno-oslo-release-plan"&gt;https://etherpad.openstack.org/p/juno-oslo-release-plan&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This work is licensed under a Creative Commons Attribution 3.0
Unported License.
&lt;a class="reference external" href="http://creativecommons.org/licenses/by/3.0/legalcode"&gt;http://creativecommons.org/licenses/by/3.0/legalcode&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
</description><pubDate>Mon, 29 Sep 2014 00:00:00 </pubDate></item><item><title>Remove ContextAdapter from logging</title><link>https://specs.openstack.org/openstack/oslo-specs/specs/kilo/remove-context-adapter.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/oslo.log/+spec/remove-context-adapter"&gt;https://blueprints.launchpad.net/oslo.log/+spec/remove-context-adapter&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;We want to remove the &lt;code class="xref py py-class docutils literal notranslate"&gt;&lt;span class="pre"&gt;openstack.common.log.ContextAdapter&lt;/span&gt;&lt;/code&gt;
class as part of graduating &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo.log&lt;/span&gt;&lt;/code&gt;, to reduce the API footprint.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;We use &lt;code class="xref py py-class docutils literal notranslate"&gt;&lt;span class="pre"&gt;ContextAdapter&lt;/span&gt;&lt;/code&gt; to add request context information to
log messages we output. Requiring a specially adapted logging handle
limits the scope of where that context information can be added, and
unnecessarily funnels all logging calls through the oslo logging
modules.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Ensure &lt;code class="xref py py-class docutils literal notranslate"&gt;&lt;span class="pre"&gt;ContextHandler&lt;/span&gt;&lt;/code&gt; implements all of the same behaviors
as &lt;code class="xref py py-class docutils literal notranslate"&gt;&lt;span class="pre"&gt;ContextAdapter&lt;/span&gt;&lt;/code&gt;, with respect to the values being
output and their sources.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create &lt;code class="xref py py-class docutils literal notranslate"&gt;&lt;span class="pre"&gt;KeywordArgumentAdapater&lt;/span&gt;&lt;/code&gt; to take named keyword
arguments to logging methods and insert them into the ‘extra’
values for the log record (see below for details).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Change &lt;code class="xref py py-func docutils literal notranslate"&gt;&lt;span class="pre"&gt;getLogger()&lt;/span&gt;&lt;/code&gt; to return &lt;code class="xref py py-class docutils literal notranslate"&gt;&lt;span class="pre"&gt;KeywordArgumentAdapter&lt;/span&gt;&lt;/code&gt;
instances instead of &lt;code class="xref py py-class docutils literal notranslate"&gt;&lt;span class="pre"&gt;ContextAdapter&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Remove the &lt;code class="xref py py-class docutils literal notranslate"&gt;&lt;span class="pre"&gt;ContextAdapter&lt;/span&gt;&lt;/code&gt; class.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Remove the &lt;code class="xref py py-func docutils literal notranslate"&gt;&lt;span class="pre"&gt;getLazyLogger()&lt;/span&gt;&lt;/code&gt; function.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;The previous version of this spec suggested changing &lt;code class="xref py py-func docutils literal notranslate"&gt;&lt;span class="pre"&gt;getLogger()&lt;/span&gt;&lt;/code&gt;
to return a different adapter type with &lt;code class="xref py py-meth docutils literal notranslate"&gt;&lt;span class="pre"&gt;audit()&lt;/span&gt;&lt;/code&gt; and
&lt;code class="xref py py-meth docutils literal notranslate"&gt;&lt;span class="pre"&gt;deprecated()&lt;/span&gt;&lt;/code&gt; methods, allowing us to keep the API as it is for
now to buy time to update the callers that use the methods that would
otherwise be removed. Since we are starting this work at the beginning
of a cycle, I have updated the proposal to move us directly to the
sort of API we want to keep.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="impact-on-existing-apis"&gt;
&lt;h3&gt;Impact on Existing APIs&lt;/h3&gt;
&lt;p&gt;We remove some APIs, but most of them have equivalent forms available from
other libraries. There are three cases that do not.&lt;/p&gt;
&lt;section id="contextadapter-audit"&gt;
&lt;h4&gt;ContextAdapter.audit&lt;/h4&gt;
&lt;p&gt;The &lt;code class="xref py py-class docutils literal notranslate"&gt;&lt;span class="pre"&gt;ContextAdapter&lt;/span&gt;&lt;/code&gt; provides an &lt;code class="xref py py-meth docutils literal notranslate"&gt;&lt;span class="pre"&gt;audit()&lt;/span&gt;&lt;/code&gt; method for
logging at INFO+1 level. This will be removed, and the log messages
updated to either use the INFO level or use the &lt;code class="xref py py-meth docutils literal notranslate"&gt;&lt;span class="pre"&gt;log()&lt;/span&gt;&lt;/code&gt; method
with the audit level.&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;$ for d in ceilometer cinder glance heat ironic keystone neutron nova sahara trove swift;
do echo $d; ack LOG.audit $d/$d | wc -l; done
ceilometer
0
cinder
4
glance
0
heat
0
ironic
0
keystone
0
neutron
0
nova
101
sahara
0
trove
0
swift
0
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="contextadapter-deprecated"&gt;
&lt;h4&gt;ContextAdapter.deprecated&lt;/h4&gt;
&lt;p&gt;The &lt;code class="xref py py-meth docutils literal notranslate"&gt;&lt;span class="pre"&gt;deprecated()&lt;/span&gt;&lt;/code&gt; method of the &lt;code class="xref py py-class docutils literal notranslate"&gt;&lt;span class="pre"&gt;ContextAdapter&lt;/span&gt;&lt;/code&gt; is
replaced with a new function in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;versionutils&lt;/span&gt;&lt;/code&gt;. See
&lt;a class="reference external" href="https://blueprints.launchpad.net/oslo-incubator/+spec/fix-import-cycle-log-and-versionutils"&gt;fix-import-cycle-log-and-versionutils&lt;/a&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="contextadapter-keyword-argument-handling"&gt;
&lt;h4&gt;ContextAdapter keyword argument handling&lt;/h4&gt;
&lt;p&gt;The &lt;code class="xref py py-class docutils literal notranslate"&gt;&lt;span class="pre"&gt;ContextAdapter&lt;/span&gt;&lt;/code&gt; API supports doing:&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;LOG&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'some message: &lt;/span&gt;&lt;span class="si"&gt;%(named_arg)s&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;named_arg&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The standard logger methods don’t accept arbitrary keyword arguments
to be part of the ‘extra’, but we have enough cases of this that we
need to continue to support the pattern to avoid churn and breaking
things in the other projects. We will implement a
&lt;code class="xref py py-class docutils literal notranslate"&gt;&lt;span class="pre"&gt;KeywordArgumentAdapter&lt;/span&gt;&lt;/code&gt; to be returned by &lt;code class="xref py py-func docutils literal notranslate"&gt;&lt;span class="pre"&gt;getLogger()&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;div class="admonition warning"&gt;
&lt;p class="admonition-title"&gt;Warning&lt;/p&gt;
&lt;p&gt;Oslo libraries should not use this feature, to avoid circular
dependencies between the libraries and oslo.log.&lt;/p&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="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="configuration-impact"&gt;
&lt;h3&gt;Configuration 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;See “Impact on Existing APIs” above.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Doug Hellmann (doug-hellmann)&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="milestones"&gt;
&lt;h3&gt;Milestones&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Target Milestone for completion:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Kilo-1&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;Verify that the &lt;code class="xref py py-class docutils literal notranslate"&gt;&lt;span class="pre"&gt;ContextHandler&lt;/span&gt;&lt;/code&gt; works properly with
&lt;code class="xref py py-class docutils literal notranslate"&gt;&lt;span class="pre"&gt;Message&lt;/span&gt;&lt;/code&gt;, and update it to make it work if it does not.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;See “Proposed Change” above.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="incubation"&gt;
&lt;h2&gt;Incubation&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;section id="adoption"&gt;
&lt;h3&gt;Adoption&lt;/h3&gt;
&lt;p&gt;As apps that use the incubated version of oslo.log are updated, they
will need to be changed to get loggers directly from the standard
library module and to use &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;versionutils&lt;/span&gt;&lt;/code&gt; for &lt;code class="xref py py-meth docutils literal notranslate"&gt;&lt;span class="pre"&gt;deprecated()&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="library"&gt;
&lt;h3&gt;Library&lt;/h3&gt;
&lt;p&gt;oslo.log&lt;/p&gt;
&lt;/section&gt;
&lt;section id="anticipated-api-stabilization"&gt;
&lt;h3&gt;Anticipated API Stabilization&lt;/h3&gt;
&lt;p&gt;This change is part of stabilizing the API for oslo.log before
graduation.&lt;/p&gt;
&lt;/section&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="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;We need to remove the import cycle between log and versionutils
before implementing this
change. &lt;a class="reference external" href="https://blueprints.launchpad.net/oslo/+spec/app-agnostic-logging-parameters"&gt;https://blueprints.launchpad.net/oslo/+spec/app-agnostic-logging-parameters&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Discussion from the Juno summit: &lt;a class="reference external" href="https://etherpad.openstack.org/p/juno-oslo-release-plan"&gt;https://etherpad.openstack.org/p/juno-oslo-release-plan&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Related blueprint on using our context as a base class: &lt;a class="reference external" href="https://blueprints.launchpad.net/oslo.log/+spec/app-agnostic-logging-parameters"&gt;https://blueprints.launchpad.net/oslo.log/+spec/app-agnostic-logging-parameters&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Related blueprint for graduating oslo.log: &lt;a class="reference external" href="https://blueprints.launchpad.net/oslo.log/+spec/graduate-oslo-log"&gt;https://blueprints.launchpad.net/oslo.log/+spec/graduate-oslo-log&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Related blueprint for fixing the import cycle between logging and versionutils: &lt;a class="reference external" href="https://blueprints.launchpad.net/oslo-incubator/+spec/fix-import-cycle-log-and-versionutils"&gt;https://blueprints.launchpad.net/oslo-incubator/+spec/fix-import-cycle-log-and-versionutils&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This work is licensed under a Creative Commons Attribution 3.0
Unported License.
&lt;a class="reference external" href="http://creativecommons.org/licenses/by/3.0/legalcode"&gt;http://creativecommons.org/licenses/by/3.0/legalcode&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
</description><pubDate>Mon, 29 Sep 2014 00:00:00 </pubDate></item><item><title>Adoption of tooz</title><link>https://specs.openstack.org/openstack/oslo-specs/specs/kilo/tooz-adoption.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/oslo/+spec/tooz-adoption"&gt;https://blueprints.launchpad.net/oslo/+spec/tooz-adoption&lt;/a&gt;&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;The tooz library started its development phase on Stackforge in order to be used
by the OpenStack project. Now that this library is starting to get adoption and
is being used by OpenStack projects (Ceilometer), having the Oslo program taking
responsibility for it would help its maintenance in the future.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;The proposed change is to adopt this library under the Oslo program so we
can maintain it.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Do nothing.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;jdanjou&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="milestones"&gt;
&lt;h3&gt;Milestones&lt;/h3&gt;
&lt;p&gt;kilo-1&lt;/p&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Move the repository stackforge/tooz to openstack/tooz&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Change driver and maintainer of &lt;a class="reference external" href="https://launchpad.net/python-tooz"&gt;https://launchpad.net/python-tooz&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add oslo-core to tooz-core on Gerrit&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add the python-tooz Launchpad project to the “oslo” project group so it will
show up in bug queries, etc.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This work is licensed under a Creative Commons Attribution 3.0
Unported License.
&lt;a class="reference external" href="http://creativecommons.org/licenses/by/3.0/legalcode"&gt;http://creativecommons.org/licenses/by/3.0/legalcode&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
</description><pubDate>Thu, 18 Sep 2014 00:00:00 </pubDate></item><item><title>Add tpool proxy wrapper for DB-API calls</title><link>https://specs.openstack.org/openstack/oslo-specs/specs/juno/add-tpool-proxy-wrapper.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/oslo-incubator/+spec/add-tpool-proxy-wrapper"&gt;https://blueprints.launchpad.net/oslo-incubator/+spec/add-tpool-proxy-wrapper&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;During Icehouse release cycle in order to drop dependency on eventlet we
removed eventlet &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tpool.Proxy&lt;/span&gt;&lt;/code&gt; helper and the corresponding config option
(&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;use_tpool&lt;/span&gt;&lt;/code&gt;) from oslo.db code. Projects were supposed to store those in
their source trees. Since then we’ve got a lot of push back from Nova and
Cinder teams based on their experience of adoption of oslo.db changes. To
make things easier for oslo.db users, it’d actually be better to provide
optional integration with eventlet &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tpool.Proxy&lt;/span&gt;&lt;/code&gt; as a separate module within
oslo.db tree.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Most OpenStack deployments nowadays use MySQL. Unfortunately, the most popular
MySQL Python DBAPI driver - &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;MySQL-Python&lt;/span&gt;&lt;/code&gt; - has a serious problem with
eventlet green threads: being a C-extension it hangs the process on blocking
DB queries (as eventlet can’t monkey patch it to force a green thread switch
on blocking reads/writes from/to a socket).&lt;/p&gt;
&lt;p&gt;eventlet provides a work around for this problem: &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tpool.Proxy&lt;/span&gt;&lt;/code&gt; helper class
is meant to wrap classes/modules which methods/functions might possibly block
the execution of a green thread. The call is performed in the context of a
real OS thread, which knows how to deal with eventlet thread pool, on return
it will switch the execution context back to a green thread, so the process
doesn’t hang.&lt;/p&gt;
&lt;p&gt;Common DB code used to provide &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;use_tpool&lt;/span&gt;&lt;/code&gt; option which enabled
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tpool.Proxy&lt;/span&gt;&lt;/code&gt; proxying for all database methods calls. This was used by Nova
at least.  It’s worth mentioning, that in order to actually use &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;use_tpool&lt;/span&gt;&lt;/code&gt;
option one had to use a patched version of eventlet, as neither PyPI releases
nor master HEAD play nicely with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;MySQL-Python&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;During Icehouse release cycle we worked on removing extra dependencies from
common DB code. eventlet was removed as one of the dependencies we thought were
unnecessary (as oslo.db should neither enforce you to use a particular
concurrency model, nor it can make any assumptions how the target projects
process concurrent requests, whether they use eventlet green threads, real
OS threads, multiple processing, etc). But the best is the enemy of the good,
and it seems that it’s actually better to provide optional integration with
eventlet &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tpool.Proxy&lt;/span&gt;&lt;/code&gt;, so the people wouldn’t need to do this in their
source trees.&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 it possible to use oslo.db with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;MySQL-Python&lt;/span&gt;&lt;/code&gt; DB API driver and
eventlet &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tpool.Proxy&lt;/span&gt;&lt;/code&gt; call proxying we need:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Provide a helper that will either call &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;DBAPI&lt;/span&gt;&lt;/code&gt; methods directly or use
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tpool.Proxy&lt;/span&gt;&lt;/code&gt; to wrap the calls depending on the value of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;use_tpool&lt;/span&gt;&lt;/code&gt;
config option set.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Make this proposed helper register &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;use_tpool&lt;/span&gt;&lt;/code&gt; config option in group
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;database&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add an additional entry point to oslo.db, that will expose &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;use_tpool&lt;/span&gt;&lt;/code&gt;
config option to projects.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Even though we’ll use eventlet &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tpool.Proxy&lt;/span&gt;&lt;/code&gt; class at runtime, we are not
going to add it to oslo.db &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;requirements.txt&lt;/span&gt;&lt;/code&gt; (we don’t want eventlet to
be an install time dependency; if you use eventlet, it will be up to you to
ensure it’s installed) and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;test-requirements.txt&lt;/span&gt;&lt;/code&gt; (that would prevent us
from running unit tests on Python 3.x versions; as we don’t need to test
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tpool.Proxy&lt;/span&gt;&lt;/code&gt; functionality itself, we could safely mock this class in
tests).&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;The alternative way to solve this would be:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Put this helper into &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;openstack.common.concurrency&lt;/span&gt;&lt;/code&gt; module, which would
depend on oslo.db.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Document, that if someone wanted to use oslo.db with eventlet
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tpool.Proxy&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;MySQL-Python&lt;/span&gt;&lt;/code&gt; Python DB API driver, they would need
to use a helper provided by &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;openstack.common.concurrency&lt;/span&gt;&lt;/code&gt; module.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The advantage of this solution is that we don’t need to re-add eventlet stuff
back to oslo.db.&lt;/p&gt;
&lt;p&gt;The disadvantage of this solution is that we add more interdependencies between
oslo.* libraries and make it harder to use oslo.db (it’d probably be not very
clear to users why they need to use another library, if they use eventlet and
MySQL together).&lt;/p&gt;
&lt;/section&gt;
&lt;section id="impact-on-existing-apis"&gt;
&lt;h3&gt;Impact on Existing APIs&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="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;Enabling of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;use_tpool&lt;/span&gt;&lt;/code&gt; improves performance of DB-bound services (APIs) a
lot, when eventlet and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;MySQL-Python&lt;/span&gt;&lt;/code&gt; are used. Note: you will still need
to use unreleased eventlet code.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="configuration-impact"&gt;
&lt;h3&gt;Configuration Impact&lt;/h3&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;use_tpool&lt;/span&gt;&lt;/code&gt; won’t be a new config file option, we just introduce it in the
context of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo.db&lt;/span&gt;&lt;/code&gt;. Currently, projects consume it from
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;openstack.common.db&lt;/span&gt;&lt;/code&gt; package. No changes will be needed from deployers
perspective.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer Impact&lt;/h3&gt;
&lt;p&gt;OpenStack projects that want to use oslo.db with eventlet &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tpool.Proxy&lt;/span&gt;&lt;/code&gt; call
proxying will need to switch from using of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;DBAPI&lt;/span&gt;&lt;/code&gt; class to the new helper.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;akurilin&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;rpodolyaka&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="milestones"&gt;
&lt;h3&gt;Milestones&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Target Milestone for completion:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Juno-1&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 a new module to oslo.db which will introduce &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tpool.Proxy&lt;/span&gt;&lt;/code&gt; helper and
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;use_tpool&lt;/span&gt;&lt;/code&gt; config option.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add a new entry point to oslo.db exposing &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;use_tpool&lt;/span&gt;&lt;/code&gt; config option.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="incubation"&gt;
&lt;h2&gt;Incubation&lt;/h2&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;section id="adoption"&gt;
&lt;h3&gt;Adoption&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="library"&gt;
&lt;h3&gt;Library&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="anticipated-api-stabilization"&gt;
&lt;h3&gt;Anticipated API Stabilization&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&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;use_tpool&lt;/span&gt;&lt;/code&gt; should be marked as experimental. It should be stated in docs,
that patched version of eventlet is needed to use it.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;To work properly, this depends on the unreleased version of eventlet. Though,
we’ve been providing &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;use_tpool&lt;/span&gt;&lt;/code&gt; option so far anyway. Rackspace uses patched
version of eventlet in production. We are going to leave it up to deployers to
decide whether to enable this or not (default was and remains &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;False&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;p&gt;A PoC patch on review:&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://review.openstack.org/#/c/96467/"&gt;https://review.openstack.org/#/c/96467/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The related ML thread:&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="http://lists.openstack.org/pipermail/openstack-dev/2014-April/033120.html"&gt;http://lists.openstack.org/pipermail/openstack-dev/2014-April/033120.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The Launchpad bug for tracking usage of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;use_tpool&lt;/span&gt;&lt;/code&gt; in projects:&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://bugs.launchpad.net/nova/+bug/1309297"&gt;https://bugs.launchpad.net/nova/+bug/1309297&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;eventlet tpool docs:&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="http://eventlet.net/doc/threading.html#module-eventlet.tpool"&gt;http://eventlet.net/doc/threading.html#module-eventlet.tpool&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The patch fixing the eventlet issue:&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://bitbucket.org/eventlet/eventlet/pull-request/29/"&gt;https://bitbucket.org/eventlet/eventlet/pull-request/29/&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 work is licensed under a Creative Commons Attribution 3.0
Unported License.
&lt;a class="reference external" href="http://creativecommons.org/licenses/by/3.0/legalcode"&gt;http://creativecommons.org/licenses/by/3.0/legalcode&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
</description><pubDate>Tue, 09 Sep 2014 00:00:00 </pubDate></item><item><title>Add ChainingRegExpFilter into rootwrap</title><link>https://specs.openstack.org/openstack/oslo-specs/specs/juno/chaining-regexp-filter.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/oslo-incubator/+spec/chaining-regexp-filter"&gt;https://blueprints.launchpad.net/oslo-incubator/+spec/chaining-regexp-filter&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Add new filter which accepts utilities prefixed to other commands, such as
‘nice’ and ‘ionice’. This will increase maintenability of config files.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Currently we don’t have a good way to define filters to allow prefix utilities.
For example, cinder is using 3 RegExpFilter rules to allow ‘ionice’ + ‘dd’
command which cover various ‘dd’ options. But this is fragile to changes of
‘dd’ usage (actually these rules are broken now by a bugfix patch for ‘dd’:
&lt;a class="reference external" href="https://bugs.launchpad.net/cinder/+bug/1318748"&gt;https://bugs.launchpad.net/cinder/+bug/1318748&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;By adding ChainingRegExpFilter, which is configured by the format below, we
can easily add a new filter that accepts prefix utilities.&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;dl class="simple"&gt;
&lt;dt&gt;filter_name: ChainingRegExpFilter, &amp;lt;command&amp;gt;, &amp;lt;user&amp;gt;,&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;&amp;lt;RegExp list for the arguments&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;This filter regards the length of the regular expressions list as the number of
arguments to be checked, and remaining parts are checked by other filters.
That is, the command specified to the argument of prefix utility must be
allowed to execute directly.&lt;/p&gt;
&lt;p&gt;For example, ‘ionice’+’dd’ can be accepted by single rule below
safely (that is, accepted only when the following command is acceptable by
other filters).&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;ionice: ChainingRegExpFilter, ionice, root, ionice, -c[0-3]( -n[0-7])?&lt;/p&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;‘dd’ must also be allowed to execute directly (without ‘ionice’).
Note that cinder currently allows ‘dd’ for root using CommandFilter as default.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;We could implement a specialized filter class for each prefix command like
IpNetnsExecFilter each time it is needed.
That might be easier to reuse the same rule among projects, although it may
require a lot of classes.
ChainingRegExpFilter is more generic, so it is still useful at least until the
utility is found sharable.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="impact-on-existing-apis"&gt;
&lt;h3&gt;Impact on Existing APIs&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;Rules for prefix utilities must be written carefully not to allow unchecked
commands executed. For example, it can be dangerous to allowing any string
(‘.*’) for the argument that could be interpreted as command to be executed.&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="configuration-impact"&gt;
&lt;h3&gt;Configuration Impact&lt;/h3&gt;
&lt;p&gt;New filter ‘ChainingRegExpFilter’ will be available.&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;tsekiyama&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="milestones"&gt;
&lt;h3&gt;Milestones&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Target Milestone for completion:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Juno-1&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 ChainingRegExpFilter
-&amp;gt; &lt;a class="reference external" href="https://review.openstack.org/#/c/97336/"&gt;https://review.openstack.org/#/c/97336/&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="incubation"&gt;
&lt;h2&gt;Incubation&lt;/h2&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;section id="adoption"&gt;
&lt;h3&gt;Adoption&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="library"&gt;
&lt;h3&gt;Library&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="anticipated-api-stabilization"&gt;
&lt;h3&gt;Anticipated API Stabilization&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;Usage of ChainingRegExpFilter should be added to the document.&lt;/p&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 feature provides a good way for Cinder to fix ‘ionice’ command rules&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A cinder patch to implement I/O rate limit requires to execute ‘cgexec’
prefix utility with rootwrap ( &lt;a class="reference external" href="https://review.openstack.org/#/c/92894/"&gt;https://review.openstack.org/#/c/92894/&lt;/a&gt; )&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This work is licensed under a Creative Commons Attribution 3.0
Unported License.
&lt;a class="reference external" href="http://creativecommons.org/licenses/by/3.0/legalcode"&gt;http://creativecommons.org/licenses/by/3.0/legalcode&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
</description><pubDate>Tue, 09 Sep 2014 00:00:00 </pubDate></item><item><title>Graduating oslo.concurrency</title><link>https://specs.openstack.org/openstack/oslo-specs/specs/juno/graduate-oslo-concurrency.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/oslo.concurrency/+spec/graduate-oslo-concurrency"&gt;https://blueprints.launchpad.net/oslo.concurrency/+spec/graduate-oslo-concurrency&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;A library for managing threads and processes.&lt;/p&gt;
&lt;section id="library-name"&gt;
&lt;h2&gt;Library Name&lt;/h2&gt;
&lt;p&gt;oslo.concurrency&lt;/p&gt;
&lt;/section&gt;
&lt;section id="contents"&gt;
&lt;h2&gt;Contents&lt;/h2&gt;
&lt;p&gt;lockutils.py
tests/unit/test_lockutils.py
fixture/lockutils.py&lt;/p&gt;
&lt;p&gt;processutils.py
tests/unit/test_processutils.py&lt;/p&gt;
&lt;/section&gt;
&lt;section id="early-adopters"&gt;
&lt;h2&gt;Early Adopters&lt;/h2&gt;
&lt;p&gt;Neutron - there was a note from the summit session that some changes in the
Neutron rootwrap calling code needed to be addressed as part of this work,
but no one remembers the details so we’ll start with it to make sure any
issues are addressed before cutting a final release.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;bnemec&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="primary-maintainer"&gt;
&lt;h3&gt;Primary Maintainer&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary Maintainer:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;bnemec&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="security-contact"&gt;
&lt;h3&gt;Security Contact&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Security Contact:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;bnemec&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="milestones"&gt;
&lt;h3&gt;Milestones&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Target Milestone for completion:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Juno-2&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;&lt;a class="reference external" href="https://wiki.openstack.org/wiki/Oslo/CreatingANewLibrary#Checklist"&gt;https://wiki.openstack.org/wiki/Oslo/CreatingANewLibrary#Checklist&lt;/a&gt;&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Make lockutils.main() a console script entry point&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Clean up processutils use of greenthreads and random sleeps&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Rename fixture/lockutils.py to fixture.py in the lib&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Fix PosixLock problem with program termination:
&lt;a class="reference external" href="https://bugs.launchpad.net/oslo/+bug/1327946"&gt;https://bugs.launchpad.net/oslo/+bug/1327946&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Open a bug about this lib’s use of fileutils so it can be converted when
oslo.io graduates&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="adoption-notes"&gt;
&lt;h2&gt;Adoption Notes&lt;/h2&gt;
&lt;p&gt;None&lt;/p&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://blueprints.launchpad.net/oslo/+spec/graduate-oslo-log"&gt;https://blueprints.launchpad.net/oslo/+spec/graduate-oslo-log&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/oslo/+spec/cleanup-processutils-for-graduation"&gt;https://blueprints.launchpad.net/oslo/+spec/cleanup-processutils-for-graduation&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;lockutils uses fileutils, so that module will be copied from oslo-incubator
until oslo.io graduates.&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://etherpad.openstack.org/p/juno-oslo-release-plan"&gt;https://etherpad.openstack.org/p/juno-oslo-release-plan&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 work is licensed under a Creative Commons Attribution 3.0
Unported License.
&lt;a class="reference external" href="http://creativecommons.org/licenses/by/3.0/legalcode"&gt;http://creativecommons.org/licenses/by/3.0/legalcode&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
</description><pubDate>Tue, 09 Sep 2014 00:00:00 </pubDate></item><item><title>Graduating oslo.log</title><link>https://specs.openstack.org/openstack/oslo-specs/specs/juno/graduate-oslo-log.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/oslo.log/+spec/graduate-oslo-log"&gt;https://blueprints.launchpad.net/oslo.log/+spec/graduate-oslo-log&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The oslo.log library contains common code for configuring logging in
OpenStack services.&lt;/p&gt;
&lt;section id="library-name"&gt;
&lt;h2&gt;Library Name&lt;/h2&gt;
&lt;p&gt;oslo.log&lt;/p&gt;
&lt;/section&gt;
&lt;section id="contents"&gt;
&lt;h2&gt;Contents&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;openstack/common/context.py&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;openstack/common/local.py&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;openstack/common/log.py&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;openstack/common/fixture/logging.py&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;tests/unit/test_context.py&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;tests/unit/test_local.py&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;tests/unit/test_log.py&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;tests/unit/fixture/test_logging.py&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="early-adopters"&gt;
&lt;h2&gt;Early Adopters&lt;/h2&gt;
&lt;p&gt;No projects have stepped forward. I’ll probably experiment with
ceilometer, if none of the liaisons volunteer first.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Doug Hellmann (doug-hellmann)&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Chuck Short (zulcss)
dims&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="primary-maintainer"&gt;
&lt;h3&gt;Primary Maintainer&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary Maintainer:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Doug Hellmann (doug-hellmann)&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="security-contact"&gt;
&lt;h3&gt;Security Contact&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Security Contact:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Doug Hellmann (doug-hellmann)&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="milestones"&gt;
&lt;h3&gt;Milestones&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Target Milestone for completion:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Juno-2&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://blueprints.launchpad.net/oslo/+spec/fix-import-cycle-log-and-versionutils"&gt;https://blueprints.launchpad.net/oslo/+spec/fix-import-cycle-log-and-versionutils&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/Oslo/CreatingANewLibrary#Checklist"&gt;https://wiki.openstack.org/wiki/Oslo/CreatingANewLibrary#Checklist&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Organizational changes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Move the option definitions into a private file.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add a &lt;code class="xref py py-func docutils literal notranslate"&gt;&lt;span class="pre"&gt;register_options()&lt;/span&gt;&lt;/code&gt; function to be called before
parsing command line options and before calling &lt;code class="xref py py-func docutils literal notranslate"&gt;&lt;span class="pre"&gt;setup()&lt;/span&gt;&lt;/code&gt; to
register the command line (and other) options for logging.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Keep &lt;code class="xref py py-func docutils literal notranslate"&gt;&lt;span class="pre"&gt;setup()&lt;/span&gt;&lt;/code&gt; in log.py, but change its API to take a config
object as argument.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Move the formatter classes to separate files.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Move handler classes to separate files.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Expose &lt;code class="xref py py-func docutils literal notranslate"&gt;&lt;span class="pre"&gt;set_defaults()&lt;/span&gt;&lt;/code&gt; in log.py but move it to the options
file and change the API to take a config object as an argument.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Keep &lt;code class="xref py py-func docutils literal notranslate"&gt;&lt;span class="pre"&gt;getLogger()&lt;/span&gt;&lt;/code&gt; in log.py&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Move &lt;code class="xref py py-class docutils literal notranslate"&gt;&lt;span class="pre"&gt;WritableLogger&lt;/span&gt;&lt;/code&gt; to a separate public module.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Make the &lt;code class="xref py py-mod docutils literal notranslate"&gt;&lt;span class="pre"&gt;local&lt;/span&gt;&lt;/code&gt; module private (&lt;code class="xref py py-mod docutils literal notranslate"&gt;&lt;span class="pre"&gt;_local&lt;/span&gt;&lt;/code&gt;). We may move
the module to another library in the future, but for now only the
context and logging code uses it.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="adoption-notes"&gt;
&lt;h2&gt;Adoption Notes&lt;/h2&gt;
&lt;p&gt;The code changes described above should allow all apps to import with
a statement 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="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;oslo.log&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;log&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;replacing the current form:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;foo.openstack.common&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;log&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;Prerequisites:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/oslo/+spec/fix-import-cycle-log-and-versionutils"&gt;https://blueprints.launchpad.net/oslo/+spec/fix-import-cycle-log-and-versionutils&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Related blueprints:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/oslo/+spec/fix-import-cycle-log-and-versionutils"&gt;https://blueprints.launchpad.net/oslo/+spec/fix-import-cycle-log-and-versionutils&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/oslo/+spec/app-agnostic-logging-parameters"&gt;https://blueprints.launchpad.net/oslo/+spec/app-agnostic-logging-parameters&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Discussion from the Juno summit: &lt;a class="reference external" href="https://etherpad.openstack.org/p/juno-oslo-release-plan"&gt;https://etherpad.openstack.org/p/juno-oslo-release-plan&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This work is licensed under a Creative Commons Attribution 3.0
Unported License.
&lt;a class="reference external" href="http://creativecommons.org/licenses/by/3.0/legalcode"&gt;http://creativecommons.org/licenses/by/3.0/legalcode&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
</description><pubDate>Tue, 09 Sep 2014 00:00:00 </pubDate></item><item><title>Graduating Oslo Middleware</title><link>https://specs.openstack.org/openstack/oslo-specs/specs/juno/graduate-oslo-middleware.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/oslo.middleware/+spec/graduate-oslo-middleware"&gt;https://blueprints.launchpad.net/oslo.middleware/+spec/graduate-oslo-middleware&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The new oslo.middleware library will provide a common library for wsgi
middleware currently contained in oslo-incubator.&lt;/p&gt;
&lt;section id="library-name"&gt;
&lt;h2&gt;Library Name&lt;/h2&gt;
&lt;p&gt;oslo.middleware&lt;/p&gt;
&lt;/section&gt;
&lt;section id="contents"&gt;
&lt;h2&gt;Contents&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;openstack/common/middleware/base.py&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;openstack/common/middleware/catch_errors.py&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;openstack/common/middleware/correlation_id.py&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;openstack/common/middleware/debug.py&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;openstack/common/middleware/request_id.py&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;openstack/common/middleware/sizelimit.py&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;tests/unit/middleware/test_catch_errors.py&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;tests/unit/middleware/test_correlation_id.py&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;tests/unit/middleware/test_request_id.py&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;tests/unit/middleware/test_sizelimit.py&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="early-adopters"&gt;
&lt;h2&gt;Early Adopters&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="public-api"&gt;
&lt;h2&gt;Public API&lt;/h2&gt;
&lt;p&gt;oslo.middleware library provides access to the following middleware
(‘middleware’ suffix will be dropped from original naming):&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;CatchErrors&lt;/span&gt;
&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;CorrelationId&lt;/span&gt;
&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;Debug&lt;/span&gt;
&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;RequestId&lt;/span&gt;
&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;RequestBodySizeLimiter&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;To utilise the new middleware, after including oslo.middleware library,
projects can declare the new middleware in wsgi pipeline as such:&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="nb"&gt;filter&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;middleware&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;paste&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;filter_factory&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;oslo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;middleware&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;ClassName&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;.&lt;/span&gt;&lt;span class="n"&gt;factory&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;chungg&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="primary-maintainer"&gt;
&lt;h3&gt;Primary Maintainer&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary Maintainer:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;dims&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other Contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;chungg&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="security-contact"&gt;
&lt;h3&gt;Security Contact&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Security Contact:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;dims&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="milestones"&gt;
&lt;h3&gt;Milestones&lt;/h3&gt;
&lt;p&gt;Target Milestone for completion: Juno-3&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;&lt;a class="reference external" href="https://wiki.openstack.org/wiki/Oslo/CreatingANewLibrary#Checklist"&gt;https://wiki.openstack.org/wiki/Oslo/CreatingANewLibrary#Checklist&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;add deprecated decorator to current incubator classes&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;drop middleware suffix from class names&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;import middleware classes into middleware/__init__.py&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;audit middleware will not be included. it will be included in
keystonemiddleware as part of keystone’s adoption of audit&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;notifier middleware will not be included. it will be included in
oslo.messaging to minimise dependencies in oslo.middleware.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="adoption-notes"&gt;
&lt;h2&gt;Adoption Notes&lt;/h2&gt;
&lt;p&gt;General use of middleware remains the same. The only change in usage would be
to reference middlware in oslo.middleware library rather than openstack/common.&lt;/p&gt;
&lt;p&gt;A deprecated decorator will be added to existing incubator classes so when
the incubator version is used, log will notify of current oslo.middleware
version.&lt;/p&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="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;&lt;a class="reference external" href="https://etherpad.openstack.org/p/oslo-middleware-dependency"&gt;https://etherpad.openstack.org/p/oslo-middleware-dependency&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 work is licensed under a Creative Commons Attribution 3.0
Unported License.
&lt;a class="reference external" href="http://creativecommons.org/licenses/by/3.0/legalcode"&gt;http://creativecommons.org/licenses/by/3.0/legalcode&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
</description><pubDate>Tue, 09 Sep 2014 00:00:00 </pubDate></item><item><title>Graduating oslo.serialization</title><link>https://specs.openstack.org/openstack/oslo-specs/specs/juno/graduate-oslo-serialization.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/oslo.serialization/+spec/graduate-oslo-serialization"&gt;https://blueprints.launchpad.net/oslo.serialization/+spec/graduate-oslo-serialization&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;OpenStack-specific serialization tools&lt;/p&gt;
&lt;section id="library-name"&gt;
&lt;h2&gt;Library Name&lt;/h2&gt;
&lt;p&gt;oslo.serialization&lt;/p&gt;
&lt;/section&gt;
&lt;section id="contents"&gt;
&lt;h2&gt;Contents&lt;/h2&gt;
&lt;p&gt;jsonutils.py
tests/unit/test_jsonutils.py&lt;/p&gt;
&lt;/section&gt;
&lt;section id="early-adopters"&gt;
&lt;h2&gt;Early Adopters&lt;/h2&gt;
&lt;p&gt;?&lt;/p&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;bnemec&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="primary-maintainer"&gt;
&lt;h3&gt;Primary Maintainer&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary Maintainer:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;bnemec&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="security-contact"&gt;
&lt;h3&gt;Security Contact&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Security Contact:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;bnemec&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="milestones"&gt;
&lt;h3&gt;Milestones&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Target Milestone for completion:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Juno-2&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;&lt;a class="reference external" href="https://wiki.openstack.org/wiki/Oslo/CreatingANewLibrary#Checklist"&gt;https://wiki.openstack.org/wiki/Oslo/CreatingANewLibrary#Checklist&lt;/a&gt;&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Adopt oslo.i18n in jsonutils&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="adoption-notes"&gt;
&lt;h2&gt;Adoption Notes&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Adopting projects will need to have switched to oslo.i18n before using this
library because it references the Message class, so the project needs to be
using the same one.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&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.i18n&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;oslo.utils (for timeutils)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;importutils from incubator.  That may be moving to oslo.utils, however.&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://etherpad.openstack.org/p/juno-oslo-release-plan"&gt;https://etherpad.openstack.org/p/juno-oslo-release-plan&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 work is licensed under a Creative Commons Attribution 3.0
Unported License.
&lt;a class="reference external" href="http://creativecommons.org/licenses/by/3.0/legalcode"&gt;http://creativecommons.org/licenses/by/3.0/legalcode&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
</description><pubDate>Tue, 09 Sep 2014 00:00:00 </pubDate></item><item><title>Graduating oslo.utils</title><link>https://specs.openstack.org/openstack/oslo-specs/specs/juno/graduate-oslo-utils.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/oslo.utils/+spec/graduate-oslo-utils"&gt;https://blueprints.launchpad.net/oslo.utils/+spec/graduate-oslo-utils&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Every project has one. &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo.utils&lt;/span&gt;&lt;/code&gt; is our “grab-bag” library, made
up of little modules with few dependencies that are too small to
warrant release management on their own.&lt;/p&gt;
&lt;section id="library-name"&gt;
&lt;h2&gt;Library Name&lt;/h2&gt;
&lt;p&gt;oslo.utils&lt;/p&gt;
&lt;/section&gt;
&lt;section id="contents"&gt;
&lt;h2&gt;Contents&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;openstack/common/excutils.py&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;openstack/common/importutils.py&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;openstack/common/network_utils.py -&amp;gt; openstack/common/netutils.py&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;openstack/common/timeutils.py&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;openstack/common/strutils.py&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;openstack/common/units.py&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;tests/unit/test_excutils.py&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;tests/unit/test_importutils.py&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;tests/unit/test_netutils.py&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;tests/unit/test_timeutils.py&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;tests/unit/test_strutils.py&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;tests/unit/test_units.py&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="early-adopters"&gt;
&lt;h2&gt;Early Adopters&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;dims&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;doug-hellmann
flaper87&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="primary-maintainer"&gt;
&lt;h3&gt;Primary Maintainer&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary Maintainer:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;dims&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other Contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;doug-hellmann
flaper87&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="security-contact"&gt;
&lt;h3&gt;Security Contact&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Security Contact:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;dims&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="milestones"&gt;
&lt;h3&gt;Milestones&lt;/h3&gt;
&lt;p&gt;Target Milestone for completion: Juno-2&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;&lt;a class="reference external" href="https://blueprints.launchpad.net/oslo/+spec/graduate-oslo-i18n"&gt;https://blueprints.launchpad.net/oslo/+spec/graduate-oslo-i18n&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;After bringing importutils.py into the library repo, clean up the
portions that will be part of its public API so that only
&lt;code class="xref py py-func docutils literal notranslate"&gt;&lt;span class="pre"&gt;try_import()&lt;/span&gt;&lt;/code&gt; is exported. Clean up test_importutils.py to
match.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://wiki.openstack.org/wiki/Oslo/CreatingANewLibrary#Checklist"&gt;https://wiki.openstack.org/wiki/Oslo/CreatingANewLibrary#Checklist&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Split strutils into 2 different modules:
1. Containing encoding/decoding functions
- safe_encode
- safe_decode
2. Containing string transformation functions
- to_slug
- string_to_bytes
- int_from_bool_as_string
- bool_from_string
- mask_password&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Mark not ported functions as deprecated in the incubator.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="adoption-notes"&gt;
&lt;h2&gt;Adoption Notes&lt;/h2&gt;
&lt;p&gt;The copy of importutils we are releasing in this library will only
have the function &lt;code class="xref py py-func docutils literal notranslate"&gt;&lt;span class="pre"&gt;try_import()&lt;/span&gt;&lt;/code&gt; in its public API. Use of the
other functions for actually importing modules and classes is
deprecated, and should be replaced with stevedore. We are leaving the
current importutils.py in the incubator untouched to ease that
transition.&lt;/p&gt;
&lt;p&gt;No API changes are anticipated for the other modules, so it should
just be a matter of updating the import statements.&lt;/p&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://blueprints.launchpad.net/oslo/+spec/graduate-oslo-i18n"&gt;https://blueprints.launchpad.net/oslo/+spec/graduate-oslo-i18n&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;This work obsoletes
&lt;a class="reference external" href="https://blueprints.launchpad.net/oslo/+spec/graduate-oslo-language"&gt;https://blueprints.launchpad.net/oslo/+spec/graduate-oslo-language&lt;/a&gt;,
since we’re incorporating excutils.py into this library instead.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://wiki.openstack.org/wiki/Oslo/GraduationStatus#oslo.utils"&gt;https://wiki.openstack.org/wiki/Oslo/GraduationStatus#oslo.utils&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/juno-oslo-release-plan"&gt;https://etherpad.openstack.org/p/juno-oslo-release-plan&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This work is licensed under a Creative Commons Attribution 3.0
Unported License.
&lt;a class="reference external" href="http://creativecommons.org/licenses/by/3.0/legalcode"&gt;http://creativecommons.org/licenses/by/3.0/legalcode&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
</description><pubDate>Tue, 09 Sep 2014 00:00:00 </pubDate></item><item><title>Add a ConfigFilter wrapper class to enforce option scoping</title><link>https://specs.openstack.org/openstack/oslo-specs/specs/juno/oslo-config-cfgfilter.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/oslo.config/+spec/oslo-config-cfgfilter"&gt;https://blueprints.launchpad.net/oslo.config/+spec/oslo-config-cfgfilter&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Add a new class designed to wrap cfg.ConfigFilter, with the following use cases
in mind:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Help enforce that a given module does not access options registered by
another module, without first declaring those cross-module dependencies
using import_opt().&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Prevent private configuration opts from being visible to modules other than
the one which registered it.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;section id="cross-module-option-dependencies"&gt;
&lt;h3&gt;Cross-Module Option Dependencies&lt;/h3&gt;
&lt;p&gt;When using the global cfg.CONF object, it is quite common for a module to
require the existence of configuration options registered by other modules.&lt;/p&gt;
&lt;p&gt;For example, if module ‘foo’ registers the ‘blaa’ option and the module ‘bar’
uses the ‘blaa’ option then ‘bar’ might do:&lt;/p&gt;
&lt;div class="highlight-default 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="nn"&gt;foo&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;CONF&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;blaa&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;However, it’s completely non-obvious why foo is being imported (is it
unused, can we remove the import) and where the ‘blaa’ option comes from.&lt;/p&gt;
&lt;p&gt;The CONF.import_opt() method allows such a dependency to be explicitly
declared:&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;CONF&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;import_opt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'blaa'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'foo'&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;CONF&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;blaa&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;However, import_opt() has a weakness - if ‘bar’ imports ‘foo’ using the import
builtin and doesn’t use import_opt() to import ‘blaa’, then ‘blaa’ can still be
used without problems. Similarly, where multiple options are registered a
module imported via import_opt(), a lazy programmer can get away with only
declaring a dependency on a single option.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="private-configuration-options"&gt;
&lt;h3&gt;Private Configuration Options&lt;/h3&gt;
&lt;p&gt;Libraries which register configuration options typically do not want users of
the library API to access those configuration options. If API users do access
private configuration options, those users will be disrupted if and when a
configuration option is renamed. In other words, one does not typically wish
for the name of the private config options to be part of the public API.&lt;/p&gt;
&lt;p&gt;For example, users of the oslo.messaging library should not be allowed to
reference configuration options (like CONF.rpc_backend) which were registered
by the library.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;section id="add-a-configfilter-class"&gt;
&lt;h3&gt;Add a ConfigFilter Class&lt;/h3&gt;
&lt;p&gt;The ConfigFilter implementation recognizes that there are two parts to a
ConfigOpts instance - the set of option schemas registered with it and raw
config values parsed from config files and the command line.&lt;/p&gt;
&lt;p&gt;By simply ensuring that ConfigOpts has its own set of option schemas but yet
shares the parsed values (the _namespace attribute) with the underlying
ConfigOpts, we allow ConfigFilter to act as a distinct view of the underlying
parsed values.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="id1"&gt;
&lt;h3&gt;Cross-Module Option Dependencies&lt;/h3&gt;
&lt;p&gt;The ConfigFilter class will provide a way to ensure that options are not
available unless they have been registered in the module or imported using
import_opt() e.g. with:&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;CONF&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ConfigFilter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CONF&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;CONF&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;import_opt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'blaa'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'foo'&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;CONF&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;blaa&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;no other options other than ‘blaa’ are available via CONF.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="id2"&gt;
&lt;h3&gt;Private Configuration Options&lt;/h3&gt;
&lt;p&gt;The ConfigFilter class will provide a way for a library to register options
such that they are not visible via the ConfigOpts instance which the API user
supplies to the library. 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="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;__future__&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;print_function&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;oslo.config.cfg&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;openstack.common.cfgfilter&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Widget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;object&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;conf&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;conf&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;conf&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;_private_conf&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ConfigFilter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;conf&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_private_conf&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;register_opt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;StrOpt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'foo'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

    &lt;span class="nd"&gt;@property&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&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;_private_conf&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;foo&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;ConfigOpts&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;widget&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Widget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;conf&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;widget&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;foo&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;conf&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# raises NoSuchOptError&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;No other way of addressing the cross-module dependencies issue was considered.&lt;/p&gt;
&lt;p&gt;The private configuration options issue could have been addressed by making it
somewhat sane for configuration options to be part of the public API, by
providing backwards compatibility support when configuration options are
renamed or moved. This option was rejected because it seems desirable to not
expose configuration options unconditionally through the API even if this
backwards compat was available.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="impact-on-existing-apis"&gt;
&lt;h3&gt;Impact on Existing APIs&lt;/h3&gt;
&lt;p&gt;There is no direct impact to the existing APIs, but ConfigFilter uses a private
implementation detail of ConfigOpts where it references ConfigOpts._namespace
and ConfigOpts._args to link ConfigFilter’s ConfigOpts instance with the raw
parsed values in the wrapped ConfigOpts instances.&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="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;Minimal memory impact for each ConfigFilter instance the application, along
with minimal lookup time overhead.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="configuration-impact"&gt;
&lt;h3&gt;Configuration 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 who choose to use ConfigFilter will need to change how their
configuration options are exposed to Oslo’s configuration file generator since
options will not be discoverable via cfg.CONF. Instead, developers will need to
register an oslo.config.opts entry point which returns a list of the available
configuration options.&lt;/p&gt;
&lt;p&gt;The change impacts oslo.config developers by making ConfigOpts slightly harder
to refactor later because ConfigFilter depends on its implementation details.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;&lt;a class="reference external" href="mailto:markmc%40redhat.com"&gt;markmc&lt;span&gt;@&lt;/span&gt;redhat&lt;span&gt;.&lt;/span&gt;com&lt;/a&gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="milestones"&gt;
&lt;h3&gt;Milestones&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Target Milestone for completion:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;juno-1&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 work items should be straightforward - a working ConfigFilter
implementation is waiting for review in oslo-incubator. It just needs to be
moved into oslo.config with zero changes.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="incubation"&gt;
&lt;h2&gt;Incubation&lt;/h2&gt;
&lt;p&gt;The cfgfilter module does exist in oslo-incubator, but there are no users yet
so it can just be removed.&lt;/p&gt;
&lt;section id="adoption"&gt;
&lt;h3&gt;Adoption&lt;/h3&gt;
&lt;p&gt;oslo.messaging will most likely be the first to adopt this.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="library"&gt;
&lt;h3&gt;Library&lt;/h3&gt;
&lt;p&gt;oslo.config.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="anticipated-api-stabilization"&gt;
&lt;h3&gt;Anticipated API Stabilization&lt;/h3&gt;
&lt;p&gt;The API should be stable now.&lt;/p&gt;
&lt;/section&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="dependencies"&gt;
&lt;h2&gt;Dependencies&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://blueprints.launchpad.net/oslo/+spec/cfg-filter-view"&gt;https://blueprints.launchpad.net/oslo/+spec/cfg-filter-view&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/95676"&gt;https://review.openstack.org/95676&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This work is licensed under a Creative Commons Attribution 3.0
Unported License.
&lt;a class="reference external" href="http://creativecommons.org/licenses/by/3.0/legalcode"&gt;http://creativecommons.org/licenses/by/3.0/legalcode&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
</description><pubDate>Tue, 09 Sep 2014 00:00:00 </pubDate></item><item><title>oslo-config-generator</title><link>https://specs.openstack.org/openstack/oslo-specs/specs/juno/oslo-config-generator.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/oslo.config/+spec/oslo-config-generator"&gt;https://blueprints.launchpad.net/oslo.config/+spec/oslo-config-generator&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Add a command line utility for generating sample config files to
oslo.config which will replace the generator utility in
oslo-incubator.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;The need for such a utility is well understood:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;A sample config file containing the list of all available config
options, the associated help text, type and commented out default
value makes it much easier for operators to discover and understand
config options.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It needs to be possible for operators to run the tool themselves
rather than attempting to maintain these auto-generated files in
git.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The issues with the current tool include:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Loading modules and expecting them to register their options with
cfg.CONF is slow, weird, and error prone.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;This reliance on cfg.CONF perpetuates the use of a global object.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The generator doesn’t have information about which groups an option
belongs to so it resorts to guessing - this probably has resulted in
people avoiding adding a ‘debug’ option in multiple groups, for
example.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It’s impossible to to handle “split configs” - i.e. some config
options only make sense in glance-api.conf and others only make
sense in glance-registry.conf - because the generator has no
information on to decide which service an option is used by.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We already have a pattern of explicitly registering config options
under the oslo.config.opts entry point namespace, but it’s not
used outside oslo.messaging right now.&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;We will add a sample config file generator utility called
oslo-config-generator to the oslo.config package.&lt;/p&gt;
&lt;p&gt;This new utility will take a dramatically different approach to
discovery from the current generator in oslo-incubator, whereby we
move away from magic towards much more explicit control over the
options the generator sees.&lt;/p&gt;
&lt;p&gt;To generate a sample config file for oslo.messaging you would run:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;$&amp;gt; oslo-config-generator --namespace oslo.messaging &amp;gt; oslo.messaging.conf
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;This generated sample lists all of the available options, along with their help
string, type, deprecated aliases and defaults.&lt;/p&gt;
&lt;p&gt;The –namespace option specifies an entry point name registered under the
‘oslo.config.opts’ entry point namespace. For example, in oslo.messaging’s
setup.cfg we have:&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;entry_points&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;oslo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;opts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="n"&gt;oslo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;messaging&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;oslo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;messaging&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;list_opts&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The callable referenced by the entry point should take no arguments and return
a list of (group_name, [opt_1, opt_2]) tuples. For example:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;opts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StrOpt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'foo'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StrOpt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'bar'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CONF&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;register_opts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;group&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'blaa'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;list_opts&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="s1"&gt;'blaa'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;You might choose to return a copy of the options so that the return value can’t
be modified for nefarious purposes:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;list_opts&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="s1"&gt;'blaa'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;copy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;deepcopy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;))]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;A single codebase might have multiple programs, each of which use a subset of
the total set of options registered by the codebase. In that case, you can
register multiple entry points:&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;entry_points&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;oslo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;opts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="n"&gt;nova&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;common&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;nova&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;list_common_opts&lt;/span&gt;
    &lt;span class="n"&gt;nova&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;api&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;nova&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;list_api_opts&lt;/span&gt;
    &lt;span class="n"&gt;nova&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;compute&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;nova&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;list_compute_opts&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;and generate a config file specific to each program:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;$&amp;gt; oslo-config-generator --namespace oslo.messaging \
                         --namespace nova.common \
                         --namespace nova.api &amp;gt; nova-api.conf
$&amp;gt; oslo-config-generator --namespace oslo.messaging \
                         --namespace nova.common \
                         --namespace nova.compute &amp;gt; nova-compute.conf
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;To make this more convenient, you can use config files to describe your config
files:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;$&amp;gt; cat &amp;gt; config-generator/api.conf &amp;lt;&amp;lt;EOF
[DEFAULT]
output_file = etc/nova/nova-api.conf
namespace = oslo.messaging
namespace = nova.common
namespace = nova.api
EOF
$&amp;gt; cat &amp;gt; config-generator/compute.conf &amp;lt;&amp;lt;EOF
[DEFAULT]
output_file = etc/nova/nova-compute.conf
namespace = oslo.messaging
namespace = nova.compute
namespace = nova.compute
EOF
$&amp;gt; oslo-config-generator --config-file config-generator/api.conf
$&amp;gt; oslo-config-generator --config-file config-generator/compute.conf
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The default runtime values of configuration options are not always the most
suitable values to include in sample config files - for example, rather than
including the IP address or hostname of the machine where the config file
was generated, you might want to include something like ‘10.0.0.1’. To
facilitate this, options can be supplied with a ‘sample_default’ attribute:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StrOpt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'base_dir'&lt;/span&gt;
           &lt;span class="n"&gt;default&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;getcwd&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
           &lt;span class="n"&gt;sample_default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'/usr/lib/myapp'&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;The alternative would be to stick with the current generator’s
automagic option discovery approach and attempt to work around its
deficiencies. This has been the path we’ve been on for quite some
time, but has been a constant source of frustration.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="impact-on-existing-apis"&gt;
&lt;h3&gt;Impact on Existing APIs&lt;/h3&gt;
&lt;p&gt;The generator is primarily intended to be used via the
oslo-config-generator command line interface, but it is also available
via a public generate(conf) API. There is also a
register_cli_opts(conf) API so that callers to generate() can set
config options beforehand.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;There is no security 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 generator completes more quickly because it has to load less
modules in order to discover options.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="configuration-impact"&gt;
&lt;h3&gt;Configuration Impact&lt;/h3&gt;
&lt;p&gt;No configuration impact.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer Impact&lt;/h3&gt;
&lt;p&gt;The explicit approach of advertising configuration options means that
developers will need to manually maintain a list of the config options
available in their code so it can be returned by the callable
registered as a oslo.config.opts entry point.&lt;/p&gt;
&lt;p&gt;This shouldn’t be a huge burden because it typically is a list which
references existing lists of options.&lt;/p&gt;
&lt;p&gt;However, some sort of automated assistance to help catch cases where
the list needs updating would be hugely helpful. How exactly that will
work remains to be seen.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;markmc&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="milestones"&gt;
&lt;h3&gt;Milestones&lt;/h3&gt;
&lt;p&gt;juno-2&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 oslo-config-generator to oslo.config.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Advertise the keystone auth_token options under oslo.config.opts.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Demonstrate how services like Nova, Ceilometer, Glance or Heat can
adopt this new utility.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Remove the old generator from oslo-incubator.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Set up infra jobs to publish sample config files somewhere like
docs.openstack.org.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Consider adding something like ‘python setup.py sample_config’.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="incubation"&gt;
&lt;h2&gt;Incubation&lt;/h2&gt;
&lt;p&gt;The new utility replaces the one in oslo-incubator.&lt;/p&gt;
&lt;section id="adoption"&gt;
&lt;h3&gt;Adoption&lt;/h3&gt;
&lt;p&gt;All applications are expected to adopt it.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="library"&gt;
&lt;h3&gt;Library&lt;/h3&gt;
&lt;p&gt;oslo.config.&lt;/p&gt;
&lt;p&gt;Note this means that oslo.config gains a dependency on stevedore.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="anticipated-api-stabilization"&gt;
&lt;h3&gt;Anticipated API Stabilization&lt;/h3&gt;
&lt;p&gt;The API is pretty minimal and is expected to be stable from the time
it is merged.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;The operators guide would benefit from instructions on how to use the utility.&lt;/p&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="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/oslo/+spec/oslo-config-generator"&gt;https://blueprints.launchpad.net/oslo/+spec/oslo-config-generator&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/oslo/+bug/1300546"&gt;https://bugs.launchpad.net/oslo/+bug/1300546&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="http://lists.openstack.org/pipermail/openstack-dev/2014-June/thread.html#37954"&gt;http://lists.openstack.org/pipermail/openstack-dev/2014-June/thread.html#37954&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This work is licensed under a Creative Commons Attribution 3.0
Unported License.
&lt;a class="reference external" href="http://creativecommons.org/licenses/by/3.0/legalcode"&gt;http://creativecommons.org/licenses/by/3.0/legalcode&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
</description><pubDate>Tue, 09 Sep 2014 00:00:00 </pubDate></item><item><title>Support Policy configuration directories</title><link>https://specs.openstack.org/openstack/oslo-specs/specs/juno/policy-configuration-directories.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/oslo-incubator/+spec/policy-configuration-directories"&gt;https://blueprints.launchpad.net/oslo-incubator/+spec/policy-configuration-directories&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This propose to add a way to override the default policy rules.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;There some complain about policy configuration is hard to use. So think of
there isn’t a way to override default policy rule. The only way to modify
default policy rule is to edit the policy.conf. This isn’t convenient for
deployer.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Proposed to support for policy configuration directories. The policy rules
that loaded from policy configuration directories will override the default
policy rules from ‘policy_file’.&lt;/p&gt;
&lt;p&gt;Add new configuration option:&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;cfg.ListOpt(‘policy_configuration_directories’, default=[‘policy.d’],&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;help=_(‘The directories of policy configuration files’))&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;‘policy_configuration_directories’ accept a list of directories. Those
directories will be iterated by order. The files in those directories will be
loaded by alphabet order, and the rules will be overrided by that order. The
sub-directories will be ignore.&lt;/p&gt;
&lt;p&gt;If the directory in the policy_configuration_directories isn’t existed, there
will be error raised when loading policy.&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="impact-on-existing-apis"&gt;
&lt;h3&gt;Impact on Existing APIs&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 policy rules will be loaded from specified directories. If those
directories have appropriate permissions, there won’t have any security issue.&lt;/p&gt;
&lt;p&gt;The permissions suggest only the admin can read and write the policy
configurations directories and files. And openstack program can read those
directories and files is enough.&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 need iterated a list of directories, that will slow down the
init/reload of policy rules.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="configuration-impact"&gt;
&lt;h3&gt;Configuration Impact&lt;/h3&gt;
&lt;p&gt;This change introduce new configuration option:
policy_definition_path = [list of directories]&lt;/p&gt;
&lt;p&gt;The option is convenient for deployer change where to store the policy config
files. The default value is ‘policy.d’. The location searching will be same with
option ‘policy_file’.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer Impact&lt;/h3&gt;
&lt;p&gt;When developer add this feature into app, developer need to add UpgradeImpact
flags and upgrade docs to notice deployer to create ‘policy.d’ directory in
his development, otherwise there will be error raised by ‘policy.d’ can’t be
found.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;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 Xu (&lt;a class="reference external" href="mailto:xuhj%40linux.vnet.ibm.com"&gt;xuhj&lt;span&gt;@&lt;/span&gt;linux&lt;span&gt;.&lt;/span&gt;vnet&lt;span&gt;.&lt;/span&gt;ibm&lt;span&gt;.&lt;/span&gt;com&lt;/a&gt;)&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="milestones"&gt;
&lt;h3&gt;Milestones&lt;/h3&gt;
&lt;p&gt;Target Milestone for completion: Juno-3&lt;/p&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;p&gt;This change only need one single patch.
This will be implemented in
oslo-incubator/openstack/common/policy.py:Enforcer&lt;/p&gt;
&lt;p&gt;Enforcer.load_rules will scan the policy configuration directories, and load
them to override the rules by order.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="incubation"&gt;
&lt;h2&gt;Incubation&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;section id="adoption"&gt;
&lt;h3&gt;Adoption&lt;/h3&gt;
&lt;p&gt;Nova will use this to improvement the configuration of policy rules. But this
feature can be used by most of openstack project that support policy rules.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="library"&gt;
&lt;h3&gt;Library&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="anticipated-api-stabilization"&gt;
&lt;h3&gt;Anticipated API Stabilization&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;The new option should be documented at configuration documents.
&lt;a class="reference external" href="http://docs.openstack.org/icehouse/config-reference/content"&gt;http://docs.openstack.org/icehouse/config-reference/content&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;And we should describe how to write policies to explain how multiple policy
files are combined to build up the full set of rules.&lt;/p&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="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;&lt;a class="reference external" href="https://etherpad.openstack.org/p/juno-nova-devops"&gt;https://etherpad.openstack.org/p/juno-nova-devops&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 work is licensed under a Creative Commons Attribution 3.0
Unported License.
&lt;a class="reference external" href="http://creativecommons.org/licenses/by/3.0/legalcode"&gt;http://creativecommons.org/licenses/by/3.0/legalcode&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
</description><pubDate>Tue, 09 Sep 2014 00:00:00 </pubDate></item><item><title>Adoption of pylockfile</title><link>https://specs.openstack.org/openstack/oslo-specs/specs/juno/pylockfile-adoption.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/pylockfile/+spec/pylockfile-adoption"&gt;https://blueprints.launchpad.net/pylockfile/+spec/pylockfile-adoption&lt;/a&gt;&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;The pylockfile library is used by at least oslo.db instead of
oslo-incubator/lockutils. This library has seen a few maintenance issues in
the last months, which caused problem. The current maintainer is looking for
help to maintain it in the future.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;The proposed change is to adopt this library under the Oslo program so we
can maintain it and merge it with oslo-incubator/lockutils.
The goal is to move the feature we have in lockutils and that are not
present in pylockfile such as fcntl() based locking, and then release
oslo.lockutils as a thin-layer of top of it relying on oslo.config and
oslo.log.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Do nothing.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;jdanjou&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="milestones"&gt;
&lt;h3&gt;Milestones&lt;/h3&gt;
&lt;p&gt;juno-3&lt;/p&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Create a repository on OpenStack infra&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add oslo-core to pylockfile-core on Gerrit&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Release a new version of pylockutils&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&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;Request from current pylockfile maintainer for help:
&lt;a class="reference external" href="https://github.com/smontanaro/pylockfile/issues/11#issuecomment-45634012"&gt;https://github.com/smontanaro/pylockfile/issues/11#issuecomment-45634012&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;openstack-dev thread: &lt;a class="reference external" href="http://lists.openstack.org/pipermail/openstack-dev/2014-June/038387.html"&gt;http://lists.openstack.org/pipermail/openstack-dev/2014-June/038387.html&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Review to create pylockfile repository: &lt;a class="reference external" href="https://review.openstack.org/#/c/101911/"&gt;https://review.openstack.org/#/c/101911/&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This work is licensed under a Creative Commons Attribution 3.0
Unported License.
&lt;a class="reference external" href="http://creativecommons.org/licenses/by/3.0/legalcode"&gt;http://creativecommons.org/licenses/by/3.0/legalcode&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
</description><pubDate>Tue, 09 Sep 2014 00:00:00 </pubDate></item><item><title>Use a Filter API with SQLAlchemy Engine Events for Error Wrapping</title><link>https://specs.openstack.org/openstack/oslo-specs/specs/juno/use-events-for-error-wrapping.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/oslo.db/+spec/use-events-for-error-wrapping"&gt;https://blueprints.launchpad.net/oslo.db/+spec/use-events-for-error-wrapping&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The system that oslo.db provides for transformation of SQLAlchemy execution-
time errors, including DBAPI and related errors, should be improved
to be simpler, more portable, more forwards-compatible, more extensible,
and more testable.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;oslo.db presents a system by which common exceptions raised within SQLAlchemy
are intercepted and usually converted to an oslo-specific exception
within &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo.db.exception&lt;/span&gt;&lt;/code&gt;.  The mechanism by which this occurs involves
placing a wrapper function around key ORM &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Session&lt;/span&gt;&lt;/code&gt; methods such that when
they are invoked and raise an exception, the exception is caught by
a handler function which makes some immediate decisions about the exception,
then potentially hands it off to a series of “exception match” functions.
The oslo.db test suite contains a variety of tests for this system,
with separate test suites for different kinds of exceptions.&lt;/p&gt;
&lt;p&gt;Key issues in the current implementation of this system include:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;In order to place the error interceptor where statements are executed,
oslo.db presents a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Session&lt;/span&gt;&lt;/code&gt; subclass which then lists out key methods
that invoke database queries, and wraps them with a wrapper called
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;@_wrap_db_error&lt;/span&gt;&lt;/code&gt;.  This approach misses many ORM-level
methods, such as all of those on top of the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Query&lt;/span&gt;&lt;/code&gt; object itself
(see &lt;a class="reference external" href="https://review.openstack.org/#/c/92002/"&gt;https://review.openstack.org/#/c/92002/&lt;/a&gt; for one such issue),
the lazy loading emitted by mapped attributes that are unloaded or
expired, as well as the entire Core level system, which is exposed
even at the ORM level in the case of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Session.execute()&lt;/span&gt;&lt;/code&gt;
in the form of the result object, which also can throw database-level
exceptions on row access.    The system in its current form cannot be
expanded to cover every possible access without great difficulty,
particularly with regards to ORM-instrumented attributes.
Even if this system could be expanded to cover every
possible method, it isn’t forwards compatible with new systems that might
also invoke statement execution from different start points.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The error interceptor itself provides an imperative
(read: lots of conditionals) system of intercepting exceptions and
routing them to different decision paths.  Some exceptions, such as
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;UnicodeEncodeError&lt;/span&gt;&lt;/code&gt; to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;DBInvalidUnicodeParameter&lt;/span&gt;&lt;/code&gt;, are handled directly
inside of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;@_wrap_db_error&lt;/span&gt;&lt;/code&gt;.  Others, such as those of deadlocks
and duplicate rows, are handed off to other functions, which
themselves contain a fair degree of imperative logic, particularly
the case of the “duplicate row” handler.  Adding support for new
exception scenarios necessitates adding new conditionals to these
systems, destabilizing the logic for all of them as they are all
interrelated.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The system of unit testing the exception filters is inconsistent and
incomplete.  The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;_wrap_db_error()&lt;/span&gt;&lt;/code&gt; function itself has only 14
out of 27 code lines total covered by tests; about half of the potential
error scenarios aren’t fully tested.  Additionally, the tests, such as
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;TestDBDeadlocked&lt;/span&gt;&lt;/code&gt;, test the error filter function
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;_raise_if_deadlock_error()&lt;/span&gt;&lt;/code&gt;, but don’t test it in context of the full
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;_wrap_db_error()&lt;/span&gt;&lt;/code&gt; function.  If a different filter function
such as &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;_raise_if_db_connection_lost()&lt;/span&gt;&lt;/code&gt; is inadvertently catching
this error, that scenario is not being tested.  It’s not easy to add tests
for new error scenarios as the testing system takes different approaches
for different exceptions.&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;oslo.db will take advantage of a SQLAlchemy &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Connection&lt;/span&gt;&lt;/code&gt;-level hook
that is called for all DBAPI-generated exceptions that SQLAlchemy itself
intercepts within the statement execution and result-fetching phases.
While such a hook, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;dbapi_error()&lt;/span&gt;&lt;/code&gt;, has been supported
within SQLAlchemy since 0.7, it will be superseded by a new hook,
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;handle_error()&lt;/span&gt;&lt;/code&gt;, which is fleshed out to ensure that it is invoked for all
possible errors that SQLAlchemy itself handles, not just DBAPI-level
exceptions, as well as such that it supports conversion
of the given exception into a new one.&lt;/p&gt;
&lt;p&gt;The mechanism for the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;handle_error()&lt;/span&gt;&lt;/code&gt; hook, which will be released in
SQLAlchemy 0.9.7, will be available for all prior versions of SQLAlchemy
listed in requirements.txt by back-porting the event into oslo.db directly,
using a custom &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Connection&lt;/span&gt;&lt;/code&gt; subclass, which SQLAlchemy supports
replacement of via the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Engine&lt;/span&gt;&lt;/code&gt; that serves as its factory.
This aspect of the change is similar to the current approach that subclasses
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Session&lt;/span&gt;&lt;/code&gt;, and technically can satisfy the feature going forward on its own;
however, allowing SQLAlchemy to provide this event natively from 0.9.7 forward
means that oslo.db’s compatibility layer only needs to target already-released
versions of SQLAlchemy, with no risk that the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Connection&lt;/span&gt;&lt;/code&gt; subclass approach
changes in future versions, as it won’t be used for future versions.&lt;/p&gt;
&lt;p&gt;Within the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;handle_error()&lt;/span&gt;&lt;/code&gt; listener, the logic for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;_wrap_db_error()&lt;/span&gt;&lt;/code&gt;
will be unrolled into a declarative system, where functions can be declared
that present a filter for a specific database / exception / regular expression
combination.   These filters will be interpreted by a generic system
that ensures the correct filter is called for a given exception input.  The
existing rules, in particular the regular expressions and the notes regarding
them, can be maintained and ported to the new system without being changed,
so the existing work that’s been done on this system based on real
database observation is maintained.&lt;/p&gt;
&lt;p&gt;An example of such a filter looks 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="nd"&gt;@filters&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="n"&gt;sqla_exc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OperationalError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="s2"&gt;"^.*\(1213, 'Deadlock.*"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nd"&gt;@filters&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="n"&gt;sqla_exc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OperationalError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="s2"&gt;"^.*deadlock detected.*"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;_deadlock_error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;operational_error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;match&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;engine_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;is_disconnect&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="n"&gt;exception&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DBDeadlock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;operational_error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;In the above approach, support for new database backends and newly intercepted
exceptions can be added with no impact on existing rules.&lt;/p&gt;
&lt;p&gt;On the testing side, a similar framework will allow construction of
exception filter tests using a consistent system that runs from
SQLAlchemy’s point of statement execution up through the filtering routine
to the end result.   The key to this system will be to mock the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Dialect.do_execute()&lt;/span&gt;&lt;/code&gt; method of the current engine’s dialect, such that
a specific exception, including a mock DBAPI-level exception, can be raised.
All exception scenarios will be easy to inject here, and the system of filters
and actions can be covered 100%.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;The errors could be handled at more of a framework level.   If all
oslo.db applications used the database code within some common
wrapper, such as a univerally used “transaction” wrapper, consistent
exception handling could occur at that level as well.   We aren’t
doing this because current database approaches are not at this level
of consistency, and it also places a restriction on all code that will
have the effect of unexpected and unhandled exceptions being raised if
this restriction isn’t obeyed in all cases.&lt;/p&gt;
&lt;p&gt;For routing of exceptions, an even-more data-driven system could be used,
such as a rules engine that expresses exception filtering and handling using
names.   We aren’t doing this because it would be too heavy-handed; as it
stands, we have a data-driven approach at the exception filtering level,
which moves into programmatic at the point at which we handle what to
do with the now-intercepted exception.  This seems like a good way to leverage
Python’s abilities to treat functions as data structures.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="impact-on-existing-apis"&gt;
&lt;h3&gt;Impact on Existing APIs&lt;/h3&gt;
&lt;p&gt;The change should not have impact outside of oslo.db except to the extent
that other systems are making explicit use of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;_wrap_db_error()&lt;/span&gt;&lt;/code&gt;.  This
function is underscored as private so should not be the case, however
if it is, we can provide &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;_wrap_db_error()&lt;/span&gt;&lt;/code&gt; that is a do-nothing method,
as the new filtering system takes place well beneath that layer.&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="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;handle_error()&lt;/span&gt;&lt;/code&gt; event and the filtering system use a negligible
additional amount of comparison and iteration compared to that of the
current system.  Both systems are only invoked after an exception
has been raised, which is already a non-performant branch within Python,
so any slight difference in performance has essentially no impact in any case.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="configuration-impact"&gt;
&lt;h3&gt;Configuration 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 oslo.db.exceptions system would now be in effect for all SQL operations.
Existing systems that aren’t covered by the existing system would now
invoke the new behavior.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;zzzeek&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="milestones"&gt;
&lt;h3&gt;Milestones&lt;/h3&gt;
&lt;p&gt;The initial prototype implementation is complete and will be put up as a
Gerrit accompanying this blueprint.&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;Implement the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;handle_error()&lt;/span&gt;&lt;/code&gt; event and tests within SQLAlchemy and
prepare for 0.9.7 release.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Implement the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;handle_error()&lt;/span&gt;&lt;/code&gt; compatibility layer within oslo.db,
porting selected elements of both the logic and tests from the
SQLAlchemy change.  This will take place in a new sub-package
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo.db.sqlalchemy.compat&lt;/span&gt;&lt;/code&gt;, which will be where various SQLAlchemy
backwards-compatibility systems of this nature will start to go.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Ensure the oslo.db layer works on 0.7, 0.8, and 0.9 series of SQLAlchemy.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Rework &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;_wrap_db_error()&lt;/span&gt;&lt;/code&gt; and sub-functions into the declarative filter
system, install the filter within the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo.db.sqlalchemy.session.create_engine()&lt;/span&gt;&lt;/code&gt; factory.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Locate all test suites within tests/ that are testing various parts of
the exception integration system and convert them to use the new system.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="incubation"&gt;
&lt;h2&gt;Incubation&lt;/h2&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;section id="adoption"&gt;
&lt;h3&gt;Adoption&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="library"&gt;
&lt;h3&gt;Library&lt;/h3&gt;
&lt;p&gt;oslo.db&lt;/p&gt;
&lt;/section&gt;
&lt;section id="anticipated-api-stabilization"&gt;
&lt;h3&gt;Anticipated API Stabilization&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;If there is documentation in oslo.db regarding exception handling, the fact
that this handling is installed into the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Engine&lt;/span&gt;&lt;/code&gt; at a core level should
be mentioned.&lt;/p&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 is dependent on the integration of SQLAlchemy 0.7, 0.8,
0.9 versions into the tox.ini suite, which has been merged.&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;This feature was discussed in the SQLAlchemy and OpenStack wiki page
at &lt;a class="reference external" href="https://wiki.openstack.org/wiki/OpenStack_and_SQLAlchemy#Exception_Rewriting"&gt;https://wiki.openstack.org/wiki/OpenStack_and_SQLAlchemy#Exception_Rewriting&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 work is licensed under a Creative Commons Attribution 3.0
Unported License.
&lt;a class="reference external" href="http://creativecommons.org/licenses/by/3.0/legalcode"&gt;http://creativecommons.org/licenses/by/3.0/legalcode&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
</description><pubDate>Tue, 09 Sep 2014 00:00:00 </pubDate></item><item><title>Teaching PBR about semver</title><link>https://specs.openstack.org/openstack/oslo-specs/specs/juno/pbr-semver.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/oslo/+spec/pbr-semver"&gt;https://blueprints.launchpad.net/oslo/+spec/pbr-semver&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;OpenStack uses semver but pbr doesn’t actually understand it today.
Teaching it to understand semver will allow less thought and more automation
by developers, as well as better and clearer version numbers for folk doing
continual deployment (CD) of OpenStack.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;With postversioning (the default) given a tag of 1.3.2 pbr generates per-commit
versions of 1.3.2.N.g$sha. pip currently considers such versions invalid, but if
pip learns about build tags - the g$sha, then the version would be considered a
release, but often the intent of an untagged commit is to be a developer
version for local installs / testing. So this is not &lt;a class="reference external" href="http://legacy.python.org/dev/peps/pep-0440/"&gt;PEP-440&lt;/a&gt; compliant.
Conflicting with this is the desire of CD deployers and CD packagers to have
monotonic versions that can be used to install packages on e.g. Debian systems,
but subsequent tags can collide with these versions as well.&lt;/p&gt;
&lt;p&gt;PEP-440 versions do not map entirely well to version_info - a core python
concept but some users of pbr export version_info tuples in their module, and
offering that would enable them to use pbr.&lt;/p&gt;
&lt;p&gt;Lastly, semver provides deterministic rules for picking the next version number
which at the moment is a developer task. Developers can easily get this wrong
because they’re having to think ‘what version next’ vs categorising the changes
in the version.&lt;/p&gt;
&lt;p&gt;In summary:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;The versions pbr generates are not always pip compatible (PEP440).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The versions pbr generates for non-tagged commits are marked as releases
rather than dev versions. This means that if pushed into a mirror pip
will default to installing them rather than the latest release.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;There is no tooling support to reconcile the needs of devs (give me a version
to install) and CD’ers (give me a unique version # for this commit in trunk
that sorts correctly with all other trunk versions).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;There is no tooling support for picking new (postversioned) version numbers.&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;section id="proposed-details"&gt;
&lt;h3&gt;Proposed details&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Change from tagging versions like 1.2.3a4 (which some projects are using) to
tagging them as 1.2.3.0a4 instead, and update the semver docs to specify the
leading 0 accordingly. This gets us both PEP440 compatibility (which permits
either 1.2.3a4 or 1.2.3.0a4 but not 1.2.3.a4) and conceptual compatibility
with semver where the MAJOR.MINOR.PATCH format is strongly expected to be just
numbers, which the 3a4 construct breaks. We need to continue accepting the
current format tags since they already exist on our branches - but we can
emit deprecation warnings.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add pseudo-headers to commits that indicate feature / api-break / deprecation
/ bugfix changes. The default will be to assume bugfix. If a commit fails to
mention the important changes this can be fixed up with a commit with just
the metadata header and some trivial change. If a commit incorrectly claimed
a significant change, we will live with the result - CD users can create
packages for any commit that has landed in a branch. For instance to mark a
new feature that introduces api incompatibility:&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;sem&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;ver&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;feature&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;api&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="k"&gt;break&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For untagged builds, generate devN versions - e.g.  x.y.z.dev4+gHASH, where
x.y.z are derived by applying the semver rules with the metadata about the
most recent change of each type. For pre-versioned builds, we will also
generate devN builds but will not apply semver rules. The +gHASH is driven
by PEP-440, and will be slightly syntax incompatible with upstream semver,
but we think this is the right tradeoff. Semantically it is compatible.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Provide a new command (&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;tag-release&lt;/span&gt;&lt;/code&gt;) to do the git tagging for developers.
It will accept parameters allowing manual control, but will enforce semver is
being followed (e.g. if there is a newer tag than the version being tagged in
the history of the branch, that’s an error). Alpha, beta and rc tagging can be
automated too.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Provide a python API for getting version_info style version data. 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="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;pbr.version&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="n"&gt;version_info&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pbr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Version&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'MYPACKAGENAME'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;version_info&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;Provide a new command (&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;deb-version&lt;/span&gt;&lt;/code&gt;) to output Debian package version
compatible version strings. This primarily involves translating PEP-440
precedence rules into Debian ~ and . component separators.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Provide a new command (&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;rpm-version&lt;/span&gt;&lt;/code&gt;) to output RPM version metadata for
incorporation in RPM versions using the &lt;a class="reference external" href="http://zenit.senecac.on.ca/wiki/index.php/ENVRA"&gt;ENVRA&lt;/a&gt; format. As RPM lacks a
‘before’ operator (~) the primary method for translation is to treat
pre-release and dev builds as release builds of next lowest version to drive
the sort order above all actual releases of the version below. We assume that
no version will ever have more than 9998 patch/minor releases.  E.g.
1.2.0.dev5 is rendered as 1.1.9999.dev5. 1.0.0.dev5 would be rendered as
0.0.9999.dev5 and finally 0.0.0.dev5 would also be rendered as 0.0.0.dev5 to
avoid negative version numbers.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Provide a new command (&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;next-version&lt;/span&gt;&lt;/code&gt;) to output the next calculated semver
version. E.g. if the last release was 1.2.3 but backwards incompatibility has
happened, this command would output 2.0.0. The expected use of this command
is to aid developers choose the next version to tag.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;sdist and the new Debian and RPM version string commands will accept a
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;--no-rc&lt;/span&gt;&lt;/code&gt; parameter which will tell them to only ever emit versions that
are a) normal versions or b) devN builds. This resolves the sorting ambiguity
in semver where devN is lower than &lt;em&gt;any&lt;/em&gt; pre-release build, but version
numbers may not have both a pre-release version &lt;em&gt;and&lt;/em&gt; a devN version
component. CD deployers can then include –no-rc in their scripts and have a
consistent timeline (as long as they’re pulling from a monotonically
advancing branch) while regular users and packagers will want to select
regular builds only.&lt;/p&gt;
&lt;p&gt;There is one caveat here which is that new point releases of old versions
must not be merged into the history of trunk, or the devN versions will be
reset at that point.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;section id="new-configuration-flags"&gt;
&lt;h4&gt;New configuration flags&lt;/h4&gt;
&lt;p&gt;We are adding a new command line option.&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;--no-rc&lt;/span&gt;&lt;/code&gt; passed on the command line to commands that output versions.
When passed this causes version calculation from git tags to never output
alpha/beta/rc versions - it will always work towards normal versions (that
is X.Y.Z versions). This provides a stable comparable timeline for versions
within one branch, so long as the ‘most recent release’ never resets without
also moving up to the next semver mandated version. For instance, working
with master, if semver dictates that the next version will be 1.2, and the
current version is 1.1.2 adding a new tag of 1.1.3 reachable from master
will reset the devN versions for all commits subsequent to 1.1.3 and thus
invalidate this timeline. Adding a tag of 1.2 is however fine, because the
next calculated version will be (at lowest) 1.2.1, and the devN versions
for any remaining unreleased commits will have a higher precedence than the
prior 1.2.0 devN versions before the 1.2 tag was added.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
&lt;section id="new-post-version-rules"&gt;
&lt;h4&gt;New post-version rules&lt;/h4&gt;
&lt;p&gt;There are four incrementable components in a version: major, minor, patch and
pre-release. The following is a description of how pbr will implement the
assignment rules described by semver.rst for post-versioned numbers. For
pre-versioned numbers, the user specifies the target version to use and we
cannot automatically increment versions. A future spec may consider doing
semver with pre-versioned version numbers in pbr, but since they are often
not semver versions, and because their definition is ‘the user has chosen’,
it is out of scope for now.&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;dl class="simple"&gt;
&lt;dt&gt;If there are one or more tags for a commit then the highest such tag is&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;considered to be the ‘last tag’ for these rules.&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If the last tag is a pre-release tag, then the –no-rc option is consulted.
If set, pre-release tags are not considered when looking for the last
tag.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The highest eligible tag reachable from the commit is considered to be the
‘last tag’. If there is more than one tag with equal distance (e.g. an rc
and a final tag on a single commit) then the highest tag is still used. If
there is no tag reachable at all, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;0.0.0&lt;/span&gt;&lt;/code&gt; is implied as the last tag.
Tags are eligible if they are PEP-440 version strings, reachable from the
commit in the git history, and not excluded by the –no-rc option.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If the distance to the last tag is zero, that tag supplies the version and
the process stops.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Otherwise, a patch level version is required and the version shall be a
devN version.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We then ask git for all the commits leading back to the last tag.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In each commit we look for a sem-ver: pseudo header, and if found
parse it (split on ‘,’ whitespace strip and build a set). Unknown
symbols are not an error (so that folk can’t wedge pbr), but we will
warn on them, and may want to make a linter for the gate.
Known symbols: &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;feature&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;api-break&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;deprecation&lt;/span&gt;&lt;/code&gt;, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;bugfix&lt;/span&gt;&lt;/code&gt;.
A missing sem-ver line is equivalent to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;sem-ver:&lt;/span&gt; &lt;span class="pre"&gt;bugfix&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If we found a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;deprecation&lt;/span&gt;&lt;/code&gt; or &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;feature&lt;/span&gt;&lt;/code&gt; then we do a minor version
increment.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I we found a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;api-break&lt;/span&gt;&lt;/code&gt; then we do a major version increment.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If the last tag has a major component of 0 then major and minor increments
are right-shifted. That is a major increment becomes a minor increment and
a minor increment becomes a patch level increment.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Using these rules a few examples may aid in 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="c1"&gt;# no tags, one commit, no sem-ver:&lt;/span&gt;
&lt;span class="n"&gt;last_tag&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.0.0&lt;/span&gt;
&lt;span class="n"&gt;tag_distance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.0.1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dev1&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;gHASH&lt;/span&gt;
&lt;span class="n"&gt;Debian&lt;/span&gt; &lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.0.1&lt;/span&gt;&lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="n"&gt;dev1&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;gHASH&lt;/span&gt;
&lt;span class="n"&gt;RPM&lt;/span&gt; &lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.0.0&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dev1&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;gHASH&lt;/span&gt;

&lt;span class="c1"&gt;# tag of 0.0.1 on a commit - tag sets version.&lt;/span&gt;
&lt;span class="n"&gt;last_tag&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.0.1&lt;/span&gt;
&lt;span class="n"&gt;tag_distance&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;version&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.0.1&lt;/span&gt;
&lt;span class="n"&gt;Debian&lt;/span&gt; &lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.0.1&lt;/span&gt;
&lt;span class="n"&gt;RPM&lt;/span&gt; &lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.0.1&lt;/span&gt;

&lt;span class="c1"&gt;# tag of 0.0.1.0a4 on a commit, 5 commits since the start&lt;/span&gt;
&lt;span class="c1"&gt;# tag sets X.Y.Z of next version, and a devN version is emitted.&lt;/span&gt;
&lt;span class="n"&gt;no_rc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt;
&lt;span class="n"&gt;last_tag&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.0.0&lt;/span&gt;
&lt;span class="n"&gt;tag_distance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="c1"&gt;# distance to origin&lt;/span&gt;
&lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.0.1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dev5&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;gHASH&lt;/span&gt;
&lt;span class="n"&gt;Debian&lt;/span&gt; &lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.0.1&lt;/span&gt;&lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="n"&gt;dev5&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;gHASH&lt;/span&gt;
&lt;span class="n"&gt;RPM&lt;/span&gt; &lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.0.0&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dev5&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;gHASH&lt;/span&gt;

&lt;span class="c1"&gt;# tag of 0.12.2, 2 commits ago with a sem-ver: deprecation line present&lt;/span&gt;
&lt;span class="c1"&gt;# in one of them.&lt;/span&gt;
&lt;span class="c1"&gt;# However since this is a 0.x.y version, we right shift the increment.&lt;/span&gt;
&lt;span class="n"&gt;last_tag&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.12.2&lt;/span&gt;
&lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.12.3&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dev2&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;gHASH&lt;/span&gt;
&lt;span class="n"&gt;Debian&lt;/span&gt; &lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.12.3&lt;/span&gt;&lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="n"&gt;dev2&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;gHASH&lt;/span&gt;
&lt;span class="n"&gt;RPM&lt;/span&gt; &lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.12.2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dev2&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;gHASH&lt;/span&gt;

&lt;span class="c1"&gt;# tag of 1.12.2, 2 commits ago with a sem-ver: deprecation line present&lt;/span&gt;
&lt;span class="c1"&gt;# in one of them.&lt;/span&gt;
&lt;span class="n"&gt;pbr_deprecation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;1.12&lt;/span&gt;
&lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;1.13.0&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dev2&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;gHASH&lt;/span&gt;
&lt;span class="n"&gt;Debian&lt;/span&gt; &lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.13.0&lt;/span&gt;&lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="n"&gt;dev2&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;gHASH&lt;/span&gt;
&lt;span class="n"&gt;RPM&lt;/span&gt; &lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.12.9999&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dev2&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;gHASH&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;We could do nothing, but right now folk are reinventing stuff in adhoc fashions
and there is no ability to reuse their solutions in a systematic fashion.&lt;/p&gt;
&lt;p&gt;We could put deprecated etc. markers in setup.cfg (see previous iterations of
this spec in gerrit). This was felt to be too tedious to maintain.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="impact-on-existing-apis"&gt;
&lt;h3&gt;Impact on Existing APIs&lt;/h3&gt;
&lt;p&gt;No public APIs change (since pbr has approximately no public APIs at all).&lt;/p&gt;
&lt;p&gt;New public APIs will be added that we have to support.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;The needed calculations are trivial, so non-trivially slower. Reading the git
history between releases is done for changelog generation already, so it will
be in cache, and pulling out lines from that is trivial.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="configuration-impact"&gt;
&lt;h3&gt;Configuration 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 can largely ignore this - it will just result in PEP-440 compatible
versions &lt;em&gt;unless&lt;/em&gt; the project has chosen to start using the new features.
If a project wants to opt into the new features they can do so: export
version_info tuples in their projects, record when they make breaking changes
and have pbr enforce appropriate version changes for them. These options are
all opt-in with one exception: the change of generated numbers to be PEP-440
compatible which includes the change to issue devN for untagged versions.&lt;/p&gt;
&lt;section id="developer-workflow"&gt;
&lt;h4&gt;Developer Workflow&lt;/h4&gt;
&lt;p&gt;This forms the beginnings of a manual for using semver in PBR.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Tagging releases: run setup.py next-version from the git commit you want to
become the release. This outputs the next version according to semver rules.
Make a git tag as normal using either that version, or any higher version you
desire.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Making API compatible bugfixes to code: Commit and push to gerrit as normal.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Making changes that add new features: Push to gerrit as usual, but include
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;sem-ver:&lt;/span&gt; &lt;span class="pre"&gt;feature&lt;/span&gt;&lt;/code&gt; in the commit.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Making changes that deprecate things: Push to gerrit as usual, but include
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;sem-ver:&lt;/span&gt; &lt;span class="pre"&gt;deprecation&lt;/span&gt;&lt;/code&gt; in the commit.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Making changes that break compatibility - either removing deprecated code or
removing not-yet deprecated code, or adding mandatory things users of the
code must do that they did not have to previously: Push to gerrit as usual,
but include &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;sem-ver:&lt;/span&gt; &lt;span class="pre"&gt;api-break&lt;/span&gt;&lt;/code&gt; in the commit.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Making daily/per commit builds of master for inclusion in package
repositories: Use &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;setup.py&lt;/span&gt; &lt;span class="pre"&gt;--no-rc&lt;/span&gt;&lt;/code&gt; to get package version numbers that
form a consistent timeline (so alpha/beta/rc are not reflected in the
version). The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;setup.py&lt;/span&gt; &lt;span class="pre"&gt;debian-version&lt;/span&gt; &lt;span class="pre"&gt;--no-rc&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;setup.py&lt;/span&gt; &lt;span class="pre"&gt;rpm-version&lt;/span&gt;
&lt;span class="pre"&gt;--no-rc&lt;/span&gt;&lt;/code&gt; commands will give you appropriate version numbers for use on
their respective platforms.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Robert Collins (lifeless)&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Joshua Harlow (harlowja)
Anyone I can rope in.&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="milestones"&gt;
&lt;h3&gt;Milestones&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Target Milestone for completion:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Juno-2&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;Cleanup internal logic in PBR to separate out the setuptools interactions and
the version modelling.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add devN-incrementing feature.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add history-grepping feature for incrementing major and minor versions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add tagging feature.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add debian-version feature.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add rpm-version feature.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add version_info feature.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="incubation"&gt;
&lt;h2&gt;Incubation&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;section id="adoption"&gt;
&lt;h3&gt;Adoption&lt;/h3&gt;
&lt;p&gt;ALL OF THEM.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="library"&gt;
&lt;h3&gt;Library&lt;/h3&gt;
&lt;p&gt;pbr&lt;/p&gt;
&lt;/section&gt;
&lt;section id="anticipated-api-stabilization"&gt;
&lt;h3&gt;Anticipated API Stabilization&lt;/h3&gt;
&lt;p&gt;None. It shall be perfect.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;The pbr manual (in the pbr tree) needs fleshing out to cover this behaviour.&lt;/p&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="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/pbr-postversion-semver"&gt;https://etherpad.openstack.org/p/pbr-postversion-semver&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://www.mail-archive.com/openstack-dev@lists.openstack.org/msg19450.html"&gt;https://www.mail-archive.com/openstack-dev@lists.openstack.org/msg19450.html&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="http://legacy.python.org/dev/peps/pep-0440/"&gt;http://legacy.python.org/dev/peps/pep-0440/&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This work is licensed under a Creative Commons Attribution 3.0
Unported License.
&lt;a class="reference external" href="http://creativecommons.org/licenses/by/3.0/legalcode"&gt;http://creativecommons.org/licenses/by/3.0/legalcode&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
</description><pubDate>Tue, 05 Aug 2014 00:00:00 </pubDate></item><item><title>Oslo Cache Updated to use dogpile.cache</title><link>https://specs.openstack.org/openstack/oslo-specs/specs/kilo/oslo-cache-using-dogpile.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/oslo/+spec/oslo-cache-using-dogpile"&gt;proposed bp oslo-cache-using-dogpile&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Currently the various OpenStack projects implement caching (memoization,
key-value-store, etc) in a number of various ways. All of the mechanisms for
caching should be unified under a single Oslo library &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo.cache&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;With the many implementations (and varying degree of flexibility) OpenStack
projects should standardize on a single library for caching (memoization,
key-value-store, etc) within the code base. Currently, Keystone has used
&lt;a class="reference external" href="http://dogpilecache.readthedocs.org/en/latest/"&gt;dogpile.cache&lt;/a&gt; very
successfully. With the flexible backend implementation, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;dogpile.cache&lt;/span&gt;&lt;/code&gt; is
a natural fit to replace the many different implementations of caching.&lt;/p&gt;
&lt;p&gt;The new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo.cache&lt;/span&gt;&lt;/code&gt; library would replace the following:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Keystone Caching Layer&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Keystone Key-Value-Store Implementation&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Oslo MemoryCache Module&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Caching within the Keystone Middleware&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Marconi use of oslo.cache (incubator) module&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;(potentially) Swift Ring Memcache&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This new module would also open the door for other projects to more easily
adopt memoization or other forms of caching.&lt;/p&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo.cache&lt;/span&gt;&lt;/code&gt; module is mostly targeted to be an OpenStack friendly
wrapper for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;dogpile.cache&lt;/span&gt;&lt;/code&gt;. This will provide a consistent way to cache and
memoize data within the OpenStack ecosystem.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;The current &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo-incubator&lt;/span&gt;&lt;/code&gt;
&lt;a class="reference external" href="https://git.openstack.org/cgit/openstack/oslo-incubator/openstack/common/cache"&gt;oslo openstack.common.cache module&lt;/a&gt;
would be replaced with an implementation that leverages &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;dogpile.cache&lt;/span&gt;&lt;/code&gt;
library instead of a custom-built system.&lt;/p&gt;
&lt;p&gt;This new implementation will provide a mechanism to handle key-value-store
(e.g. traditional Memcached) and memoization to begin with.&lt;/p&gt;
&lt;p&gt;The Base backends that will be supported are:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Memcached&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;BMemcached&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Standard Memcached&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Pylibmc&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In-Memory (Python dict-based)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Redis&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;MongoDB - There is a MongoDB backend that was developed for Keystone, a
similar (based upon the code in Keystone) implementation will be submitted
as an enhancement to the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;dogpile.cache&lt;/span&gt;&lt;/code&gt; library if it is not already
supported at the time of implementation. If the backend is not accepted
by the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;dogpile.cache&lt;/span&gt;&lt;/code&gt; library, it will be maintained in the
to-be-determined method of maintaining OpenStack specific backend modules.&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;oslo.cache&lt;/span&gt;&lt;/code&gt; module is intended to provide 3 distinct features above
and beyond raw use of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;dogpile.cache&lt;/span&gt;&lt;/code&gt;:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;OpenStack style configuration of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;dogpile.cache&lt;/span&gt;&lt;/code&gt;. It is not expected that
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;dogpile.cache&lt;/span&gt;&lt;/code&gt; would accept patches that include &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo.config&lt;/span&gt;&lt;/code&gt; as the
basis. Use of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo.config&lt;/span&gt;&lt;/code&gt; would not be appropriate in the case of
a more general-purpose library such as &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;dogpile.cache&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Updates to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;dogpile.cache&lt;/span&gt;&lt;/code&gt;. Any updates that are needed to support the
OpenStack specific configuration will be submitted to the upstream library.
This may include enhancements to the decorators for memoization and the
key-value-store interfaces. These potential enhancements will be submitted
with the plan to use them as they become available (oslo.cache may have a
little extra conditional code added until the new features are released and
OpenStack accepts the minimum &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;dogpile.cache&lt;/span&gt;&lt;/code&gt; version increase to the
global requirements), but it should not block development or use of the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo.cache&lt;/span&gt;&lt;/code&gt; module.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Backend maintenance. If the MongoDB backend is not accepted by the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;dogpile.cache&lt;/span&gt;&lt;/code&gt; library a clear path for maintaining OpenStack specific
backends will be documented and laid out (either within &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo.cache&lt;/span&gt;&lt;/code&gt; module
or an associated module).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Each project that implements either it’s own version of caching using
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;dogpile.cache&lt;/span&gt;&lt;/code&gt; or other implementations of caching will be converted to use
the new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo.cache&lt;/span&gt;&lt;/code&gt; module.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;This could be left to each project to implement their own caching or develop
an OpenStack specific set of modules. Neither of these options are optimal as
it requires specific knowledge of the various (or OpenStack specific) caching
system to implement a custom backend. With &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;dogpile.cache&lt;/span&gt;&lt;/code&gt; it is possible to
implement a very simple backend and configure it for use with all OpenStack
services that make use of the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo.cache&lt;/span&gt;&lt;/code&gt; module.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="impact-on-existing-apis"&gt;
&lt;h3&gt;Impact on Existing APIs&lt;/h3&gt;
&lt;p&gt;Current APIs should remain unchanged (both in Oslo and in other projects) until
caching is implemented. Caching implementation may impact the APIs in some
regard (e.g. memoization requires proper invalidation of data).&lt;/p&gt;
&lt;p&gt;The current &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo.cache&lt;/span&gt;&lt;/code&gt; module will remain available but be marked as
deprecated. The new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo.cache&lt;/span&gt;&lt;/code&gt; implementation will be provided side-by-side
for a period of time to allow time for any current consumers of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo.cache&lt;/span&gt;&lt;/code&gt;
to change-over to the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;dogpile.cache&lt;/span&gt;&lt;/code&gt; based implementation.&lt;/p&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo.cache&lt;/span&gt;&lt;/code&gt; will provide a fairly simple constructor to access/instantiate
the CacheRegion object(s) based upon the configuration built with
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo.cache&lt;/span&gt;&lt;/code&gt;. There will also be an option to extract the configuration
dictionary that can be directly passed to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;dogpile.cache&lt;/span&gt;&lt;/code&gt; if a developer
chooses to do so.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h3&gt;Security impact&lt;/h3&gt;
&lt;p&gt;No direct security implications. Use of the new caching module requires all
cached data to be properly invalidated (on change, etc). Stale data could
cause security related impact (and thus should be closely reviewed).&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;Ideally the performance impact of using caching should be only positive,
however maintenance of the cache coherency can have overhead when caching
is implemented.&lt;/p&gt;
&lt;p&gt;It is likely &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;dogpile.cache&lt;/span&gt;&lt;/code&gt; will have a better performance profile than
the current &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;MemoryCache&lt;/span&gt;&lt;/code&gt; module.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="configuration-impact"&gt;
&lt;h3&gt;Configuration Impact&lt;/h3&gt;
&lt;p&gt;New options for caching will be added. To leverage caching the configuration
for a service using &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo.cache&lt;/span&gt;&lt;/code&gt; will need to have the values set.&lt;/p&gt;
&lt;p&gt;By default caching will be disabled (can be overrided by a project) to ensure
that memory leaking / improper caching / negative performance impact waiting on
non-existent external services will not impact an OpenStack project.&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 become familiar with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;dogpile.cache&lt;/span&gt;&lt;/code&gt; and how to
implement usage of memoization and/or key-value-store regions.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Morgan Fainberg &amp;lt;mdrnstm&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Other contributors:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Michael Bayer
Flavio Percoco&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="milestones"&gt;
&lt;h3&gt;Milestones&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Target Milestone for completion:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Kilo-2&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;Convert &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo.cache&lt;/span&gt;&lt;/code&gt; module over to use &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;dogpile.cache&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Provide a clean / easy way to configure the cache region (in-memory
cache object that provides access to the key-value-store and memoization
decorators)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Ensure design allows for future expansion into cryptographic signing and/or
encryption of data stored within the key-value-store backend.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="incubation"&gt;
&lt;h2&gt;Incubation&lt;/h2&gt;
&lt;p&gt;Lifecycle will be incubation, and adoption in projects that leverage either
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;dogpile.cache&lt;/span&gt;&lt;/code&gt; directly (Keystone) or the oslo.MemoryCache module. Once
the interfaces are stable (and clearly documented) it is expected this module
can quickly move to graduation.&lt;/p&gt;
&lt;section id="adoption"&gt;
&lt;h3&gt;Adoption&lt;/h3&gt;
&lt;p&gt;Keystone will be the primary (first target) to adopt the new module (replacing
the custom &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;dogpile.cache&lt;/span&gt;&lt;/code&gt; implementation.&lt;/p&gt;
&lt;p&gt;The oslo.MemoryCache module will be updated to leverage the new &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo.cache&lt;/span&gt;&lt;/code&gt;
module.&lt;/p&gt;
&lt;p&gt;The direct use of the oslo.MemoryCache module will be deprecated in favor of
directly using &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo.cache&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="library"&gt;
&lt;h3&gt;Library&lt;/h3&gt;
&lt;p&gt;The Library will graduate into a top-level &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo.cache&lt;/span&gt;&lt;/code&gt; library.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="anticipated-api-stabilization"&gt;
&lt;h3&gt;Anticipated API Stabilization&lt;/h3&gt;
&lt;p&gt;I expect that this library should be able to stabilize within a single
development cycle. Adoption via incubator for Kilo and L, release as a library
in either K or L.&lt;/p&gt;
&lt;/section&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 on configuring the cache region will be required.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Developer documentation on implementing key-value-store and memoization
within an OpenStack project will be needed.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;All dependencies should already be in the global requirements. No external
blueprints should be needed.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This work is licensed under a Creative Commons Attribution 3.0
Unported License.
&lt;a class="reference external" href="http://creativecommons.org/licenses/by/3.0/legalcode"&gt;http://creativecommons.org/licenses/by/3.0/legalcode&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
</description><pubDate>Tue, 15 Jul 2014 00:00:00 </pubDate></item><item><title>OSprofiler cross service &amp;amp; project profiling</title><link>https://specs.openstack.org/openstack/oslo-specs/specs/mitaka/osprofiler-cross-service-project-profiling.html</link><description>

&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/oslo/+spec/osprofiler-cross-service-project-profiling"&gt;https://blueprints.launchpad.net/oslo/+spec/osprofiler-cross-service-project-profiling&lt;/a&gt;&lt;/p&gt;
&lt;section id="mission-statement"&gt;
&lt;h2&gt;Mission Statement&lt;/h2&gt;
&lt;p&gt;The OSprofiler is a distributed trace toolkit library. It provides pythonic
helpers to do trace generation to avoid repeated code to trace WSGI, RPC, DB,
and other important places… It also provides an interfaces for various
collection backends and helpers to parse data in and out of it.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem Description&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Background:&lt;/p&gt;
&lt;p&gt;OpenStack consists of multiple projects. Each project, in turn, is composed
of multiple services. To process some request, e.g. to boot a virtual
machine, OpenStack uses multiple services from different projects. In the
case something works too slowly, it’s extremely complicated to understand
what exactly goes wrong and to locate the bottleneck.&lt;/p&gt;
&lt;p&gt;To resolve this issue, we introduce a tiny but powerful library,
&lt;strong&gt;OSprofiler&lt;/strong&gt;, that could be used by all OpenStack projects and their
python clients. To be able to generate a single trace per request, that goes
through all involved services, and builds a tree of calls (see an
&lt;a class="reference external" href="http://boris-42.github.io/ngk.html"&gt;example&lt;/a&gt;).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For more details about how exactly OSprofiler works take a look at
&lt;a class="reference external" href="https://github.com/openstack/osprofiler/blob/master/README.rst"&gt;readme&lt;/a&gt;&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;OSprofiler is already used by Cinder, Heat, Glance and it is going
to be used by most of other projects like:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Nova &lt;a class="reference external" href="https://review.openstack.org/#/c/254703/"&gt;https://review.openstack.org/#/c/254703/&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;OpenStack Client &lt;a class="reference external" href="https://review.openstack.org/#/c/255861/"&gt;https://review.openstack.org/#/c/255861/&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Since currently OSprofiler is not under OpenStack umbrella in governance
&lt;a class="reference external" href="https://github.com/openstack/governance/blob/master/reference/projects.yaml"&gt;https://github.com/openstack/governance/blob/master/reference/projects.yaml&lt;/a&gt;
we are proposing the Oslo program should be home for OSprofiler.&lt;/p&gt;
&lt;p&gt;Further just like other oslo projects, we should have a core team just for
OSprofiler as well.&lt;/p&gt;
&lt;section id="implementation"&gt;
&lt;h3&gt;Implementation&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;How OSprofiler works&lt;/strong&gt; *&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;OSprofiler is very tiny library that allows you to create nested
traced. Basically it just keeps in memory stack (list) of elements.&lt;/p&gt;
&lt;p&gt;Each element has 3 trace id:&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;dl class="simple"&gt;
&lt;dt&gt;base_id     - all points of the same trace have same base_id, which helps&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;us to fetch all points related to some trace&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;parent_id  - parent’s point id&lt;/p&gt;
&lt;p&gt;current_id - current point’s id&lt;/p&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;And it has 2 methods start() and stop(), start() is pushing new elements
and calling driver’s notify method with payload, stop() is removing latest
element from stack and calling one more notify()&lt;/p&gt;
&lt;p&gt;This allows us to build tree of calls with durations and payload info:
Like &lt;a class="reference external" href="http://boris-42.github.io/ngk.html"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;For more details please
&lt;a class="reference external" href="https://github.com/openstack/osprofiler"&gt;read the docs&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;What is going to be used as a OSprofiler driver (trace collector)&lt;/strong&gt; *&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;OSprofiler is going to have multi drivers support. Which means
that basically any centralized system can be used to collect data.
Or even we can write trace information just to files.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As a first driver we are going to use oslo.messaging &amp;amp; Ceilometer&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In future OSprofiler team is going to add drivers for:
MongoDB, InfluxDB, ElasticSearch&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;OSprofiler integration points:&lt;/strong&gt; *&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Changes in projects configuration:&lt;/p&gt;
&lt;p&gt;Add config group “profiler” and 3 config options inside (in all projects):&lt;/p&gt;
&lt;p&gt;enabled = False     # Fully disable OSprofiler by default&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;trace_db = False    # Whatever trace DB requests or not. It is disabled&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;# by default, because there are too many DB  requests
# and tracing them is useful only for deep debugging.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;hmacs = SECRET_KEY  # HMAC keys that are used to sign HTTP headers&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;# that activate OSprofiler, this is used to
# block regular users to trigger OSProfiler.
# They must be the same for all projects.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;connection = None   # Connection string that specify which&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;# OSProfiler driver to use and credentials
# for specified backend. Like
# mongo://user:password@ip:port/schema&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Keep single trace between 2 projects:&lt;/p&gt;
&lt;p&gt;Add OSprofiler middleware to all pipelines in all paste.ini of all projects&lt;/p&gt;
&lt;p&gt;This middleware is initializing OSProfiler if there is special HTTP
header signed with proper HMAC key.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Keep single trace between 2 services of single project:&lt;/p&gt;
&lt;p&gt;If RPC caller has initialized profiler it should add special payload
to all RPC messages that contains trace information.
Callee process should initialize OSProfiler if it found such message.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Changes required in python clients&lt;/p&gt;
&lt;p&gt;There are 2 changes required in each python client:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;If profiler is enabled add profiler trace header, this will be used
when project A is calling project B API via python client.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;CLI argument –profile &amp;lt;HMAC&amp;gt; - that will initialize OSprofiler&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;What points should be tracked by default?&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;I think that for all projects we should include by default 5 kinds of points:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;All HTTP calls - helps to get information about: what HTTP requests were
done, duration of calls (latency of service), information about projects
involved in request.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;All RPC calls - helps to understand duration of parts of request related
to different services in one project. This information is essential to
understand which service produce the bottleneck.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;All DB API calls - in some cases slow DB query can produce bottleneck. So
it’s quite useful to track how much time request spend in DB layer.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;All driver layer calls - in case of nova, cinder and others we have vendor
drivers. (e.g. nova.virt.driver)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;All DB API layer calls (e.g. nova.db.api)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;All raw SQL requests (turned off by default, because it produce a lot of
traffic)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Any other import for specific project methods/classes/code pieces&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;** Points that should be tracked in future as well:**&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;All external commands.
For example, oslo.concurrency processutils.execute() calls.
Because the work done by external commands is a key part of many backend
API implementations and takes non-trivial time.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Worker threads spawned / run.
Some API calls will result in single-use background threads being spawned
to process some work asynchronously from the rest of the work.
I think it is important to be able to capture this work in traces,
by recording a trace when a thread start is requested, and then having
a trace in the start+end of the thread main method.&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="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Why not cProfile and other python tracer/debugger?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The scope of this library is quite different:&lt;/strong&gt;&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;It should create single trace that goes cross all services/projects&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It is more interesting to be able to collect data about specific points
in code instead of all methods&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;CProfiler like functionality can be integrated in future in OSprofiler&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;This library should be easy integratable with OpenStack. This means that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;It shouldn’t require too many changes in code bases of integrating
projects.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It should be simple to turn it off fully&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It should be possible to keep it turned on in lazy mode in production
(e.g. users that knows HMAC key can trace their requests).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What about Zipkin and other existing distributed tracing solutions?&lt;/p&gt;
&lt;p&gt;OSprofiler is small library that is used to provide no vendor lock-in
tracing solution for OpenStack.&lt;/p&gt;
&lt;p&gt;OSprofiler doesn’t intend to implement whole Zipkin like stack. It’s just
tiny library that is used integrate OpenStack with different collectors
and provide native OpenStack tracer/profiler that is not hard coded on any
tracing service (e.g. Zipkin).&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="impact-on-existing-apis"&gt;
&lt;h3&gt;Impact On Existing APIs&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;All API methods of all projects will accept 2 new headers:
X-Trace-Info and X-Trace-HMAC that will actually trigger profiler.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;dl class="simple"&gt;
&lt;dt&gt;All python clients will accept –profile key, that will actually put proper&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;X-Trace-Info and X-Trace-HMAC headers to HTTP request, and print trace id.&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;There is no need in any changes in any existing oslo libs at the moment.
If we decide to integrate OSprofiler to some of oslo libs we will do the
standard process of specs/pr/reviews in that specific lib.&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;OSprofiler is using HMAC to sign trace headers. Only the people who know the
secret key used for HMAC are able to trigger profiler.
As HMAC is quite secure there won’t be issues with security.&lt;/p&gt;
&lt;p&gt;Even in worse case, when attacker knows secret key, he will be able to trigger
profiler, that will make his request a bit slower, but won’t affect other
users.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;If it is turned off there is negligible performance overhead.
Just couple of “if None” checks&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If it is turned on, there are two different cases:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;No trace headers in request =&amp;gt; No performance impact&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;There is trace header:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Trace id is signed with wrong HMAC overhead on checking that trace id
is signed by proper HMAC key.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Trace id is signed with proper HMAC, overhead will depend on amount of
trace points and Notification API performance. For requests like
booting VM, creating Volumes it can be measurable, for simple requests
like showing details about resource it will be insignificant.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Trace every N request configuration (not done yet)&lt;/p&gt;
&lt;p&gt;In such configuration every N request will have OSprofiler overhead that
depends on many things: Amount of traced points (depends on API method),
OSprofiler backend, and other factors..&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="configuration-impact"&gt;
&lt;h3&gt;Configuration Impact&lt;/h3&gt;
&lt;p&gt;We are adding to all projects new CONF group options:&lt;/p&gt;
&lt;p&gt;[profiler]
#If False fully disable profiling feature.
#enabled = False&lt;/p&gt;
&lt;p&gt;# If False doesn’t trace SQL requests.
#trace_db = True&lt;/p&gt;
&lt;p&gt;# HMAC keys that are used to sign headers.
# Because OpenStack contains many projects we are not able to update all HMAC
# keys at the same point of time. To provide ability of no downtime rolling
# updates of HMAC keys (security reasons) we need ability to specify many HMACs
# The process of update OLDKey -&amp;gt; NEWKey will look like:
# 1) Initial system configuration:
#    ALL Services have OLDKey, users use OLDKey
# 2) in the middle 1:
#    All Services have OLDKey, part of them have both OLDKey and NEWKey, users
#    use OLDKey
# 3) in the middle 2:
#    All Services have OLDKey and NEWKey, users use NEWKey
# 4) in the middle 3:
#    Part of service have both keys and some of services have only NEWKey,
#    users use NEWKey
# 5) end system configuration:
#     All services have only NewKey
#hmacs = SECRET_KEY1, SECRET_KEY2&lt;/p&gt;
&lt;p&gt;# Profiler driver collector connection string.
connection = None&lt;/p&gt;
&lt;p&gt;By default OSprofiler is turned off. However it can be keep on in production,
because it doesn’t add any overhead until it is triggered and profiler can be
trigged only by person who knows HMAC key.&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 be able to profile OpenStack and fix different issues related
to performance and scale.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="id1"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;boris-42
dinabelova
harlowja
zhiyan&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="milestones"&gt;
&lt;h3&gt;Milestones&lt;/h3&gt;
&lt;p&gt;Mitaka-3&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;Remove from paste.ini OSprofiler configuration:
&lt;a class="reference external" href="https://github.com/openstack/osprofiler/blob/master/doc/specs/in-progress/make_paste_ini_config_optional.rst"&gt;https://github.com/openstack/osprofiler/blob/master/doc/specs/in-progress/make_paste_ini_config_optional.rst&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Multi backend support:
&lt;a class="reference external" href="https://github.com/openstack/osprofiler/blob/master/doc/specs/in-progress/multi_backend_support.rst"&gt;https://github.com/openstack/osprofiler/blob/master/doc/specs/in-progress/multi_backend_support.rst&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Move all projects to new multi backend model&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Integrate OSprofiler in all OpenStack projects&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Better integration testing:
&lt;a class="reference external" href="https://github.com/openstack/osprofiler/blob/master/doc/specs/in-progress/integration_testing.rst"&gt;https://github.com/openstack/osprofiler/blob/master/doc/specs/in-progress/integration_testing.rst&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Better DevStack integration:
&lt;a class="reference external" href="https://github.com/openstack/osprofiler/blob/master/doc/specs/in-progress/better_devstack_integration.rst"&gt;https://github.com/openstack/osprofiler/blob/master/doc/specs/in-progress/better_devstack_integration.rst&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Integrate Rally &amp;amp; OSprofiler&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="incubation"&gt;
&lt;h2&gt;Incubation&lt;/h2&gt;
&lt;section id="adoption"&gt;
&lt;h3&gt;Adoption&lt;/h3&gt;
&lt;p&gt;All projects and python clients should add quite small amount of code to
make it possible to do the cross project/service tracing.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="library"&gt;
&lt;h3&gt;Library&lt;/h3&gt;
&lt;p&gt;Code of OSprofiler library can be find here:
&lt;a class="reference external" href="https://github.com/openstack/osprofiler/"&gt;https://github.com/openstack/osprofiler/&lt;/a&gt;&lt;/p&gt;
&lt;/section&gt;
&lt;section id="anticipated-api-stabilization"&gt;
&lt;h3&gt;Anticipated API Stabilization&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;We should document in one place how to configure and use OSprofiler.&lt;/p&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;OSprofiler can be runtime dependency to python clients&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;OSprofiler should be in requirements of projects that are will use OSprofiler&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;OSprofiler lib: &lt;a class="reference external" href="https://github.com/stackforge/osprofiler"&gt;https://github.com/stackforge/osprofiler&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;OSprofiler specs: &lt;a class="reference external" href="https://github.com/openstack/osprofiler/tree/master/doc/specs"&gt;https://github.com/openstack/osprofiler/tree/master/doc/specs&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This work is licensed under a Creative Commons Attribution 3.0
Unported License.
&lt;a class="reference external" href="http://creativecommons.org/licenses/by/3.0/legalcode"&gt;http://creativecommons.org/licenses/by/3.0/legalcode&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
</description><pubDate>Tue, 01 Jul 2014 00:00:00 </pubDate></item><item><title>Fix the Import Cycle Between log and versionutils</title><link>https://specs.openstack.org/openstack/oslo-specs/specs/juno/fix-import-cycle-log-and-versionutils.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/oslo/+spec/fix-import-cycle-log-and-versionutils"&gt;https://blueprints.launchpad.net/oslo/+spec/fix-import-cycle-log-and-versionutils&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Break the import cycle so we can release oslo.log.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;There is a circular dependency between versionutils and the logging
code, which are slated to be released in separate libraries. We need
to break the cycle to allow oslo.log to graduate this cycle.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Move the &lt;code class="xref py py-meth docutils literal notranslate"&gt;&lt;span class="pre"&gt;ContextAdapter.deprecated()&lt;/span&gt;&lt;/code&gt; method to a function in
versionutils with the other deprecation-related code. That means
moving the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;fatal_deprecations&lt;/span&gt;&lt;/code&gt; configuration option, and updating
all callers.&lt;/p&gt;
&lt;p&gt;The proposed function signature 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="c1"&gt;# versionutils.py&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;deprecation_warning&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&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;kwds&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="sd"&gt;"""Call this function when a deprecated feature is used.&lt;/span&gt;

&lt;span class="sd"&gt;     If the system is configured for fatal deprecations then the message&lt;/span&gt;
&lt;span class="sd"&gt;     is logged at the 'critical' level and :class:`DeprecatedConfig` will&lt;/span&gt;
&lt;span class="sd"&gt;     be raised.&lt;/span&gt;

&lt;span class="sd"&gt;     Otherwise, the message will be logged (once) at the 'warn' level.&lt;/span&gt;

&lt;span class="sd"&gt;     :raises: :class:`DeprecatedConfig` if the system is configured for&lt;/span&gt;
&lt;span class="sd"&gt;              fatal deprecations.&lt;/span&gt;

&lt;span class="sd"&gt;     """&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;To maintain the current logging behavior, &lt;code class="xref py py-func docutils literal notranslate"&gt;&lt;span class="pre"&gt;deprecation_warning()&lt;/span&gt;&lt;/code&gt;
will look up the stack one level to get the module name, ask for the
logger with that name, and then use it to emit the message (instead of
having a single logger with the name of the versionutils module).&lt;/p&gt;
&lt;p&gt;Move &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;fatal_deprecations&lt;/span&gt;&lt;/code&gt; out of the default option group to the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;deprecation&lt;/span&gt;&lt;/code&gt; group, with appropriate deprecation settings to honor
the old name if it is found.&lt;/p&gt;
&lt;p&gt;Update &lt;code class="xref py py-func docutils literal notranslate"&gt;&lt;span class="pre"&gt;versionutils.deprecated()&lt;/span&gt;&lt;/code&gt; to call
&lt;code class="xref py py-func docutils literal notranslate"&gt;&lt;span class="pre"&gt;deprecation_warning()&lt;/span&gt;&lt;/code&gt; instead of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;LOG.deprecated()&lt;/span&gt;&lt;/code&gt;.&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;Change the implementation of the deprecated() decorator in
versionutils to not call LOG.deprecated(). That might mean
duplicating the logic from LOG.deprecated().&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Move most of the body of LOG.deprecated() to versionutils but
keep the method. This limits the number of changes we have to make
in the callers, but means that oslo.log depends on
oslo.versionutils. We can eliminate the circular dependency by
having the function in versionutils use python’s standard logger
instead of oslo.log.  This seems to be in keeping with the API
changes for oslo.log above.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Both alternative solutions fix the cycle, but require that we keep
LOG.deprecated() and our special ContextAdapter. We are trying to
remove that class in another blueprint related to graduating oslo.log.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="impact-on-existing-apis"&gt;
&lt;h3&gt;Impact on Existing APIs&lt;/h3&gt;
&lt;p&gt;Callers of LOG.deprecated() will need to be updated to use
&lt;code class="xref py py-func docutils literal notranslate"&gt;&lt;span class="pre"&gt;versionutils.deprecation_warning()&lt;/span&gt;&lt;/code&gt; instead.&lt;/p&gt;
&lt;p&gt;For backwards compatibility and slow adopters, we will keep
ContextAdapter.deprecated() in the log setup code in the incubator but
it will be removed from &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oslo.log&lt;/span&gt;&lt;/code&gt; when that module graduates.&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="performance-impact"&gt;
&lt;h3&gt;Performance Impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="configuration-impact"&gt;
&lt;h3&gt;Configuration Impact&lt;/h3&gt;
&lt;p&gt;Move &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;fatal_deprecations&lt;/span&gt;&lt;/code&gt; out of the default option group to the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;versionutils&lt;/span&gt;&lt;/code&gt; group.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer Impact&lt;/h3&gt;
&lt;p&gt;The API for reporting deprecated code and features will be moving to a
new place, so we will need to publicize the change. The apps can be
updated when syncing changes to the logging and versionutils code from
the incubator.&lt;/p&gt;
&lt;p&gt;Most callers use the &lt;code class="xref py py-func docutils literal notranslate"&gt;&lt;span class="pre"&gt;deprecated()&lt;/span&gt;&lt;/code&gt; decorator instead anyway.&lt;/p&gt;
&lt;p&gt;Calls to update:&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;oslo&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;incubator&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;tests&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;unit&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;test_deprecated&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;py&lt;/span&gt;
&lt;span class="mi"&gt;38&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_deprecated&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="mi"&gt;39&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;        &lt;span class="n"&gt;LOG&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;deprecated&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'test'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mi"&gt;54&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;        &lt;span class="n"&gt;LOG&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;deprecated&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'only once!'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mi"&gt;55&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;        &lt;span class="n"&gt;LOG&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;deprecated&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'only once!'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mi"&gt;56&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;        &lt;span class="n"&gt;LOG&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;deprecated&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'only once!'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mi"&gt;65&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;        &lt;span class="n"&gt;LOG&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;deprecated&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mi"&gt;66&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;        &lt;span class="n"&gt;LOG&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;deprecated&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mi"&gt;67&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;        &lt;span class="n"&gt;LOG&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;deprecated&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mi"&gt;68&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;        &lt;span class="n"&gt;LOG&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;deprecated&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mi"&gt;69&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;        &lt;span class="n"&gt;LOG&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;deprecated&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mi"&gt;70&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;        &lt;span class="n"&gt;LOG&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;deprecated&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mi"&gt;83&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;        &lt;span class="n"&gt;LOG&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;deprecated&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'only once! &lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'arg1'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mi"&gt;84&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;        &lt;span class="n"&gt;LOG&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;deprecated&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'only once! &lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'arg1'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mi"&gt;85&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;        &lt;span class="n"&gt;LOG&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;deprecated&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'only once! &lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'arg2'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mi"&gt;86&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;        &lt;span class="n"&gt;LOG&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;deprecated&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'only once! &lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'arg2'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mi"&gt;108&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;        &lt;span class="n"&gt;LOG&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;deprecated&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg_fmt_1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;msg_fmt_1_arg_1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mi"&gt;109&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;        &lt;span class="n"&gt;LOG&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;deprecated&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg_fmt_1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;msg_fmt_1_arg_2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# logged: args different&lt;/span&gt;
&lt;span class="mi"&gt;110&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;        &lt;span class="n"&gt;LOG&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;deprecated&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg_fmt_1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;msg_fmt_1_arg_1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# no log: same msg+args&lt;/span&gt;
&lt;span class="mi"&gt;112&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;        &lt;span class="n"&gt;LOG&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;deprecated&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg_fmt_2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;msg_fmt_2_arg_1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mi"&gt;113&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;        &lt;span class="n"&gt;LOG&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;deprecated&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg_fmt_2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;msg_fmt_2_arg_2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# logged: args different&lt;/span&gt;
&lt;span class="mi"&gt;114&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;        &lt;span class="n"&gt;LOG&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;deprecated&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg_fmt_2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;msg_fmt_2_arg_3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# logged: args different&lt;/span&gt;
&lt;span class="mi"&gt;115&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;        &lt;span class="n"&gt;LOG&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;deprecated&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg_fmt_2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;msg_fmt_2_arg_3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# no log: same msg+args&lt;/span&gt;
&lt;span class="mi"&gt;116&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;        &lt;span class="n"&gt;LOG&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;deprecated&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg_fmt_2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;msg_fmt_2_arg_2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# no log: same msg+args&lt;/span&gt;

&lt;span class="n"&gt;cinder&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;cinder&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;contrib&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;services&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;py&lt;/span&gt;
&lt;span class="mi"&gt;91&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;            &lt;span class="n"&gt;LOG&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;deprecated&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="s2"&gt;"Query by service parameter is deprecated. "&lt;/span&gt;

&lt;span class="n"&gt;cinder&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;cinder&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;quota&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;py&lt;/span&gt;
&lt;span class="mi"&gt;106&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;                &lt;span class="n"&gt;LOG&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;deprecated&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="s2"&gt;"Default quota for resource: &lt;/span&gt;&lt;span class="si"&gt;%(res)s&lt;/span&gt;&lt;span class="s2"&gt; is set "&lt;/span&gt;

&lt;span class="n"&gt;cinder&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;cinder&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;scheduler&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;manager&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;py&lt;/span&gt;
&lt;span class="mi"&gt;66&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;            &lt;span class="n"&gt;LOG&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;deprecated&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;'ChanceScheduler and SimpleScheduler have been '&lt;/span&gt;

&lt;span class="n"&gt;neutron&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;neutron&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;plugins&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;vmware&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;nsx_cluster&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;py&lt;/span&gt;
&lt;span class="mi"&gt;49&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;            &lt;span class="n"&gt;LOG&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;deprecated&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="s2"&gt;"Attribute '&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s2"&gt;' has been deprecated or moved "&lt;/span&gt;

&lt;span class="n"&gt;neutron&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;neutron&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;agent&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;common&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;py&lt;/span&gt;
&lt;span class="mi"&gt;104&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;        &lt;span class="n"&gt;LOG&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;deprecated&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;'DEFAULT.root_helper is deprecated! Please move '&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;glance&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;store&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="fm"&gt;__init__&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;py&lt;/span&gt;
&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;                &lt;span class="n"&gt;LOG&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;deprecated&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="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s2"&gt; not found in `known_store`. "&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Searching for uses:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;$ ack --ignore-dir=.tox --ignore-dir=build --ignore-dir=.venv \
--ignore-dir=.update-venv --ignore-dir=openstack 'deprecated\('

python-keystoneclient/keystoneclient/tests/test_discovery.py
673:    def test_allow_deprecated(self):

python-keystoneclient/keystoneclient/tests/test_http.py
136:    def test_client_deprecated(self):

keystone/keystone/catalog/backends/templated.py
128:@versionutils.deprecated(

keystone/keystone/contrib/stats/core.py
130:    @versionutils.deprecated(

keystone/keystone/contrib/access/core.py
35:    @versionutils.deprecated(

keystone/keystone/middleware/s3_token.py
50:    @versionutils.deprecated(

keystone/keystone/middleware/core.py
148:    @versionutils.deprecated(

keystone/keystone/auth/plugins/external.py
102:    @versionutils.deprecated(
113:    @versionutils.deprecated(
130:    @versionutils.deprecated(
151:    @versionutils.deprecated(

keystone/keystone/token/core.py
263:    @versionutils.deprecated(versionutils.deprecated.ICEHOUSE, remove_in=+1)

keystone/keystone/common/controller.py
33:def v2_deprecated(f):
42:        v2_deprecated = versionutils.deprecated(

keystone/keystone/common/kvs/legacy.py
49:    @versionutils.deprecated(versionutils.deprecated.ICEHOUSE,

keystone/vendor/python-keystoneclient-master/keystoneclient/tests/test_http.py
136:    def test_client_deprecated(self):

oslo-incubator/tests/unit/test_versionutils.py
24:    def assert_deprecated(self, mock_log, **expected_details):
35:        @versionutils.deprecated(as_of=versionutils.deprecated.ICEHOUSE)
48:            @versionutils.deprecated(as_of=versionutils.deprecated.ICEHOUSE)
59:        @versionutils.deprecated(as_of=versionutils.deprecated.ICEHOUSE,
66:        self.assert_deprecated(mock_log,
75:        @versionutils.deprecated(as_of=versionutils.deprecated.GRIZZLY,
82:        self.assert_deprecated(mock_log,
91:        @versionutils.deprecated(as_of=versionutils.deprecated.GRIZZLY)
97:        self.assert_deprecated(mock_log,
105:        @versionutils.deprecated(as_of=versionutils.deprecated.GRIZZLY,
113:        self.assert_deprecated(mock_log,
122:        @versionutils.deprecated(as_of=versionutils.deprecated.GRIZZLY,
129:        self.assert_deprecated(mock_log,
137:        @versionutils.deprecated(as_of=versionutils.deprecated.GRIZZLY,
144:        self.assert_deprecated(mock_log,

oslo-incubator/tests/unit/test_log.py
600:    def test_logfile_deprecated(self):
610:    def test_logdir_deprecated(self):

oslo-incubator/tests/unit/test_deprecated.py
38:    def test_deprecated(self):
39:        LOG.deprecated('test')
54:        LOG.deprecated('only once!')
55:        LOG.deprecated('only once!')
56:        LOG.deprecated('only once!')
65:        LOG.deprecated(msg1)
66:        LOG.deprecated(msg2)
67:        LOG.deprecated(msg1)
68:        LOG.deprecated(msg1)
69:        LOG.deprecated(msg2)
70:        LOG.deprecated(msg2)
83:        LOG.deprecated('only once! %s', 'arg1')
84:        LOG.deprecated('only once! %s', 'arg1')
85:        LOG.deprecated('only once! %s', 'arg2')
86:        LOG.deprecated('only once! %s', 'arg2')
108:        LOG.deprecated(msg_fmt_1, msg_fmt_1_arg_1)
109:        LOG.deprecated(msg_fmt_1, msg_fmt_1_arg_2)  # logged: args different
110:        LOG.deprecated(msg_fmt_1, msg_fmt_1_arg_1)  # no log: same msg+args
112:        LOG.deprecated(msg_fmt_2, msg_fmt_2_arg_1)
113:        LOG.deprecated(msg_fmt_2, *msg_fmt_2_arg_2)  # logged: args different
114:        LOG.deprecated(msg_fmt_2, *msg_fmt_2_arg_3)  # logged: args different
115:        LOG.deprecated(msg_fmt_2, *msg_fmt_2_arg_3)  # no log: same msg+args
116:        LOG.deprecated(msg_fmt_2, *msg_fmt_2_arg_2)  # no log: same msg+args

cinder/cinder/api/contrib/services.py
91:            LOG.deprecated(_("Query by service parameter is deprecated. "

cinder/cinder/quota.py
106:                LOG.deprecated(_("Default quota for resource: %(res)s is set "

cinder/cinder/scheduler/manager.py
66:            LOG.deprecated(_('ChanceScheduler and SimpleScheduler have been '

oslo.config/tests/test_cfg.py
654:    def test_conf_file_str_value_override_use_deprecated(self):
1086:    def test_conf_file_dict_values_override_deprecated(self):
1106:    def test_conf_file_dict_deprecated(self):
1232:    def test_conf_file_multistr_values_append_deprecated(self):
1271:    def test_conf_file_multistr_deprecated(self):

neutron/neutron/plugins/vmware/nsx_cluster.py
49:            LOG.deprecated(_("Attribute '%s' has been deprecated or moved "

neutron/neutron/agent/common/config.py
104:        LOG.deprecated(_('DEFAULT.root_helper is deprecated! Please move '

heat/heat/tests/test_neutron_loadbalancer.py
429:    def test_create_deprecated(self):

heat/heat/tests/test_neutron_vpnservice.py
201:    def test_create_deprecated(self):

heat/heat/tests/test_parser.py
759:    def test_stack_resolve_runtime_data_deprecated(self):

heat/heat/tests/test_engine_service.py
1950:    def test_list_resource_types_deprecated(self):

heat/heat/tests/test_neutron.py
914:    def test_subnet_deprecated(self):
1387:    def test_router_interface_deprecated(self):
1801:    def test_floating_ip_deprecated(self):

heat/heat/tests/test_neutron_network_gateway.py
233:    def test_network_gateway_create_deprecated(self):

os-refresh-config/os_refresh_config/tests/test_os_refresh_config.py
27:    def test_default_base_dir_deprecated(self):

glance/glance/store/__init__.py
200:                LOG.deprecated(_("%s not found in `known_store`. "

os-apply-config/os_apply_config/tests/test_apply_config.py
293:    def test_default_templates_dir_deprecated(self):
298:    def test_default_templates_dir_old_deprecated(self):
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Doug Hellmann (doug-hellmann)&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="milestones"&gt;
&lt;h3&gt;Milestones&lt;/h3&gt;
&lt;p&gt;Target Milestone for completion: Juno-1&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;Move &lt;code class="xref py py-meth docutils literal notranslate"&gt;&lt;span class="pre"&gt;ContextAdapter.deprecated()&lt;/span&gt;&lt;/code&gt; to
&lt;code class="xref py py-func docutils literal notranslate"&gt;&lt;span class="pre"&gt;deprecation_warning()&lt;/span&gt;&lt;/code&gt; and update the implementation.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Move location of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;fatal_deprecations&lt;/span&gt;&lt;/code&gt; option definition and the
group where it is registered.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update Cinder.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update Neutron.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update Glance.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="incubation"&gt;
&lt;h2&gt;Incubation&lt;/h2&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;section id="adoption"&gt;
&lt;h3&gt;Adoption&lt;/h3&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;section id="library"&gt;
&lt;h3&gt;Library&lt;/h3&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;section id="anticipated-api-stabilization"&gt;
&lt;h3&gt;Anticipated API Stabilization&lt;/h3&gt;
&lt;p&gt;This new API should be stable enough that oslo.versionutils can graduate.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;The configuration option is moving to a new group, so the sample
config files and config tables generated in the documentation will
need to be updated.&lt;/p&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="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Discussion at Juno summit: &lt;a class="reference external" href="https://etherpad.openstack.org/p/juno-oslo-release-plan"&gt;https://etherpad.openstack.org/p/juno-oslo-release-plan&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This work is licensed under a Creative Commons Attribution 3.0
Unported License.
&lt;a class="reference external" href="http://creativecommons.org/licenses/by/3.0/legalcode"&gt;http://creativecommons.org/licenses/by/3.0/legalcode&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
</description><pubDate>Fri, 23 May 2014 00:00:00 </pubDate></item></channel></rss>