<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0"><channel><title>zaqar-specs</title><link>https://specs.openstack.org/openstack/zaqar-specs</link><description /><copyright>2021, OpenStack Foundation</copyright><item><title>Remove V1 API Code From Zaqar</title><link>https://specs.openstack.org/openstack/zaqar-specs/specs/yoga/remove-v1-api-code-from-zaqar.html</link><description>
 
&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/zaqar/+spec/remove-v1-api-code"&gt;https://blueprints.launchpad.net/zaqar/+spec/remove-v1-api-code&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Now there is no need for V1 APIs, its old and could be completely replaced by V2 APIs.
So it’s time to remove it from the code tree. This action is first one of steps to optimize
Zaqar’s codes and functions.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Currently, Zaqar has tree versions of APIs, V1, V1_1 and V2. The V1 is the oldest apis that
there is no need for them right now. All new features are implemented under V2 APIs. So
its time to remove V1 APIs and optimize the Zaqar’s codes.&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;Remove all V1 APIs codes and change the basic APIs to V1_1.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Clean the unit tests and tempest tests about V1 APIs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Modify the API doc according the changes.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;section id="api-impact"&gt;
&lt;h3&gt;API Impact&lt;/h3&gt;
&lt;p&gt;The whole V1 APIs code will be removed from Zaqar’s service.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="drawbacks"&gt;
&lt;h3&gt;Drawbacks&lt;/h3&gt;
&lt;p&gt;If someone are still using V1 APIs, they must change the API version to
V1_1 or V2(best to V2) after Yoga release.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;wanghao &amp;lt;&lt;a class="reference external" href="mailto:sxmatch1986%40gmail.com"&gt;sxmatch1986&lt;span&gt;@&lt;/span&gt;gmail&lt;span&gt;.&lt;/span&gt;com&lt;/a&gt;&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Secondary assignee:&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;Yoga M-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;Remove V1 api and transport code.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Remove unit and functional tests for V1.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add release note for this feature.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update API reference according those changes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Change tempest tests accordingly.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;remove client support.&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="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
</description><pubDate>Tue, 16 Nov 2021 00:00:00 </pubDate></item><item><title>Support Extra Specs to Subscription-confirming</title><link>https://specs.openstack.org/openstack/zaqar-specs/specs/wallaby/support-extra-specs-to-subscription-confirming.html</link><description>
 
&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/zaqar/+spec/support-extra-specs-to-subscription-confirming"&gt;https://blueprints.launchpad.net/zaqar/+spec/support-extra-specs-to-subscription-confirming&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This requirement came from a true scenariowhen people use the subscription
function of Zaqar, for example, text messages, they need to return some extra
information like message authentication code in confirming process.
Now Zaqar still cant support it, that will impact the usage of subscription.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Currently, Zaqar can’t support extra information in subscription
confirming process. This will block user to input information that
is needed when subcription is confirming. There is a true case that
came from Zaqar’s user. They want to input the message authentication
code into Zaqar when the subscription is confirming, the code will be
used to identify the subscriber. So Zaqar should support this kind of
mechanism.&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;Introduce a key-value called “extra_spec” in confirming request body.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Introduce a driver mechanism to let vendors to implement what they
want to do with extra_spec information.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;section id="api-impact"&gt;
&lt;h3&gt;API Impact&lt;/h3&gt;
&lt;p&gt;Subscription confirming request:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;PUT&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;v2&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;subscriptions&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;subscription_id&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;confirm&lt;/span&gt;

  &lt;span class="n"&gt;RESPONSE&lt;/span&gt; &lt;span class="n"&gt;CODE&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;204&lt;/span&gt;
  &lt;span class="n"&gt;REQUEST&lt;/span&gt; &lt;span class="n"&gt;BODY&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;"confirmed"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"extra_spec"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"message_authentication_code"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"xxxxxx"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="drawbacks"&gt;
&lt;h3&gt;Drawbacks&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;wanghao &amp;lt;&lt;a class="reference external" href="mailto:sxmatch1986%40gmail.com"&gt;sxmatch1986&lt;span&gt;@&lt;/span&gt;gmail&lt;span&gt;.&lt;/span&gt;com&lt;/a&gt;&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Secondary assignee:&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;wallaby M-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;Modify api and transport code.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add driver mechanism to handler the extra spec.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add release note for this feature.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update API reference.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Change unit, functional and tempest tests accordingly.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add client support.&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="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
</description><pubDate>Tue, 12 Jan 2021 00:00:00 </pubDate></item><item><title>Query Queues With Count</title><link>https://specs.openstack.org/openstack/zaqar-specs/specs/ussuri/query-queues-with-count.html</link><description>
 
&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/zaqar/+spec/query-queues-with-count"&gt;https://blueprints.launchpad.net/zaqar/+spec/query-queues-with-count&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This will support query queues with ‘with_count=true’ filter, Zaqar will return
the amount of queues in backend storage. This feature will be very convenient
to users to know how many resources they own.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Currently, Zaqar can’t return the amount of queues when querying the queue.
It depends on users themselves to calculate the number one by one. For other
clients or applications also need to do it after invoking Zaqar’s API. Its
quite inconvenient for users or developers.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Add a new query filter item named &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;with_count&lt;/span&gt;&lt;/code&gt;, default value is &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;False&lt;/span&gt;&lt;/code&gt;.
When querying queues with “with_count=true” in url, Zaqar will add the
function to calculate total number of queus in backend storage and
return the amount of queues in response body like “count=100”.&lt;/p&gt;
&lt;section id="api-impact"&gt;
&lt;h3&gt;API Impact&lt;/h3&gt;
&lt;p&gt;Query queue list:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;GET: /v2/queues?with_count=true

  RESPONSE CODE: 200
  RESPONSE BODY:
  {
    "count": 100,
    "queues": [...]
  }
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="drawbacks"&gt;
&lt;h3&gt;Drawbacks&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;wanghao &amp;lt;&lt;a class="reference external" href="mailto:sxmatch1986%40gmail.com"&gt;sxmatch1986&lt;span&gt;@&lt;/span&gt;gmail&lt;span&gt;.&lt;/span&gt;com&lt;/a&gt;&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Secondary assignee:&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;ussuri RC2&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Modify transport code.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add release note for this feature.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update API reference.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Change unit, functional and tempest tests accordingly.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add client support.&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="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
</description><pubDate>Thu, 04 Jun 2020 00:00:00 </pubDate></item><item><title>Encrypted Messages in Queue</title><link>https://specs.openstack.org/openstack/zaqar-specs/specs/victoria/encrypted-messages-in-queue.html</link><description>
 
&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/zaqar/+spec/encrypted-messages-in-queue"&gt;https://blueprints.launchpad.net/zaqar/+spec/encrypted-messages-in-queue&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The queue in Zaqar will support to encrypt messages before storing them into
storage backends, also could support to decrypt (or not) messages when those
are claimed by consumer. This feature will enhance the security of messaging
service.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Currently, Zaqar can’t encrypt any messages and just store those messages into
storage backends. That’ll bring some security issues like information leakage
or hacker attack.&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;Add one new metadata in queue object that will indicate how to
encrypt messages:&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;“_enable_encrypt_messages=true/false” : this will tell Zaqar whether encrypt
messages before storing them into backends or not.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;ol class="arabic simple" start="2"&gt;
&lt;li&gt;&lt;p&gt;Support to use algorithms to encrypt messages in transport layer before
storing them into backends. In V cycle, Zaqar may just support the global
key for encryption and decryption, and it will be held by Zaqar service.
Users don’t need to encrypt/decypt message by themselves.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Go a step further, Zaqar also could support to let user upload their public
key and hold the private key by themselves. In this case, Zaqar just need to
encrypt the message by using public key and return the encrypted messages to
user.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;About the algorithms, in V cycle, Zaqar will introduce the AES-256
encryption at first. In next cycles, Zaqar can suppot asymmetric
encryption to let user upload public key and keep the private key
by their own.&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;About the option of encryption algorithms and keys, Zaqar would support
specify them throught more metadatas of queues, but it will be done in next
serveral cycles. In Victoria, we will choose one algorithm (like AES256) to
support and support to storage the keys by Zaqar itself or other
service like Barbican.&lt;/p&gt;
&lt;/div&gt;
&lt;section id="api-impact"&gt;
&lt;h3&gt;API Impact&lt;/h3&gt;
&lt;p&gt;Create queue list:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;POST&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;v2&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;queues&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;queue_name&lt;/span&gt;

  &lt;span class="n"&gt;RESPONSE&lt;/span&gt; &lt;span class="n"&gt;CODE&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;
  &lt;span class="n"&gt;REQUEST&lt;/span&gt; &lt;span class="n"&gt;BODY&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;"_enable_encrypt_messages"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;true&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="drawbacks"&gt;
&lt;h3&gt;Drawbacks&lt;/h3&gt;
&lt;p&gt;The ecryption algorithms will impact the performance of storing
messages into backends
and getting the messages from the queue.&lt;/p&gt;
&lt;p&gt;This depends on which kind of encryption algorithms we choose and support.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;wanghao &amp;lt;&lt;a class="reference external" href="mailto:sxmatch1986%40gmail.com"&gt;sxmatch1986&lt;span&gt;@&lt;/span&gt;gmail&lt;span&gt;.&lt;/span&gt;com&lt;/a&gt;&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Secondary assignee:&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;victoria M-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;Modify api and transport code.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add support for encryption algorithm and key management.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add release note for this feature.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update API reference.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Change unit, functional and tempest tests accordingly.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add client support.&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="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
</description><pubDate>Thu, 04 Jun 2020 00:00:00 </pubDate></item><item><title>Make FIFO guarantee optional</title><link>https://specs.openstack.org/openstack/zaqar-specs/specs/kilo/fifo-optional.html</link><description>
 
&lt;p&gt;FIFO has been one of Zaqar’s most wanted guarantees. Besides
reliability, durability and other latency requirements, users have
always requested FIFO to be there. This feature, however, has proven
to be an issue for some scenarios that don’t necessarily require it,
hence this proposal.&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/zaqar/+spec/make-fifo-optional"&gt;https://blueprints.launchpad.net/zaqar/+spec/make-fifo-optional&lt;/a&gt;&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;FIFO, despite being a great guarantee to have, brings in some scale
and performance issues that Zaqar is not willing to accept as the
default behavior. This spec proposes making FIFO optional and letting
drivers capable of supporting such scenario to do so.&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, as stated in previous sections, is to make FIFO
optional. It is possible to do so through &lt;cite&gt;flavors&lt;/cite&gt;.&lt;/p&gt;
&lt;p&gt;Not all store drivers are capable of supporting FIFO but those who
are, will have FIFO listed in their supported capabilities and such
capabilities will be exposed through the &lt;cite&gt;flavors&lt;/cite&gt; ones. However, it’s
not as straightforward as it seems. See the &lt;a class="reference internal" href="#work-items"&gt;Work Items&lt;/a&gt; section for
a list of required changes that will make this possible.&lt;/p&gt;
&lt;section id="drawbacks"&gt;
&lt;h3&gt;Drawbacks&lt;/h3&gt;
&lt;p&gt;As a side effect of this change, we’ll have to relax the delivery
guarantee for pub-sub. The reason being that walking through the queue
won’t prevent consumers to skip messages.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Keep it as is&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Remove FIFO completely&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: flaper87&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: K-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;dl class="simple"&gt;
&lt;dt&gt;Allow driver to expose what features they support&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Each driver supporst a set of features and this set needs to be accessible
from the upper layers&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/li&gt;
&lt;li&gt;&lt;dl class="simple"&gt;
&lt;dt&gt;Standardize the &lt;em&gt;supported&lt;/em&gt; capabilities&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Make a list of supported capabilities&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/li&gt;
&lt;li&gt;&lt;dl class="simple"&gt;
&lt;dt&gt;Add a way to pass capabilities down to the driver&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;We can do this when the driver is initialized since we know what the
capabilities are at that time.&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Support both, FIFO and non-FIFO, post methods.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://review.opendev.org/#/c/126531/"&gt;https://review.opendev.org/#/c/126531/&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, 13 May 2019 00:00:00 </pubDate></item><item><title>Persistent transport</title><link>https://specs.openstack.org/openstack/zaqar-specs/specs/kilo/persistent-transport.html</link><description>
 
&lt;p&gt;Persistent connections allow a single TCP connection to send and receive
multiple requests/responses instead of opening a new TCP connection for
each pair. When an application opens fewer TCP connections and keeps them
open for a longer period, it causes less network traffic, use less time
establishing new connections, and allows the TCP protocol to work more
efficiently.&lt;/p&gt;
&lt;p&gt;Currently Zaqar has support for a non-persistent transport, leaving aside
some use cases that would be covered in a more efficient and reliable way
with a persistent transport solution.&lt;/p&gt;
&lt;p&gt;Some use cases that will be positively impacted by this change are:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Communication with browsers: Websockets will enhance the communication
between browsers and Zaqar, a key factor in the integration of Zaqar with
the OpenStack Dashboard (Horizon).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Notifications: this type of transport will constitute a better protocol
for notifications, a feature planned for Kilo as well.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/zaqar/+spec/persistent-transport"&gt;https://blueprints.launchpad.net/zaqar/+spec/persistent-transport&lt;/a&gt;&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Currently there is no way to establish persistent connections in Zaqar.
This spec proposes adding this feature through a websockets implementation.&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, as stated in previous sections, is to add a persistent
transport alternative to Zaqar. This can be done by using websockets.&lt;/p&gt;
&lt;p&gt;Websockets provide a full-duplex communication channel operating over a single
socket that will remove overhead and significantly reduce complexity.&lt;/p&gt;
&lt;p&gt;Currently the tranport layer in Zaqar is tightly bound to the WSGI transport,
making this addition a complex task.&lt;/p&gt;
&lt;section id="fallback"&gt;
&lt;h3&gt;Fallback&lt;/h3&gt;
&lt;p&gt;In case WebSockets are not available, the client will fallback to short-polling
the REST API.&lt;/p&gt;
&lt;p&gt;Some of the reasons of WebSockets not being available are:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Firewalls could be configured to kill HTTP connections after a certain
amount of time.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Concerns from a security standpoint will lead to killing any traffic
over port 80 or 443 that doesn’t look like HTTP.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="messages-serialization"&gt;
&lt;h3&gt;Messages serialization&lt;/h3&gt;
&lt;p&gt;A serialization technology is needed in order to transport data. There are
several alternatives, including MsgPack, Protobuf, Apache Avro and Cap’n Proto.&lt;/p&gt;
&lt;p&gt;Given that a high priority is being given to browsers compatibility, MsgPack
is the best choice between those. Remaining alternatives doesn’t have
out-of-the-box Javascript support, making it harder to ensure compatibility
with most web applications.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Establish persistent connections enabling WSGI keep-alive&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Long polling&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: vkmc&lt;/p&gt;
&lt;p&gt;Secondary assignee: cpallares&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: &amp;lt; K-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;Implement the common API layer&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Define the wire protocol for persistent transports&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Implement the driver&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Implement queues and messages controller&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Implement claims controller&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Implement pools, flavors and stats controllers&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="websocket-libraries"&gt;
&lt;h3&gt;WebSocket Libraries&lt;/h3&gt;
&lt;p&gt;After discussing several alternatives, including SockJS, SocketIO, Autobahn,
ws4py and Tornado, it has been decided that ws4py is going to be used to
implement this feature. More details on this decision will be available in
the &lt;a class="reference external" href="https://wiki.openstack.org/wiki/Zaqar/specs/websockets"&gt;WebSockets wiki&lt;/a&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://review.opendev.org/#/c/122425/"&gt;https://review.opendev.org/#/c/122425/&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/zaqar/+spec/cross-transport-api-spec"&gt;https://blueprints.launchpad.net/zaqar/+spec/cross-transport-api-spec&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, 13 May 2019 00:00:00 </pubDate></item><item><title>Mistral Notifications</title><link>https://specs.openstack.org/openstack/zaqar-specs/specs/newton/mistral-notifications.html</link><description>
 
&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/zaqar/+spec/mistral-notifications"&gt;https://blueprints.launchpad.net/zaqar/+spec/mistral-notifications&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Allow a message to a Zaqar queue to trigger a Mistral workflow via the Zaqar
notification mechanism.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Developers of cloud applications expect to be able to build autonomous
applications in the cloud. That is to say, applications that manage themselves
by accessing the APIs of the cloud to manipulate their own infrastructure.
(Examples of this include autoscaling and autorecovery.) This is one of the
primary differences between a cloud platform and a simple virtualisation
platform (the other being multi-tenancy). There are two parts to this that
require integration, which is the purpose of this blueprint.&lt;/p&gt;
&lt;p&gt;The first is that the application must be able to receive information from the
cloud. An example of this would be an Aodh alarm indicating that a server is
overutilised. These notifications must be asynchronous, since the cloud is
multitenant and cannot block waiting for any one user application to
acknowledge it. They must also exhibit queueing semantics with at-least-once
delivery and high durability, since the application may become unreliable if it
misses notifications from the cloud. Not coincidentally, Zaqar offers exactly
these semantics in a public, Keystone-authenticated API that is accessible to
applications, and is therefore a natural choice. For this reason, a number of
OpenStack projects have already started dispatching user notifications to Zaqar
and more are expected in the near future. Already Aodh alarms support Zaqar as
a target, and Heat can push stack and resources events as well as notifications
about user hooks being triggered to Zaqar.&lt;/p&gt;
&lt;p&gt;The second is that the application must be able to perform arbitrary, and
arbitrarily-complex actions. This is because in practice the Right Thing to do
in cases like autoscaling and autorecovery is application-specific. There is
also an entire universe of application-specific actions that a user might want
to create. Of course an application can run these actions on a server
provisioned with Nova, but this generally makes things more complex (and
usually more expensive) than they need to be. For example, it is very hard to
host autorecovery code on the servers that are being autorecovered themselves
and still be reliable. Finally, OpenStack makes it difficult to provide
appropriate Keystone credentials to servers provisioned with Nova. &lt;a class="reference external" href="https://wiki.openstack.org/wiki/Mistral"&gt;Mistral&lt;/a&gt;
solves these problems by providing a lightweight, multi-tenant way of reliably
running potentially long-running processes, with access to the OpenStack APIs
as well as a number of other actions (some of which, like sending email and
webhooks, are similar to Zaqar’s notifications).&lt;/p&gt;
&lt;p&gt;The missing link to build fully autonomous applications is for messages
(potentially, but not necessarily originating from the OpenStack cloud itself)
on Zaqar queues to be able to trigger Mistral workflows (potentially, but not
necessarily calling other OpenStack APIs). This would give developers of cloud
applications an extremely flexible way of plugging together event-driven,
application-specific, autonomous actions.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Create a Zaqar notification sink plugin for Mistral. The effect of a
notification to this sink would be to create a Mistral workflow &lt;a class="reference external" href="https://docs.openstack.org/mistral/latest/#executions"&gt;Execution&lt;/a&gt;
(i.e. to trigger a pre-existing Mistral workflow).&lt;/p&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;subscriber&lt;/span&gt;&lt;/code&gt; URI should be the URL of the Mistral executions endpoint,
with the URI scheme &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;trust+http&lt;/span&gt;&lt;/code&gt; or &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;trust+https&lt;/span&gt;&lt;/code&gt;. For example,
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;trust+https://mistral.example.net/v2/executions&lt;/span&gt;&lt;/code&gt;. This scheme indicates that
Zaqar should create a Keystone trust that allows it to act on behalf of the
user in making API calls to Mistral in the future. The trust ID will be
inserted into the URL before it is stored in the form
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;trust+http://trust_id@host/path&lt;/span&gt;&lt;/code&gt;. This form is modelled after &lt;a class="reference external" href="https://docs.openstack.org/aodh/latest/#trust-http"&gt;the one used
by Aodh&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The trust lifetime should be slightly longer than the TTL of the subscription,
or unlimited if there is no TTL for the subscription. Zaqar must delete the
trust when deleting the subscription.&lt;/p&gt;
&lt;p&gt;When sending a notification, Zaqar will retrieve a trust token from Keystone
using its own service user token and the trust ID stored in the URL. The trust
token thus obtained should contain the correct tenant information to then make
the request on behalf of the original user.&lt;/p&gt;
&lt;p&gt;Since in future Zaqar may want to make &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;trust+http&lt;/span&gt;&lt;/code&gt; requests to other API
endpoints, it should distinguish on more than just the URI scheme. When the
subscription is created, Zaqar should need compare the URI with the Mistral
executions endpoint URL obtained with the help of the Keystone catalog in order
to distinguish between Mistral workflow triggers and ordinary webhooks.
Fortunately, the URL is fixed for a given cloud, so the catalog would probably
only need to be read once and it would be a straight string comparison from
there.&lt;/p&gt;
&lt;p&gt;The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;options&lt;/span&gt;&lt;/code&gt; dict should contain the following keys:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;workflow_id&lt;/span&gt;&lt;/code&gt; - The ID of the workflow to trigger&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;params&lt;/span&gt;&lt;/code&gt; - a dict of parameters that varies depending on the workflow type.
e.g. a “reverse workflow” takes a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;task_name&lt;/span&gt;&lt;/code&gt; parameter to define the
target task.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;input&lt;/span&gt;&lt;/code&gt; - an arbitrary dict of keys and values to be passed as
input to every workflow execution triggered by this notification.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When creating the Mistral execution, the contents of the message and (later)
the message ID will be passed in the environment (the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;env&lt;/span&gt;&lt;/code&gt; key in the
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;params&lt;/span&gt;&lt;/code&gt;). This allows the workflow to access the message data, but does not
require it to declare a particular input for it (so the notification can be
used to trigger &lt;em&gt;any&lt;/em&gt; workflow). The message contents, interpreted as JSON,
will be passed in a Mistral environment variable named &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;notification&lt;/span&gt;&lt;/code&gt;. When
Zaqar supports passing the message id in a notification, it will be sent as the
Mistral environment variable &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;notification_id&lt;/span&gt;&lt;/code&gt;. If these names conflict with
the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;env&lt;/span&gt;&lt;/code&gt; passed by the user in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;params&lt;/span&gt;&lt;/code&gt;, the user-provided data will be
overwritten with that received in the message.  Any other keys in the user’s
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;env&lt;/span&gt;&lt;/code&gt; will be preserved. If the user does not specify an &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;env&lt;/span&gt;&lt;/code&gt;, one will be
created.  The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;input&lt;/span&gt;&lt;/code&gt; dict, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;workflow_id&lt;/span&gt;&lt;/code&gt; and all other &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;params&lt;/span&gt;&lt;/code&gt; will be
passed through unmodified.&lt;/p&gt;
&lt;p&gt;While all the data is available to do a raw HTTP request, it is preferable if
these calls are made through the python-mistralclient library.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Instead of a push model, where Zaqar takes messages and notifies Mistral, it
would also be possible to use a pull model where Mistral polls Zaqar topics for
messages. However, while the Zaqar notification implementation already exists,
there is no such existing component in Mistral that would be suitable for
polling for triggers. It would need to poll large numbers of topics in
different tenants. A similar design was considered and rejected for the
notification feature of Zaqar; the same arguments apply here.&lt;/p&gt;
&lt;p&gt;An alternative authentication method might be to use pre-signed URLs, which are
on the &lt;a class="reference external" href="https://wiki.openstack.org/wiki/Mistral/Roadmap"&gt;Mistral roadmap&lt;/a&gt;. This might be quicker to implement, but in the
longer term, Keystone trusts are probably preferable.&lt;/p&gt;
&lt;p&gt;Instead of whitelisting the Mistral executions URL, the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;trust+http&lt;/span&gt;&lt;/code&gt; scheme
could be used to make requests to any OpenStack endpoint. However, in general
the correct method of combining static information from the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;options&lt;/span&gt;&lt;/code&gt; dict
with the contents of the message to obtain the call parameters will be
different for every API. Since Mistral can already call most OpenStack APIs and
supports a language (YAQL) for calculating the arguments using data from the
notification and other input, the simplest way to achieve this is for the user
to encapsulate any other OpenStack API call they wish to make in a Mistral
workflow (which also allows them to define custom error handling).&lt;/p&gt;
&lt;p&gt;It would be nice if there were a way to identify an OpenStack resource with a
URI without necessarily requiring a URL (containing redundant information about
the location of the endpoint). AWS uses an &lt;a class="reference external" href="http://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html"&gt;unofficial URN-like identifier&lt;/a&gt;
with an arn: (instead of urn:) scheme for this purpose. Something similar might
be useful in other contexts in OpenStack too (for example, in Heat we would
like to be able to distinguish between files in Swift containers or Glare links
and ordinary HTTP URLs for the purposes of uploading user data, although there
is some precedent for using &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;swift+http&lt;/span&gt;&lt;/code&gt; as the scheme in the Swift case).
However, this would require, at a minimum, wide cross-project agreement (and
arguably IANA registration). There are no existing examples of anything like
this in 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;p&gt;This is one of those blueprints where I’m throwing it out there to see who
picks it up.&lt;/p&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-3&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Implement the Mistral notification plugin&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create a keystone trust and store its ID in the URI when setting up a
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;trust+http(s)&lt;/span&gt;&lt;/code&gt; notification. Delete the trust again when the notification
is deleted.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add the ability to distinguish between Mistral URLs and other
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;trust+http(s)&lt;/span&gt;&lt;/code&gt; URLs in the notification URI&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;We won’t be able to pass the message ID until
&lt;a class="reference external" href="https://review.opendev.org/#/c/276968/"&gt;https://review.opendev.org/#/c/276968/&lt;/a&gt; or something equivalent merges.
However, since it can be added to the Mistral environment later without
rewriting any existing workflows (to declare a new input), this is in no way a
blocker.&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, 13 May 2019 00:00:00 </pubDate></item><item><title>OSProfiler</title><link>https://specs.openstack.org/openstack/zaqar-specs/specs/ocata/osprofiler.html</link><description>
 
&lt;p&gt;OpenStack consists of multiple projects, composed of multiple services,
working together to make different services available for the users.
In case something is not working as expected, its a really complex task
to determine what is going wrong and to locate the module causing the
bottleneck.&lt;/p&gt;
&lt;p&gt;The OSProfiler tool aims to solve this issue by making possible to generate
one trace per request affecting all involved services and build a tree of
calls.&lt;/p&gt;
&lt;p&gt;More details on how OSProfiler works can be find in the
&lt;a class="reference external" href="https://github.com/openstack/osprofiler/blob/master/README.rst"&gt;OSProfiler Readme&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This is even more important for a project like Zaqar in which performance
in communications is a key feature.&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/zaqar/+spec/osprofiler"&gt;https://blueprints.launchpad.net/zaqar/+spec/osprofiler&lt;/a&gt;&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Currently there is no way to easily detect Zaqar’s bottlenecks.&lt;/p&gt;
&lt;p&gt;Now that some projects have successfully integrated with OSProfiler,
it is important to enable OSProfiler for Zaqar as well and contribute
by providing a continuous trace information view for a request traversing
the different services.&lt;/p&gt;
&lt;p&gt;This spec proposes adding the OSProfiler tool to Zaqar.&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 integrate the OSProfiler tool to Zaqar.
According to the requirements for this addition detailed in
&lt;a class="reference external" href="https://github.com/openstack/osprofiler/blob/master/README.rst"&gt;OSProfiler Readme&lt;/a&gt;,
this shouldn’t be a complex task. The steps required to do this are detailed
in the &lt;a class="reference internal" href="#work-items"&gt;Work Items&lt;/a&gt; section.&lt;/p&gt;
&lt;p&gt;Main functional change for Zaqar server:
&lt;a class="reference external" href="https://review.opendev.org/#/c/141356/"&gt;https://review.opendev.org/#/c/141356/&lt;/a&gt;&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;Not to add the OSProfiler tool&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: zhiyan&lt;/p&gt;
&lt;p&gt;Other assignee: wangxiyuan(wxy)&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: O-2&lt;/p&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Add initialization of OSProfiler when Zaqar server starts&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add tracing support for WSGI&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add tracing support for MongoDB&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add tracing support for Redis&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add tracing support for SQLAlchemy&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add tracing support for Pooling&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add profiler CONF group&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Enable or disable profiling fully&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Enable or disable MongoDB tracing&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Enable or disable Redis tracing&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Enable or disable SQLAlchemy tracing&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Enable or disable Pooling tracing&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Configure HMAC key(s) to protect trace data&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add profile support for client&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Test the “resting” overhead when profiling is disabled and without feature&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update document(s) to make sure new options are well documented.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;Usually DB requests create a lot of trace info, so its important to
be able to enable/disable those on demand&lt;/p&gt;
&lt;/div&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;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, 13 May 2019 00:00:00 </pubDate></item><item><title>Swift storage backend</title><link>https://specs.openstack.org/openstack/zaqar-specs/specs/ocata/swift-storage.html</link><description>
 
&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/zaqar/+spec/swift-storage"&gt;https://blueprints.launchpad.net/zaqar/+spec/swift-storage&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Swift is a widely deployed object storage solution for OpenStack. While it’s
not particularly designed for high throughput of lots of small objects, which
is what Zaqar mostly does, it scales really well, and is highly fault tolerant.
It would also provide an alternative to people that want to avoid to deploy
and manage MongoDB.&lt;/p&gt;
&lt;section id="driver-description"&gt;
&lt;h2&gt;Driver description&lt;/h2&gt;
&lt;p&gt;The driver only implements the data part, SQL being available for the
control driver. Containers are used per entity and per project, to provide
multitenancy.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;The driver uses one global service user, and stores all messages in one
project. It uses suffix on container names to scope them. It will use mostly
one container per entity type, plus other for additional indexes. We may need
to increase or decrease the number of containers used, to find the appropriate
performance balance.&lt;/p&gt;
&lt;p&gt;It may be worth marking the driver experimental first, so that we can change
the storage model without caring about migrating data.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="what-are-the-driver-s-guarantees-in-terms-of-reliability"&gt;
&lt;h2&gt;What are the driver’s guarantees in terms of reliability?&lt;/h2&gt;
&lt;p&gt;We rely on Swift being configured appropriately to provide message reliability.
By default objects are replicated 3 times, which offers good guarantees.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="what-are-the-driver-s-guarantees-in-terms-of-scalability"&gt;
&lt;h2&gt;What are the driver’s guarantees in terms of scalability?&lt;/h2&gt;
&lt;p&gt;Again, we rely on Swift scalability guarantees here.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="what-are-the-driver-s-guarantees-in-terms-of-interoperability"&gt;
&lt;h2&gt;What are the driver’s guarantees in terms of interoperability?&lt;/h2&gt;
&lt;p&gt;We use publicly available Swift APIs, so the data is easily auditable and
recoverable behind Zaqar.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="what-are-the-driver-s-guarantees-in-terms-of-openness"&gt;
&lt;h2&gt;What are the driver’s guarantees in terms of openness?&lt;/h2&gt;
&lt;p&gt;We use python-swiftclient to access Swift, which uses the Apache 2.0 license.&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;therve&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-3&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Implement storage driver, and make unit tests pass.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add a voting gate against Swift.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Possibly make some performance testing to tweak how objects are stored.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Depend on Swift fix for if-none-match: &lt;a class="reference external" href="https://review.opendev.org/395582"&gt;https://review.opendev.org/395582&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, 13 May 2019 00:00:00 </pubDate></item><item><title>Support redis as mgmt storage backend</title><link>https://specs.openstack.org/openstack/zaqar-specs/specs/queens/support-redis-as-mgmt-storage-backend.html</link><description>
 
&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/zaqar/+spec/support-redis-as-management-storage-backend"&gt;https://blueprints.launchpad.net/zaqar/+spec/support-redis-as-management-storage-backend&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Redis is different than other database solutions in many ways, it support
two modes: memory storage and disk storage, We can select one of the two modes
by modifying redis.conf. If we add save options in redis.conf, redis can
cyclically save the data into disk:
save 900 1
save 300 10
save 60 10000&lt;/p&gt;
&lt;p&gt;Redis includes a fairly high performance implementation of database.
Currently, zaqar supports redis, mongodb and swift as the storage backend.
After performance testing, we find that the performance of redis
is the highest among these storage-backend. Using Redis, we may provide a
system which is very practical to use, easy to administer and scale, while
providing excellent performances.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;In order to enhance the performance of zaqar, it is necessary to support
redis as a management database backend.&lt;/p&gt;
&lt;p&gt;At present, Zaqar has supported sqlalchemy and mongodb as management storage
backend, that would be a good reference for redis.&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;Add CatalogueController in redis storage:&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;Add such functions: insert, update, delete, list, get, drop_all etc.&lt;/p&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;ol class="arabic simple" start="2"&gt;
&lt;li&gt;&lt;p&gt;Add FlavorsController in redis storage:&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;Add such functions: insert, update, delete, list, get, drop_all etc.&lt;/p&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;ol class="arabic simple" start="3"&gt;
&lt;li&gt;&lt;p&gt;Add PoolsController in redis storage:&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;Add such functions: insert, update, delete, list, get, drop_all etc.&lt;/p&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;section id="drawbacks"&gt;
&lt;h3&gt;Drawbacks&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;MongoDB SQL&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;We need to add three table models, as follows:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Redis Data Structures for table catalogue:&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;All Project (Redis sorted set):&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;Set of all queue_ids, ordered by name. Used to delete the all
records of table catalogue.&lt;/p&gt;
&lt;p&gt;Key: catalogue&lt;/p&gt;
&lt;table class="docutils align-default"&gt;
&lt;colgroup&gt;
&lt;col style="width: 22%"/&gt;
&lt;col style="width: 78%"/&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Id&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Value&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;name&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&amp;lt;project_id&amp;gt;.&amp;lt;queue_name&amp;gt;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Project Index (Redis sorted set):&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;Set of all queue_ids for the given project, ordered by name.&lt;/p&gt;
&lt;p&gt;Key: &amp;lt;project_id&amp;gt;.catalogue&lt;/p&gt;
&lt;table class="docutils align-default"&gt;
&lt;colgroup&gt;
&lt;col style="width: 22%"/&gt;
&lt;col style="width: 78%"/&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Id&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Value&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;name&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&amp;lt;project_id&amp;gt;.&amp;lt;queue_name&amp;gt;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Queue and pool Information (Redis hash):&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;Key: &amp;lt;project_id&amp;gt;.&amp;lt;queue_name&amp;gt;.catalogue&lt;/p&gt;
&lt;table class="docutils align-default"&gt;
&lt;colgroup&gt;
&lt;col style="width: 71%"/&gt;
&lt;col style="width: 29%"/&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Field&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Project&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;p&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;Queue&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;p_q&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;Pool&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;p_p&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ol class="arabic simple" start="2"&gt;
&lt;li&gt;&lt;p&gt;Redis Data Structures for table flavor:&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;All flavor_ids (Redis sorted set):&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;Set of all flavor_ids, ordered by name. Used to delete the all
records of table flavors.&lt;/p&gt;
&lt;p&gt;Key: flavors&lt;/p&gt;
&lt;table class="docutils align-default"&gt;
&lt;colgroup&gt;
&lt;col style="width: 22%"/&gt;
&lt;col style="width: 78%"/&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Id&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Value&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;name&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&amp;lt;flavor&amp;gt;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Project Index (Redis sorted set):&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;Set of all flavors for the given project, ordered by name.&lt;/p&gt;
&lt;p&gt;Key: &amp;lt;project_id&amp;gt;.flavors&lt;/p&gt;
&lt;table class="docutils align-default"&gt;
&lt;colgroup&gt;
&lt;col style="width: 22%"/&gt;
&lt;col style="width: 78%"/&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Id&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Value&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;name&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&amp;lt;flavor&amp;gt;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Flavor Information (Redis hash):&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;Key: &amp;lt;flavor_id&amp;gt;.flavors&lt;/p&gt;
&lt;table class="docutils align-default"&gt;
&lt;colgroup&gt;
&lt;col style="width: 71%"/&gt;
&lt;col style="width: 29%"/&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Field&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;flavor&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;f&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;project&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;p&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;capabilities&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;c&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ol class="arabic simple" start="3"&gt;
&lt;li&gt;&lt;p&gt;Redis Data Structures for table pools:&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;All pool (Redis sorted set):&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;Set of all pool_ids, ordered by name. Used to delete the all
records of table pools.&lt;/p&gt;
&lt;p&gt;Key: pools&lt;/p&gt;
&lt;table class="docutils align-default"&gt;
&lt;colgroup&gt;
&lt;col style="width: 22%"/&gt;
&lt;col style="width: 78%"/&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Id&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Value&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;name&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&amp;lt;pool&amp;gt;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Flavor Index (Redis sorted set):&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;Set of all pool_ids for the given flavor, ordered by name.&lt;/p&gt;
&lt;p&gt;Key: &amp;lt;flavor&amp;gt;.pools&lt;/p&gt;
&lt;table class="docutils align-default"&gt;
&lt;colgroup&gt;
&lt;col style="width: 22%"/&gt;
&lt;col style="width: 78%"/&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Id&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Value&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;name&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&amp;lt;pool&amp;gt;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Pools Information (Redis hash):&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;Key: &amp;lt;pool&amp;gt;.pools&lt;/p&gt;
&lt;table class="docutils align-default"&gt;
&lt;colgroup&gt;
&lt;col style="width: 71%"/&gt;
&lt;col style="width: 29%"/&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr class="row-odd"&gt;&lt;th class="head"&gt;&lt;p&gt;Name&lt;/p&gt;&lt;/th&gt;
&lt;th class="head"&gt;&lt;p&gt;Field&lt;/p&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;pool&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;p&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;uri&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;u&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-even"&gt;&lt;td&gt;&lt;p&gt;weight&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;w&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="row-odd"&gt;&lt;td&gt;&lt;p&gt;options&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;o&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;gengchc2 &amp;lt;&lt;a class="reference external" href="mailto:geng.changcai2%40zte.com.cn"&gt;geng&lt;span&gt;.&lt;/span&gt;changcai2&lt;span&gt;@&lt;/span&gt;zte&lt;span&gt;.&lt;/span&gt;com&lt;span&gt;.&lt;/span&gt;cn&lt;/a&gt;&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Secondary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;gecong &amp;lt;&lt;a class="reference external" href="mailto:ge.cong%40zte.com.cn"&gt;ge&lt;span&gt;.&lt;/span&gt;cong&lt;span&gt;@&lt;/span&gt;zte&lt;span&gt;.&lt;/span&gt;com&lt;span&gt;.&lt;/span&gt;cn&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;dl class="simple"&gt;
&lt;dt&gt;Target Milestone for completion:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Queens-Q2&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 CatalogueController in redis storage.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add FlavorsController in redis storage.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add PoolsController in redis storage.&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;[1]:&lt;a class="reference external" href="https://review.opendev.org/#/c/345133/"&gt;https://review.opendev.org/#/c/345133/&lt;/a&gt;&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Both unit and Tempest tests need to be created to cover the code change.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Add docs about the configuration of redis and HA.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;p&gt;[2]:&lt;a class="reference external" href="http://paste.openstack.org/show/621298/"&gt;http://paste.openstack.org/show/621298/&lt;/a&gt;&lt;/p&gt;
&lt;/section&gt;
</description><pubDate>Mon, 13 May 2019 00:00:00 </pubDate></item><item><title>remove-pool-group-totally</title><link>https://specs.openstack.org/openstack/zaqar-specs/specs/stein/remove-pool-group-totally.html</link><description>
 
&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/zaqar/+spec/remove-pool-group-totally"&gt;https://blueprints.launchpad.net/zaqar/+spec/remove-pool-group-totally&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;remove-pool-group-totally.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Currently pool group is used in pool and flavor resource, but the pool group
only supports a 1:1 mapping with flavor. So it’s not necessary to keep it
since we can map 1 flavor : N pool directly. Another issue is currently there
is no API to handle the pool group resource, which is very annoying to
maintain by operators.&lt;/p&gt;
&lt;p&gt;For making a clarification to user, this bp proposes to remove useless
pool group from Zaqar, just keeps the pool resource.&lt;/p&gt;
&lt;p&gt;For backward compatibility, we have split this work into two steps:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;In Queens, we have supported the old way to use pool_group and the new way
without it in Flavor both.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In Stein, we will remove the pool_group totally and only keep the new way
in Flavor and Pool.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This bp will implement the second step and totally remove the pool group from
zaqar.&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;Modify pool and flavor operation API:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Remove group from flavor operation API: like creat, update, show, list.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Remove group from pool operation API: like creat, update, show, list.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Remove the related logic codes about group in the zaqar server:&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The Data model of flavor and pool resources have been changed in Queens,
There is no need to discard pool_group field and Drop table PoolGroup
we will just keep it in table for degrade convenience.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Modify the related logic codes about group in the zaqar client:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;openstack messaging flavor create&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;openstack messaging flavor update&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;openstack messaging pool create&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;openstack messaging pool update&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;section id="drawbacks"&gt;
&lt;h3&gt;Drawbacks&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;1. Create flavor API
The Request JSON when create flavor:&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;PUT&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;v2&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;flavors&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;flavor_name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="s2"&gt;"pool_list"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;pool1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pool2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The response JSON when Create flavor:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;Normal response codes: 201

Error response codes:
•BadRequest (400)
•Unauthorized (401)
•Forbidden (403)
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;2. Update flavor API
The Request JSON when update flavor:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt; &lt;span class="n"&gt;PATCH&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;v2&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;flavors&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;flavor_name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="s2"&gt;"pool_list"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;pool1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pool2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pool3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The response JSON when update flavor:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;{
  "href": "/v2/flavors/testflavor",
  "name": "testflavor",
  "capabilities": [
    "FIFO",
    "CLAIMS",
    "DURABILITY",
    "AOD",
    "HIGH_THROUGHPUT"
  ],
  "pool_list": [pool1, pool2, pool3]
}
 Normal response codes: 200

 Error response codes:
 •BadRequest (400)
 •Unauthorized (401)
 •Forbidden (403)
 •Not Found (404)
 •ServiceUnavailable (503)
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;3. Shows details for a flavor API
The response JSON when show details flavor:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;GET&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;v2&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;flavors&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;flavor_name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="s2"&gt;"href"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"/v2/flavors/testflavor"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;"capabilities"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="s2"&gt;"FIFO"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"CLAIMS"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"DURABILITY"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"AOD"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"HIGH_THROUGHPUT"&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="s2"&gt;"pool_list"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;pool1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pool2&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="s2"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"testflavor"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The response JSON when show details flavor:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;Normal response codes: 200

Error response codes:
•BadRequest (400)
•Unauthorized (401)
•Forbidden (403)
•Not Found (404)
•ServiceUnavailable (503)
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;4. List flavor API
The response JSON when list flavors:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;GET&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;v2&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;flavors&lt;/span&gt;

&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="s2"&gt;"flavors"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="s2"&gt;"href"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"/v2/flavors/test_flavor1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s2"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"test_flavor1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s2"&gt;"pool_list"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;pool1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pool2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="s2"&gt;"href"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"/v2/flavors/test_flavor2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s2"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"test_flavor2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s2"&gt;"pool_list"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;pool3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pool4&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;"links"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="s2"&gt;"href"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"/v2/flavors?marker=test_flavor2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s2"&gt;"rel"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"next"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The response JSON when list flavors:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;Normal response codes: 200

Error response codes:
•Unauthorized (401)
•Forbidden (403)
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;5. Create pools API
The Request JSON when create pools:&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;PUT&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;v2&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;pools&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;pool_name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;"weight"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"uri"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"mongodb://127.0.0.1:27017"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"options"&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;
        &lt;span class="s2"&gt;"max_retry_sleep"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="s2"&gt;"flavor"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"testflavor"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The response JSON when Create pools:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;Normal response codes: 201

Error response codes:
•BadRequest (400)
•Unauthorized (401)
••Conflict (409)
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;6. Update pools API
The Request JSON when update pools:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;PATCH&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;v2&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;pools&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;pool_name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="s2"&gt;"weight"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="s2"&gt;"uri"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"mongodb://127.0.0.1:27017"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="s2"&gt;"options"&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;
       &lt;span class="s2"&gt;"max_retry_sleep"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
   &lt;span class="p"&gt;},&lt;/span&gt;
   &lt;span class="s2"&gt;"flavor"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"testflavor1"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The response JSON when update pools:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;{
  "href": "/v2/pools/test_pool",
  "name": "test_pool",
  "weight": 60,
  "uri": "mongodb://127.0.0.1:27017",
  "flavor": "testflavor1"
}
 Normal response codes: 200

 Error response codes:
 •BadRequest (400)
 •Unauthorized (401)
 •Not Found (404)
 •ServiceUnavailable (503)
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;7. Shows details for a pool API
The response JSON when show details pool:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;GET&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;v2&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;pools&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;pool_name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="s2"&gt;"href"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"/v2/pools/test_pool"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;"flavor"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"flavor1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"test_pool"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;"weight"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;"uri"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"mongodb://127.0.0.1:27017"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The response JSON when show details pool:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;Normal response codes: 200

Error response codes:
•BadRequest (400)
•Unauthorized (401)
•ServiceUnavailable (503)
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;8. List pools API
The response JSON when list pools:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;GET&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;v2&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;pools&lt;/span&gt;

&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="s2"&gt;"pools"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="s2"&gt;"href"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"/v2/pools/test_pool1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s2"&gt;"flavor"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"flavor1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s2"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"test_pool1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s2"&gt;"weight"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s2"&gt;"uri"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"mongodb://192.168.1.10:27017"&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="s2"&gt;"href"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"/v2/pools/test_pool2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s2"&gt;"flavor"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"flavor1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s2"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"test_pool2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s2"&gt;"weight"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s2"&gt;"uri"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"mongodb://192.168.1.20:27017"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="s2"&gt;"links"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="s2"&gt;"href"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"/v2/pools?marker=test_pool2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s2"&gt;"rel"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"next"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The response JSON when list pools:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;Normal response codes: 200

Error response codes:
•Unauthorized (401)
•Not Found (404)
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;We use the v2 interface, just add pool_list in the flavor API and add the
flavor in the pool API. we will remove the old way in this bp.&lt;/p&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;&lt;p&gt;Old Way:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;configure group in pool API and in flavor API;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;New Way:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;configure pool_list in flavor API&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;add a pool to flavor:&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;method one: update pool_list in flavor API&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;method two: config a pool with the flavor in pool API.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;gecong&amp;lt;&lt;a class="reference external" href="mailto:ge.cong%40zte.com.cn"&gt;ge&lt;span&gt;.&lt;/span&gt;cong&lt;span&gt;@&lt;/span&gt;zte&lt;span&gt;.&lt;/span&gt;com&lt;span&gt;.&lt;/span&gt;cn&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;dl class="simple"&gt;
&lt;dt&gt;Target Milestone for completion:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Stein&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Modify pool and flavor operation APIs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Remove the related logic codes about group in the zaqar server.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Both unit and Tempest tests need to be created to cover the code change.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;The Zaqar API documentation will need to be updated to reflect the REST
API changes.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
</description><pubDate>Tue, 08 Jan 2019 00:00:00 </pubDate></item><item><title>Support zaqar_sendmail</title><link>https://specs.openstack.org/openstack/zaqar-specs/specs/stein/email-notification-by-internal-tool.html</link><description>&lt;section id="support-zaqar-sendmail"&gt;
 
&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/zaqar/+spec/zaqar-email-delivery"&gt;https://blueprints.launchpad.net/zaqar/+spec/zaqar-email-delivery&lt;/a&gt;&lt;/p&gt;
&lt;/section&gt;
&lt;section id="problem-description"&gt;
 
&lt;p&gt;Currently the email subscription in Zaqar relay on the third part tools, such
as “sendmail”. It means that deployer should install it out of Zaqar. If he
forgets, Zaqar will raise internal error. This work let Zaqar support email
subscription by itself using the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;smtp&lt;/span&gt;&lt;/code&gt; python library.&lt;/p&gt;
&lt;section id="use-cases"&gt;
&lt;h2&gt;Use Cases&lt;/h2&gt;
&lt;p&gt;The modification enables users to send email subscriptions without the third
part tools.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
 
&lt;p&gt;A new config option &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;smtp_mode&lt;/span&gt;&lt;/code&gt; will be added, it has two value choices,
[“third_part”, “self_local”]. &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;third_part&lt;/span&gt;&lt;/code&gt; means Zaqar will use the tools
from which &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;smtp_command&lt;/span&gt;&lt;/code&gt; config option provides to send email subscription.
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;self_local&lt;/span&gt;&lt;/code&gt; means Zaqar will use the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;smtp&lt;/span&gt;&lt;/code&gt; python library instead.&lt;/p&gt;
&lt;p&gt;A email template file will be added as well. Some parameters in the file should
be configured firstly before using. Those parameters include something like
smtp service account/password, smtp service address and so on. These value
should come from config options as well.&lt;/p&gt;
&lt;p&gt;The email body in the template file should be configured as well. Currently,
it can only be managed by operators out of Zaqar. In the future, we can use
jinja template way to let it be configurable by Zaqar.&lt;/p&gt;
&lt;p&gt;Once &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;self_local&lt;/span&gt;&lt;/code&gt; is used, Zaqar will fill up the template file first, then
use &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;stmp&lt;/span&gt;&lt;/code&gt; lib to send the email subscription.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h2&gt;Alternatives&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h2&gt;REST API impact&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="security-impact"&gt;
&lt;h2&gt;Security impact&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="notifications-impact"&gt;
&lt;h2&gt;Notifications impact&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h2&gt;Other end user impact&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="performance-impact"&gt;
&lt;h2&gt;Performance Impact&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-deployer-impact"&gt;
&lt;h2&gt;Other deployer impact&lt;/h2&gt;
&lt;p&gt;A new config option called &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;smtp_mode&lt;/span&gt;&lt;/code&gt; is added. To keep backward
compatibility the default behavior is keeping use third part tools to send
email subscription. If you don’t want to install the third part email tools
anymore, please change its value to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;self_local&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h2&gt;Developer impact&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
 
&lt;section id="assignee-s"&gt;
&lt;h2&gt;Assignee(s)&lt;/h2&gt;
&lt;p&gt;changyufei&amp;lt;&lt;a class="reference external" href="mailto:changyufei%40unitedstack.com"&gt;changyufei&lt;span&gt;@&lt;/span&gt;unitedstack&lt;span&gt;.&lt;/span&gt;com&lt;/a&gt;&amp;gt;&lt;/p&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h2&gt;Work Items&lt;/h2&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Add a new config option &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;smtp_mode&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add the email template&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add the logic to use &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;smtp&lt;/span&gt;&lt;/code&gt; python lib&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The test code should be added.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Document.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
&lt;section id="milestones"&gt;
&lt;h2&gt;Milestones&lt;/h2&gt;
&lt;p&gt;R-3&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
 
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
 
&lt;p&gt;For functional test, here is no good way to test it in Upstream since
OpenStack CI/CD environment doesn’t has a email service. Or we may ask the
community for help to give Zaqar team a test account within @openstack.org
email system. Or any other third part company can provide one for us. Otherwise
we could only test it locally to make sure it works well.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
 
&lt;p&gt;A new send email way will be added. It should be documented.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
 
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
</description><pubDate>Mon, 29 Oct 2018 00:00:00 </pubDate></item><item><title>Delete Message With Claim ID</title><link>https://specs.openstack.org/openstack/zaqar-specs/specs/stein/delete-message-with-claim-id.html</link><description>
 
&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/zaqar/+spec/delete-message-with-claim-id"&gt;https://blueprints.launchpad.net/zaqar/+spec/delete-message-with-claim-id&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Delete Message with claim id means that when a user deletes a message, the
message must be claimed. If you want to delete a message, you will have to use
both message id and claim id. This can improve the security of the message.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Currently, any client who knows the message ID can delete the message if it not
be claimed. It could cause some unexpected problems. A better way to delete a
message is make sure the message is deleted by the client who is claiming the
message. Amazon SQS use receipt handler to delete a message[1]. Zaqar can use
claim id and message id to delete messages.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Add a new configuration item named &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;message_delete_with_claim_id&lt;/span&gt;&lt;/code&gt;, default
value is &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;False&lt;/span&gt;&lt;/code&gt;, means it is backwards compatible. You can modify this
configuration item to decide whether to turn on the switch. If you change it to
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;True&lt;/span&gt;&lt;/code&gt;, you need to forcibly carry the claim id when delete messages. If the
claim ID is invalid, the message can not be deleted. You must re-claim the
messages, and then delete it.&lt;/p&gt;
&lt;p&gt;..note:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;No&lt;/span&gt; &lt;span class="n"&gt;matter&lt;/span&gt; &lt;span class="s2"&gt;"message_delete_with_claim_id"&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt; &lt;span class="n"&gt;of&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;admin&lt;/span&gt; &lt;span class="n"&gt;can&lt;/span&gt;
&lt;span class="n"&gt;always&lt;/span&gt; &lt;span class="n"&gt;delete&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="n"&gt;without&lt;/span&gt; &lt;span class="n"&gt;claim_id&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;section id="api-impact"&gt;
&lt;h3&gt;API Impact&lt;/h3&gt;
&lt;p&gt;Delete single message
DELETE: /v2/queues/test_queue/messages/{message_id}?claim_id={claim_id}&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;RESPONSE CODE: 204&lt;/p&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;Delete messages
DELETE: /v2/queues/test_queue/messages?ids={messages_ids}&amp;amp;claim_ids={claim_ids}&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;RESPONSE CODE: 204&lt;/p&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;/section&gt;
&lt;section id="drawbacks"&gt;
&lt;h3&gt;Drawbacks&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;cdyangzhenyu &amp;lt;&lt;a class="reference external" href="mailto:cdyangzhenyu%40gmail.com"&gt;cdyangzhenyu&lt;span&gt;@&lt;/span&gt;gmail&lt;span&gt;.&lt;/span&gt;com&lt;/a&gt;&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Secondary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;gecong&amp;lt;&lt;a class="reference external" href="mailto:ge.cong%40zte.com.cn"&gt;ge&lt;span&gt;.&lt;/span&gt;cong&lt;span&gt;@&lt;/span&gt;zte&lt;span&gt;.&lt;/span&gt;com&lt;span&gt;.&lt;/span&gt;cn&lt;/a&gt;&amp;gt;
wanghao&amp;lt;&lt;a class="reference external" href="mailto:sxmatch1986%40gmail.com"&gt;sxmatch1986&lt;span&gt;@&lt;/span&gt;gmail&lt;span&gt;.&lt;/span&gt;com&lt;/a&gt;&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="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;stein RC3&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Modify message delete code.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add release note for this feature.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update API reference.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add user/developer document for this feature.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Change unit, functional and tempest tests accordingly.&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="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;[1]:&lt;a class="reference external" href="https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-queue-message-identifiers.html"&gt;https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-queue-message-identifiers.html&lt;/a&gt;&lt;/p&gt;
&lt;/section&gt;
</description><pubDate>Mon, 15 Oct 2018 00:00:00 </pubDate></item><item><title>Introduce Topic Resource For Notification</title><link>https://specs.openstack.org/openstack/zaqar-specs/specs/stein/introduce-topic-resource-for-notification.html</link><description>
 
&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/zaqar/+spec/introduce-topic-resource-for-notification"&gt;https://blueprints.launchpad.net/zaqar/+spec/introduce-topic-resource-for-notification&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;We want to introduce a new resource called Topic into Zaqar.
Topic is a concept from AWS Simple Notification Service (SNS), it will has
relevance with subscriptions. User can send message to a topic,
and then the subscribers will get the message according to different protocols,
like http, email, sms, etc.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Now basically Zaqar has integrated two types of services,
Messaging Queue Service and Notification Service. We create subscriptions
based on queue, and also introduce retry policy for subscription and queue.
It’s not very clear from the service view, especially for the users who have
been used to the SNS and SQS in AWS&lt;/p&gt;
&lt;p&gt;So in Rocky, we want to introduce the Topic resource into Zaqar, and split
Messaging Queue Service and Notification Service clearly.&lt;/p&gt;
&lt;p&gt;AWS SNS service has the resource named Topic, that would be a good reference
for Zaqar[1].&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;To implement the Topic resource, one idea is to define the Topic as a special
queue with some special feature that is different from common queue.&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Could set the users or projects who can send topic message to this Topic&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Could set the users or projects who can subscribe this Topic.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The messages will be stored in Topic but those messages could NOT be claimed
since they are just used for sending to subscribers. When sending
successfully, Zaqar will delete this message from topic, if not, will retry
the sending process.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Besides those features, user also can set the retry policy to Topic and
Subscription both.&lt;/p&gt;
&lt;p&gt;After introducing Topic to Zaqar, we will keep the subscription of common
queue for a while, but we also want to change the users’ behavior to use Topic
if they want to subscribe something in Zaqar. So maybe we remove the
subscription of common queue in future.&lt;/p&gt;
&lt;section id="api-impact"&gt;
&lt;h3&gt;API Impact&lt;/h3&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;&lt;p&gt;Topic Creation:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;PUT&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;v2&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;topics&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;topic_name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;BODY&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="s2"&gt;"_allowed_sending_users"&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;List&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;optional&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="s2"&gt;"_allowed_sending_projects"&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;List&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="n"&gt;project&lt;/span&gt; &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;optional&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="s2"&gt;"_allowed_subscribe_users"&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;List&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;optional&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="s2"&gt;"_allowed_subscribe_projects"&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;List&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="n"&gt;project&lt;/span&gt; &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;optional&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="s2"&gt;"_allowed_subscribe_protocols"&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;List&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;optional&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="s2"&gt;"_retry_policy"&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;Dict&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;optional&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;RESPONSE&lt;/span&gt; &lt;span class="n"&gt;CODES&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;201&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;204&lt;/span&gt;
&lt;span class="n"&gt;ERROR&lt;/span&gt; &lt;span class="n"&gt;RESPONSE&lt;/span&gt; &lt;span class="n"&gt;CODES&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;BadRequest&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;Unauthorized&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;401&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;ServiceUnavailable&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;503&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;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;“_allowed_sending_users”: define which users can send message to topic.
“_allowed_sending_projects”: define which projects can send message to topic.
Of course you can set the project owned this topic here too.
“_allowed_subscribe_users”: define which users can subscribe topic.
“_allowed_subscribe_projects”: define which projects can subscribe topic.
The default behavior is allowing all the users under the project who create
this topic send message, and all projects could subscribe this topic.
Default subscribe protocols are email, webhook, and trust.
The retry policy is same as Queue’s retry policy.&lt;/p&gt;
&lt;/div&gt;
&lt;ol class="arabic" start="2"&gt;
&lt;li&gt;&lt;p&gt;Topic 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;PATCH&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;v2&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;topics&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;topic_name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;BODY&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;
   &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="s2"&gt;"op"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"replace"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s2"&gt;"path"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"/metadata/allowed_sending_projects"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s2"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;pro_id1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pro_id2&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;pro_idN&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;RESPONSE&lt;/span&gt; &lt;span class="n"&gt;CODE&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;
&lt;span class="n"&gt;ERROR&lt;/span&gt; &lt;span class="n"&gt;RESPONSE&lt;/span&gt; &lt;span class="n"&gt;CODES&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;BadRequest&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;Unauthorized&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;401&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;Not&lt;/span&gt; &lt;span class="n"&gt;Found&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;404&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;Conflict&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;409&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;ServiceUnavailable&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;503&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;Topic Query List:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;GET&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;v2&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;topics&lt;/span&gt;
&lt;span class="n"&gt;RESPONSE&lt;/span&gt; &lt;span class="n"&gt;BODY&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="s2"&gt;"topics"&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;"topic_name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;xxx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                   &lt;span class="s2"&gt;"href"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;xxx&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
             &lt;span class="p"&gt;],&lt;/span&gt;
   &lt;span class="s2"&gt;"links"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
               &lt;span class="p"&gt;{&lt;/span&gt;
                   &lt;span class="s2"&gt;"href"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'/v2/topic?marker=wellington'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                   &lt;span class="s2"&gt;"rel"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"next"&lt;/span&gt;
               &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;RESPONSE&lt;/span&gt; &lt;span class="n"&gt;CODE&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;
&lt;span class="n"&gt;ERROR&lt;/span&gt; &lt;span class="n"&gt;RESPONSE&lt;/span&gt; &lt;span class="n"&gt;CODES&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;BadRequest&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;Unauthorized&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;401&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;ServiceUnavailable&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;503&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;Topic Query Detail:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;GET&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;v2&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;topics&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;topic_name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;RESPONSE&lt;/span&gt; &lt;span class="n"&gt;BODY&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="s2"&gt;"_allowed_sending_users"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;user_id1&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;user_idN&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
   &lt;span class="s2"&gt;"_allowed_sending_projects"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;pro_id1&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;pro_idN&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
   &lt;span class="s2"&gt;"_allowed_subscribe_users"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;user_id1&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;user_idN&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
   &lt;span class="s2"&gt;"_allowed_subscribe_projects"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;pro_id1&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;pro_idN&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
   &lt;span class="s2"&gt;"_allowed_subscribe_protocols"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;webhook&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;trust&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
   &lt;span class="s2"&gt;"_retry_policy"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;RESPONSE&lt;/span&gt; &lt;span class="n"&gt;CODE&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;
&lt;span class="n"&gt;ERROR&lt;/span&gt; &lt;span class="n"&gt;RESPONSE&lt;/span&gt; &lt;span class="n"&gt;CODES&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;BadRequest&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;Unauthorized&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;401&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;ServiceUnavailable&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;503&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;Topic Delete:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;DELETE&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;v2&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;topics&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;topic_name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;RESPONSE&lt;/span&gt; &lt;span class="n"&gt;CODE&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;204&lt;/span&gt;
&lt;span class="n"&gt;ERROR&lt;/span&gt; &lt;span class="n"&gt;RESPONSE&lt;/span&gt; &lt;span class="n"&gt;CODES&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;BadRequest&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;Unauthorized&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;401&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;ServiceUnavailable&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;503&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;/section&gt;
&lt;section id="drawbacks"&gt;
&lt;h3&gt;Drawbacks&lt;/h3&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;wanghao (&lt;a class="reference external" href="mailto:sxmatch1986%40gmail.com"&gt;sxmatch1986&lt;span&gt;@&lt;/span&gt;gmail&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;R-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;Implement the Topic API.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Implement the process of CRUD.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;UTs for this feature.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;DOC support.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;[1]: &lt;a class="reference external" href="http://docs.aws.amazon.com/sns/latest/dg/welcome.html"&gt;http://docs.aws.amazon.com/sns/latest/dg/welcome.html&lt;/a&gt;&lt;/p&gt;
&lt;/section&gt;
</description><pubDate>Fri, 28 Sep 2018 00:00:00 </pubDate></item><item><title>Remove pools group from Zaqar</title><link>https://specs.openstack.org/openstack/zaqar-specs/specs/queens/remove-pool-group-from-zaqar.html</link><description>
 
&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/zaqar/+spec/remove-pool-group-from-zaqar"&gt;https://blueprints.launchpad.net/zaqar/+spec/remove-pool-group-from-zaqar&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Remove pool group from pool and flavor resource.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Currently pool group is used in pool and flavor resource, but the pool group
only supports a 1:1 mapping with flavor. So it’s not necessary to keep it
since we can map 1 flavor : N pool directly. Another issue is currently there
is no API to handle the pool group resource, which is very annoying to
maintain by operators.&lt;/p&gt;
&lt;p&gt;For making a clarification to user, this bp proposes to remove useless
pool group from Zaqar, just keeps the pool resource.&lt;/p&gt;
&lt;p&gt;For backward compatibility, we will split this work into two steps:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;In Queens, we support the old way to use pool_group and the new way without
it in Flavor both. The pool_group will be marked to let users know it will
be useless soon and remove in R release.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In Rocky, we will remove the pool_group totally and only keep the new way
in Flavor and Pool.&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;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Modify pool and flavor operation API:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Remove group from flavor operation API: like creat, update, show, list.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Remove group from pool operation API: like creat, update, show, list.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;..note:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;This&lt;/span&gt; &lt;span class="n"&gt;changes&lt;/span&gt; &lt;span class="n"&gt;isn&lt;/span&gt;&lt;span class="s1"&gt;'t going to happen in Queens release for backward&lt;/span&gt;
&lt;span class="n"&gt;compatibility&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;we&lt;/span&gt; &lt;span class="n"&gt;keep&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;pool_group&lt;/span&gt; &lt;span class="n"&gt;this&lt;/span&gt; &lt;span class="n"&gt;circle&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;mark&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="n"&gt;will&lt;/span&gt; &lt;span class="n"&gt;be&lt;/span&gt;
&lt;span class="n"&gt;useless&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;Zaqar&lt;/span&gt; &lt;span class="n"&gt;log&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;remove&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;pool&lt;/span&gt; &lt;span class="n"&gt;group&lt;/span&gt; &lt;span class="n"&gt;totally&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;R&lt;/span&gt; &lt;span class="n"&gt;release&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;ol class="arabic" start="2"&gt;
&lt;li&gt;&lt;p&gt;Modify the related logic codes about group in the zaqar server:&lt;/p&gt;
&lt;p&gt;For example, now in the creation of the queue, first we find all the pools
base on group, and then select the appropriate pool (pool = select.weighted
(pools)) to create the queue.&lt;/p&gt;
&lt;p&gt;We modify as follows:
Find all the pools base on flavor, and then select the appropriate pool to
create a queue.&lt;/p&gt;
&lt;p&gt;etc.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Change the Data model of flavor and pool resources, detail see Data model
impact.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Modify the related logic codes about group in the zaqar client:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;openstack messaging flavor create&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;openstack messaging flavor update&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;openstack messaging pool create&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;openstack messaging pool update&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;..note:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;Like&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;changes&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;Zaqar&lt;/span&gt; &lt;span class="n"&gt;APIs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;this&lt;/span&gt; &lt;span class="n"&gt;change&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;also&lt;/span&gt; &lt;span class="n"&gt;going&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;do&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;R&lt;/span&gt;
&lt;span class="n"&gt;release&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;section id="drawbacks"&gt;
&lt;h3&gt;Drawbacks&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;For sqlalchemy:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Drop table PoolGroup in R.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Modify Flavors table:&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;dl class="simple"&gt;
&lt;dt&gt;Discard pool_group field, but do not remove the field in Q in order to be&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;compatible with the latter :
CREATE TABLE &lt;cite&gt;Flavors&lt;/cite&gt; (
&lt;cite&gt;name&lt;/cite&gt; varchar(64) NOT NULL,
&lt;cite&gt;project&lt;/cite&gt; varchar(64) DEFAULT NULL,
&lt;cite&gt;pool_group&lt;/cite&gt; varchar(64) NOT NULL,
&lt;cite&gt;capabilities&lt;/cite&gt; text,
PRIMARY KEY (&lt;cite&gt;name&lt;/cite&gt;),
) ENGINE=InnoDB DEFAULT CHARSET=utf8;&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Modify Pools table:&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;dl class="simple"&gt;
&lt;dt&gt;Discard group field, but do not remove the field in Q in order to be&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;compatible with the latter;
Add flavor field, this flavor field equals name field of the flavor:
CREATE TABLE &lt;cite&gt;Pools&lt;/cite&gt; (
&lt;cite&gt;name&lt;/cite&gt; varchar(64) NOT NULL,
&lt;cite&gt;group&lt;/cite&gt; varchar(64) DEFAULT NULL,
&lt;cite&gt;uri&lt;/cite&gt; varchar(255) NOT NULL,
&lt;cite&gt;weight&lt;/cite&gt; int(11) NOT NULL,
&lt;cite&gt;options&lt;/cite&gt; text,
&lt;cite&gt;flavor&lt;/cite&gt; varchar(64) DEFAULT NULL,
PRIMARY KEY (&lt;cite&gt;name&lt;/cite&gt;),
UNIQUE KEY &lt;cite&gt;uri&lt;/cite&gt; (&lt;cite&gt;uri&lt;/cite&gt;),
CONSTRAINT &lt;cite&gt;Pools_flavor_fk&lt;/cite&gt; FOREIGN KEY (&lt;cite&gt;flavor&lt;/cite&gt;)
REFERENCES &lt;cite&gt;fla&lt;/cite&gt; (&lt;cite&gt;name&lt;/cite&gt;) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Migration strategy for Flavor and Pools table:&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Query all the Pools, and then process every record as follows:&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Find Flavors.name where Flavors.pool_group = Pools.group&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Modify Pools.flavor = Flavors.name&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ol class="arabic simple" start="2"&gt;
&lt;li&gt;&lt;p&gt;For mongodb:&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;The upgrade strategy is similar. We need to introduce a script to implement
the data migration.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;..note:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;Since&lt;/span&gt; &lt;span class="n"&gt;we&lt;/span&gt; &lt;span class="n"&gt;decide&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;remove&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;pool_group&lt;/span&gt; &lt;span class="n"&gt;totally&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;Rocky&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;that&lt;/span&gt; &lt;span class="n"&gt;then&lt;/span&gt; &lt;span class="n"&gt;we&lt;/span&gt; &lt;span class="n"&gt;need&lt;/span&gt;
&lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;provide&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;script&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;help&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;migrate&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;remove&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt;
&lt;span class="n"&gt;pool_group&lt;/span&gt; &lt;span class="n"&gt;column&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;db&lt;/span&gt; &lt;span class="n"&gt;table&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;1. Create flavor API
The Request JSON when create flavor:&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;PUT&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;v2&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;flavors&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;flavor_name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="s2"&gt;"pool_group"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"testgroup"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;# remove pool_group in Rocky release&lt;/span&gt;
  &lt;span class="s2"&gt;"pool_list"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;pool1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pool2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The response JSON when Create flavor:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;Normal response codes: 201

Error response codes:
•BadRequest (400)
•Unauthorized (401)
•Forbidden (403)
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;2. Update flavor API
The Request JSON when update flavor:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt; &lt;span class="n"&gt;PATCH&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;v2&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;flavors&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;flavor_name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="s2"&gt;"pool_group"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"testgroup"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;# remove pool_group in Rocky release&lt;/span&gt;
   &lt;span class="s2"&gt;"pool_list"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;pool1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pool2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pool3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The response JSON when update flavor:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;{
  "href": "/v2/flavors/testflavor",
  "pool_group": "testgroup",# remove pool_group in Rocky release
  "name": "testflavor",
  "capabilities": [
    "FIFO",
    "CLAIMS",
    "DURABILITY",
    "AOD",
    "HIGH_THROUGHPUT"
  ],
  "pool_list": [pool1, pool2, pool3]
}
 Normal response codes: 200

 Error response codes:
 •BadRequest (400)
 •Unauthorized (401)
 •Forbidden (403)
 •Not Found (404)
 •ServiceUnavailable (503)
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;3. Shows details for a flavor API
The response JSON when show details flavor:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;GET&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;v2&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;flavors&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;flavor_name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="s2"&gt;"href"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"/v2/flavors/testflavor"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;"pool_group"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"testgroup"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;# remove pool_group in Rocky release&lt;/span&gt;
  &lt;span class="s2"&gt;"capabilities"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="s2"&gt;"FIFO"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"CLAIMS"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"DURABILITY"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"AOD"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"HIGH_THROUGHPUT"&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="s2"&gt;"pool_list"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;pool1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pool2&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="s2"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"testflavor"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The response JSON when show details flavor:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;Normal response codes: 200

Error response codes:
•BadRequest (400)
•Unauthorized (401)
•Forbidden (403)
•Not Found (404)
•ServiceUnavailable (503)
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;4. List flavor API
The response JSON when list flavors:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;GET&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;v2&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;flavors&lt;/span&gt;

&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="s2"&gt;"flavors"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="s2"&gt;"href"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"/v2/flavors/test_flavor1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s2"&gt;"pool_group"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"testgroup"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;# remove pool_group in Rocky release&lt;/span&gt;
      &lt;span class="s2"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"test_flavor1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s2"&gt;"pool"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"testgroup"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;       &lt;span class="c1"&gt;# remove pool_group in Rocky release&lt;/span&gt;
      &lt;span class="s2"&gt;"pool_list"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;pool1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pool2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="s2"&gt;"href"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"/v2/flavors/test_flavor2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s2"&gt;"pool_group"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"testgroup"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;# remove pool_group in Rocky release&lt;/span&gt;
      &lt;span class="s2"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"test_flavor2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s2"&gt;"pool"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"testgroup"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;       &lt;span class="c1"&gt;# remove pool_group in Rocky release&lt;/span&gt;
      &lt;span class="s2"&gt;"pool_list"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;pool3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pool4&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;"links"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="s2"&gt;"href"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"/v2/flavors?marker=test_flavor2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s2"&gt;"rel"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"next"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The response JSON when list flavors:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;Normal response codes: 200

Error response codes:
•Unauthorized (401)
•Forbidden (403)
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;5. Create pools API
The Request JSON when create pools:&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;PUT&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;v2&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;pools&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;pool_name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;"weight"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"uri"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"mongodb://127.0.0.1:27017"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"options"&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;
        &lt;span class="s2"&gt;"max_retry_sleep"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="s2"&gt;"group"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"poolgroup"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;# remove pool_group in Rocky release&lt;/span&gt;
    &lt;span class="s2"&gt;"flavor"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"testflavor"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The response JSON when Create pools:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;Normal response codes: 201

Error response codes:
•BadRequest (400)
•Unauthorized (401)
••Conflict (409)
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;6. Update pools API
The Request JSON when update pools:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;PATCH&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;v2&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;pools&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;pool_name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="s2"&gt;"weight"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="s2"&gt;"uri"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"mongodb://127.0.0.1:27017"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="s2"&gt;"options"&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;
       &lt;span class="s2"&gt;"max_retry_sleep"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
   &lt;span class="p"&gt;},&lt;/span&gt;
   &lt;span class="s2"&gt;"group"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"newpoolgroup"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;# remove pool_group in Rocky release&lt;/span&gt;
   &lt;span class="s2"&gt;"flavor"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"testflavor1"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The response JSON when update pools:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;{
  "href": "/v2/pools/test_pool",
  "group": "newpoolgroup", # remove pool_group in Rocky release
  "name": "test_pool",
  "weight": 60,
  "uri": "mongodb://127.0.0.1:27017",
  "flavor": "testflavor1"
}
 Normal response codes: 200

 Error response codes:
 •BadRequest (400)
 •Unauthorized (401)
 •Not Found (404)
 •ServiceUnavailable (503)
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;7. Shows details for a pool API
The response JSON when show details pool:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;GET&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;v2&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;pools&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;pool_name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="s2"&gt;"href"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"/v2/pools/test_pool"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;"group"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"testpoolgroup"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;# remove pool_group in Rocky release&lt;/span&gt;
  &lt;span class="s2"&gt;"flavor"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"flavor1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"test_pool"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;"weight"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;"uri"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"mongodb://127.0.0.1:27017"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The response JSON when show details pool:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;Normal response codes: 200

Error response codes:
•BadRequest (400)
•Unauthorized (401)
•ServiceUnavailable (503)
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;8. List pools API
The response JSON when list pools:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;GET&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;v2&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;pools&lt;/span&gt;

&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="s2"&gt;"pools"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="s2"&gt;"href"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"/v2/pools/test_pool1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s2"&gt;"group"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"poolgroup"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;# remove pool_group in Rocky release&lt;/span&gt;
      &lt;span class="s2"&gt;"flavor"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"flavor1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s2"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"test_pool1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s2"&gt;"weight"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s2"&gt;"uri"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"mongodb://192.168.1.10:27017"&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="s2"&gt;"href"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"/v2/pools/test_pool2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s2"&gt;"group"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"poolgroup"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;# remove pool_group in Rocky release&lt;/span&gt;
      &lt;span class="s2"&gt;"flavor"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"flavor1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s2"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"test_pool2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s2"&gt;"weight"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s2"&gt;"uri"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"mongodb://192.168.1.20:27017"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="s2"&gt;"links"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="s2"&gt;"href"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"/v2/pools?marker=test_pool2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s2"&gt;"rel"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"next"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The response JSON when list pools:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;Normal response codes: 200

Error response codes:
•Unauthorized (401)
•Not Found (404)
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;We use the v2 interface, just add pool_list in the flavor API and add the
flavor in the pool API. This can be compatible with the old way.&lt;/p&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;&lt;p&gt;Old Way:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;configure group in pool API and in flavor API;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;New Way:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;configure pool_list in flavor API&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;add a pool to flavor:&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;method one: update pool_list in flavor API&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;method two: config a pool with the flavor in pool API.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;wanghao&amp;lt;&lt;a class="reference external" href="mailto:sxmatch1986%40gmail.com"&gt;sxmatch1986&lt;span&gt;@&lt;/span&gt;gmail&lt;span&gt;.&lt;/span&gt;com&lt;/a&gt;&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Secondary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;gengchc2 &amp;lt;&lt;a class="reference external" href="mailto:geng.changcai2%40zte.com.cn"&gt;geng&lt;span&gt;.&lt;/span&gt;changcai2&lt;span&gt;@&lt;/span&gt;zte&lt;span&gt;.&lt;/span&gt;com&lt;span&gt;.&lt;/span&gt;cn&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;dl class="simple"&gt;
&lt;dt&gt;Target Milestone for completion:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Queens and Rocky&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Modify pool and flavor operation APIs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Modify the related logic codes about group in the zaqar server.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Modify the Data model about Flavors , Pools and PoolGroup.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Modify the related logic codes about group in the zaqar client.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;Both unit and Tempest tests need to be created to cover the code change.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;p&gt;The Zaqar API documentation will need to be updated to reflect the REST
API changes.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
</description><pubDate>Thu, 13 Sep 2018 00:00:00 </pubDate></item><item><title>Queue filter support</title><link>https://specs.openstack.org/openstack/zaqar-specs/specs/rocky/queue-filter-support.html</link><description>
 
&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/zaqar/+spec/queue-filter-support"&gt;https://blueprints.launchpad.net/zaqar/+spec/queue-filter-support&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Metadata is a group of key-value pairs that belong to a queue. When a queue is
created, the user who creates the queue can add the metadata {“keyx”: “valuex”}
to distinguish it. It is necessary for zaqar to support the function of queue
filter so that Users can select the queue by the specified key-value of
metadata. In this blueprints, we will also add queue filter by name.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Zaqar doesn’t support queue filter when queue listing,
we may add this feature now.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;When queue listing, we add filter option in query string parameters
like this&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;GET /v2/queues?key1=value1&amp;amp;key2=value2&amp;amp;name=value3
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;If metadata of queue and name is consistent with the filter, the queues will be
listed to the user, otherwise the queue will be filtered.
If filter option is enabled, the metadata of the queue will be returned
to user.&lt;/p&gt;
&lt;section id="api-impact"&gt;
&lt;h3&gt;API Impact&lt;/h3&gt;
&lt;p&gt;Lists queues:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;GET: /v2/queues?key1=value1&amp;amp;key2=value2

RESPONSE CODE: 200
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="drawbacks"&gt;
&lt;h3&gt;Drawbacks&lt;/h3&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="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;gecong&amp;lt;&lt;a class="reference external" href="mailto:ge.cong%40zte.com.cn"&gt;ge&lt;span&gt;.&lt;/span&gt;cong&lt;span&gt;@&lt;/span&gt;zte&lt;span&gt;.&lt;/span&gt;com&lt;span&gt;.&lt;/span&gt;cn&lt;/a&gt;&amp;gt;&lt;/p&gt;
&lt;/section&gt;
&lt;section id="milestones"&gt;
&lt;h3&gt;Milestones&lt;/h3&gt;
&lt;p&gt;Rocky-1&lt;/p&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;p&gt;#* Add filter parameter for queues listing REST API.
#* Update API reference.
#* Add release note for this feature.
#* UTs for this feature.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
</description><pubDate>Thu, 13 Sep 2018 00:00:00 </pubDate></item><item><title>Remove format constraint of client id</title><link>https://specs.openstack.org/openstack/zaqar-specs/specs/rocky/remove-format-constraint-of-client-id.html</link><description>
 
&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/zaqar/+spec/remove-format-constraint-of-client-id"&gt;https://blueprints.launchpad.net/zaqar/+spec/remove-format-constraint-of-client-id&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Since some clients use different format of client id not only uuid,
so Zaqar will support this function. This also requires user to ensure the
client id is immutable.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Now Zaqar has format constraint to client id, must be UUID format. But this
constraint is not very reasonable under some cases, like user want to use
user id in LDAP as client id, but Zaqar doesn’t allow this now.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Add Three config options:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;‘client_id_uuid_safe’: Defines the format of client id, the value could be
“strict” or “off”. “strict” means the format of client id must be uuid,
“off” means the restriction be removed. The default value is ‘strict’.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;‘min_length_client_id’: Defines the minimum length of client id if remove
the uuid restriction. Default value is 10.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;‘max_length_client_id’: Defines the maximum length of client id if
remove the uuid restriction. Default value is 36.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Will change the method ‘require_client_id’ in wsgi/helpers.py to support
validating the different format of client id.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;section id="api-impact"&gt;
&lt;h3&gt;API Impact&lt;/h3&gt;
&lt;p&gt;For WSGI: Will impact all APIs in v1.1 and v2 version.&lt;/p&gt;
&lt;p&gt;For WebSocket: Will impact message list and message post in v2 version. And we
will support others APIs in following patch.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="drawbacks"&gt;
&lt;h3&gt;Drawbacks&lt;/h3&gt;
&lt;p&gt;There may be a tiny performance impact when user uses very long client id since
Zaqar need to store the client id in storage layer.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="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;wanghao&amp;lt;&lt;a class="reference external" href="mailto:sxmatch1986%40gmail.com"&gt;sxmatch1986&lt;span&gt;@&lt;/span&gt;gmail&lt;span&gt;.&lt;/span&gt;com&lt;/a&gt;&amp;gt;&lt;/p&gt;
&lt;/section&gt;
&lt;section id="milestones"&gt;
&lt;h3&gt;Milestones&lt;/h3&gt;
&lt;p&gt;Rocky-3&lt;/p&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;p&gt;#* Change the Zaqar server code.
#* Update API reference.
#* Add release note for this feature.
#* UTs for this feature.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
</description><pubDate>Thu, 13 Sep 2018 00:00:00 </pubDate></item><item><title>Subscription filtering policies</title><link>https://specs.openstack.org/openstack/zaqar-specs/specs/rocky/subscription-filtering-tags.html</link><description>
 
&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/zaqar/+spec/subscription-filtering-tags"&gt;https://blueprints.launchpad.net/zaqar/+spec/subscription-filtering-tags&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;By default, a subscriber of zaqar topic receives every message published
to the topic. To receive only a subset of the messages, a subscriber assigns
a filter policy to the topic subscription. So in this case, zaqar need to
support message filtering. This function is similar to Amazon SNS message
filtering[1].&lt;/p&gt;
&lt;p&gt;This feature supports all subscription endpoint, including mail, webhook.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;The current subscription lacks flexibility due to the fact that it does
not support message filtering. When a subscriber subscribes to a topic,
all messages which sent to the topic will be sent to this subscriber.
So, this feature is intended to solve the problem, which allows the user
to specify the filter policies when creating a subscription and publish
messages, and ultimately, the filter policies matching decides which subscriber
will receive the message.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;The filter policy is a simple JSON object. The policy contains attributes that
define which messages the subscriber receives. When you publish a message to a
topic, Zaqar compares the message attributes to the attributes in the filter
policy for each of the topic’s subscriptions. If there is a match between the
attributes, Zaqar sends the message to the subscriber. Otherwise, Zaqar skips
the subscriber without sending the message to it.&lt;/p&gt;
&lt;p&gt;With filter policies, you can simplify your message filtering criteria into
your topic subscriptions. With this consolidation, you can offload the message
filtering logic from subscribers and the message routing logic from publishers.
Therefore, you do not need to filter messages by creating a separate topic for
each filtering condition. Instead, you can use a single topic, and you can
differentiate your messages with attributes. Each subscriber receives and
processes only those messages accepted by its filter policy.&lt;/p&gt;
&lt;p&gt;For example, you could use a single topic to publish all messages generated by
transactions from your online retail site. To each message, you could assign an
attribute that indicates the type of transaction, such as order_placed,
order_cancelled, or order_declined. With filter policies, you can route each
message to the different subscriber that is meant to process the message’s
transaction type.&lt;/p&gt;
&lt;p&gt;To do this, a new attribute named &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;filter_policies&lt;/span&gt;&lt;/code&gt; need to be added to both
the message and subscription. Note that this property is optional and does not
affect existing functionality.&lt;/p&gt;
&lt;p&gt;When you create a subscription, you can specify the filter policies,
just like this:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;``{'subscriber': 'http://example.com/order_placed',
   'options':{'filter_policies': ['order_placed']}}``
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Then when you send a message to the topic, you can choose to add the
attribute, just like this:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;``{'body': 'test', 'filter_policies': ['order_placed']}``
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Finally, zaqar decides which subscribers the message should be sent to
according to the following rules:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;If the subscriber does not have any filter_policies, all messages will be
sent to the subscriber.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If the message does not contain any filter_policies, it will not be
sent to the subscriber which has filter_policies.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If the message and the subscriber’s filter_policies have intersecting
collections, the message will be sent to the subscriber.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If the message and the subscriber both have filter_policies, but
there is no intersection set, no message will be sent to the
subscriber.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The relationship of the content in &lt;cite&gt;order_placed&lt;/cite&gt; is &lt;em&gt;or&lt;/em&gt;, it means
that the message will be sent to the subscriptions that match anyone
filters in &lt;cite&gt;order_placed&lt;/cite&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;section id="drawbacks"&gt;
&lt;h3&gt;Drawbacks&lt;/h3&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;cdyangzhenyu &amp;lt;&lt;a class="reference external" href="mailto:cdyangzhenyu%40gmail.com"&gt;cdyangzhenyu&lt;span&gt;@&lt;/span&gt;gmail&lt;span&gt;.&lt;/span&gt;com&lt;/a&gt;&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="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;Rocky-3&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 message subscription process for applying this feature.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add release note for this feature.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update API reference.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add user/developer document for this feature.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Change unit, functional and tempest tests accordingly.&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="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;[1] &lt;a class="reference external" href="https://docs.aws.amazon.com/sns/latest/dg/message-filtering.html"&gt;https://docs.aws.amazon.com/sns/latest/dg/message-filtering.html&lt;/a&gt;&lt;/p&gt;
&lt;/section&gt;
</description><pubDate>Thu, 13 Sep 2018 00:00:00 </pubDate></item><item><title>Delayed Queues</title><link>https://specs.openstack.org/openstack/zaqar-specs/specs/queens/delayed-queues.html</link><description>
 
&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/zaqar/+spec/delayed-queues"&gt;https://blueprints.launchpad.net/zaqar/+spec/delayed-queues&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Delay queues can postpone the delivery of new messages in a queue for a
specific number of seconds. Which is useful for an auditing observer process
the auditor would be guaranteed to see messages before they were claimed,
and could even edit messages if needed.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Now one of the big function gaps of Zaqar is the delayed queue. Currently, all
the message posted to the queue will be visible immediately. That’s enough for
most of the user cases. However, for some user case, user want the message to
be unavailable to end users for a specific period of time.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Generally, a new attribute of queue named &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;_default_message_delay&lt;/span&gt;&lt;/code&gt;.
If the attribute value greater than 0, then queue is a delayed queue,
otherwise, it’s a normal queue.&lt;/p&gt;
&lt;p&gt;All messages sent to the delayed queue can not be immediately claimed and
must wait for a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;delay&lt;/span&gt;&lt;/code&gt;. The &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;delay&lt;/span&gt;&lt;/code&gt; can be set or update as a metadata
when the queue is created.&lt;/p&gt;
&lt;p&gt;Then, when user get or claim messages on a delayed queue, Zaqar will take
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;delay&lt;/span&gt;&lt;/code&gt; as a query condition, which is as below:&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;Message Create + Delay &amp;lt; Current Time&lt;/p&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;Basically, there are 3 scenarios:&lt;/p&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;&lt;p&gt;Normal message sent to delayed queue&lt;/p&gt;
&lt;p&gt;If a normal message without &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;delay&lt;/span&gt;&lt;/code&gt; attribute sent to a delayed queue,
then the message will use the queue’s default delay
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;_default_message_delay&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Message with attribute &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;delay&lt;/span&gt;&lt;/code&gt; sent to delayed queue&lt;/p&gt;
&lt;p&gt;If message with &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;delay&lt;/span&gt;&lt;/code&gt; attribute sent to a delayed queue, then Zaqar will
use the message’s delay seconds value instead of the delayed queue’s delay
seconds value.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Message sent to normal queue&lt;/p&gt;
&lt;p&gt;A normal queue is a queue with the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;_default_message_delay&lt;/span&gt;&lt;/code&gt; value of 0.
Whether the message is a normal message or a message with a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;delay&lt;/span&gt;&lt;/code&gt;
attribute, it will not have a delay feature when it is sent to the normal
queue. Zaqar does not perform conditional filtering on the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;delay&lt;/span&gt;&lt;/code&gt;
attribute when get/claim messages. This means the delay feature does not
affect the performance of normal queue.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Specific implementation steps:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Add a new attribute &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;_default_message_delay&lt;/span&gt;&lt;/code&gt; for all queue’s metadata.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;The attribute &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;_default_message_delay&lt;/span&gt;&lt;/code&gt; default value is 0 means
it is a normal queue. Its ranges from 0 to &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;max_message_delay&lt;/span&gt;&lt;/code&gt;
seconds, the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;max_message_delay&lt;/span&gt;&lt;/code&gt; is configurable and the default
value is 900 seconds (15 mins).&lt;/p&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;ol class="arabic simple" start="2"&gt;
&lt;li&gt;&lt;p&gt;Add a new attribute just for message’s request body: &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;delay&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;When post messages to queue, user can add &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;delay&lt;/span&gt;&lt;/code&gt; like &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ttl&lt;/span&gt;&lt;/code&gt;.
The message’s delay time has a higher priority than queues. If
message &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ttl&lt;/span&gt; &lt;span class="pre"&gt;&amp;lt;&lt;/span&gt; &lt;span class="pre"&gt;delay&lt;/span&gt;&lt;/code&gt;, the message will never be claimed, because
it is in a delay period and the message’s &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ttl&lt;/span&gt;&lt;/code&gt; has expired, so the
message will be deleted by backend.&lt;/p&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;ol class="arabic simple" start="3"&gt;
&lt;li&gt;&lt;p&gt;Add a new field &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;d&lt;/span&gt;&lt;/code&gt; in message backend.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;The field &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;d&lt;/span&gt;&lt;/code&gt; is a delay expires timestamp. It can be saved
to the backend storage. When the timestamp is less than or equal to
the current time, the delay expires.&lt;/p&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;d&lt;/span&gt;&lt;/code&gt; = &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;delay&lt;/span&gt;&lt;/code&gt; + &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;MESSAGE_CREATED_TIMESTAMP&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;ol class="arabic simple" start="4"&gt;
&lt;li&gt;&lt;p&gt;Make sure the message can not be claimed until the delay is expired.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If the queue is a normal queue means the ‘delayed queues’ feature wasn’t
being used, it is necessary to ensure that it is close to zero overhead.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Support for mongo, redis and swift.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;section id="drawbacks"&gt;
&lt;h3&gt;Drawbacks&lt;/h3&gt;
&lt;p&gt;This may introduce a little bit performance impact, because this needs another
new condition for current messages query. But it will not affect the normal
queue too much.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;There is no good option for this feature. User have to wait enough seconds to
get / claim messages against Zaqar.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;cdyangzhenyu &amp;lt;&lt;a class="reference external" href="mailto:cdyangzhenyu%40gmail.com"&gt;cdyangzhenyu&lt;span&gt;@&lt;/span&gt;gmail&lt;span&gt;.&lt;/span&gt;com&lt;/a&gt;&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="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;Queens Q-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;Add mongodb support.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add redis support.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add swift support.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add release note for this feature.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update API reference.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add user/developer document for this feature.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Change unit, functional and tempest tests accordingly.&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;
</description><pubDate>Wed, 04 Jul 2018 00:00:00 </pubDate></item><item><title>Support Checksum Of Message Body</title><link>https://specs.openstack.org/openstack/zaqar-specs/specs/queens/support-md5-of-body.html</link><description>
 
&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/zaqar/+spec/support-md5-of-body"&gt;https://blueprints.launchpad.net/zaqar/+spec/support-md5-of-body&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Now, Zaqar will add a non-URL-encoded message body checksum function.
This is essential for the security of the message body, it can prevent the
message from being tampered.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Currently, Zaqar has no checksum of the non-URL-encoded message body. It is
a good feature for the security of the message body.&lt;/p&gt;
&lt;p&gt;AWS SQS service has supported the function, that would be a good reference for
Zaqar[1].&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;When user claim or get the messages, the checksum will be returned with message
body together, So user can use it to verify that the message body is correct.
Currently zaqar only support the checksum of the non-URL-encoded message body
based on MD5 digests. We may support other algorithms in future versions,
including SHA1, sha256, sha512, and so on. So, It is necessary to change
the following:&lt;/p&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;&lt;p&gt;Add new property named &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;checksum&lt;/span&gt;&lt;/code&gt; for message. This property is
a string type.&lt;/p&gt;
&lt;p&gt;When you send a message to queue, Zaqar will use the default checksum
algorithm MD5 to calculate the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;checksum&lt;/span&gt;&lt;/code&gt; value of the non-URL-encoded
message body. Finally Zaqar will store the value on the backend.
Now the backend Mongodb, Redis and Swift can be supported.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Return the property &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;checksum&lt;/span&gt;&lt;/code&gt; for message when user claims or gets
the message.&lt;/p&gt;
&lt;p&gt;When user gets or claims the message, The API will return the k-v pair of
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;checksum&lt;/span&gt;&lt;/code&gt; in the body of the message. The user can then use this value to
verify that the body of the newly retrieved message is correct or not.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;This feature is backward compatible.&lt;/p&gt;
&lt;p&gt;For old messages that do not have the checksum attribute, the checksum will
return &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;None&lt;/span&gt;&lt;/code&gt; for both &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;claim&lt;/span&gt;&lt;/code&gt; and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;get&lt;/span&gt;&lt;/code&gt; operation. This feature will
also transit smoothly as the old messages gradually expire.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add new data model for message body and queue on different backend.&lt;/p&gt;
&lt;p&gt;MESSAGE:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="o"&gt;+----------------------+---------+&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="n"&gt;Name&lt;/span&gt;                &lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="n"&gt;Field&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;+======================+=========+&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="n"&gt;checksum&lt;/span&gt;            &lt;span class="o"&gt;|&lt;/span&gt;   &lt;span class="n"&gt;cs&lt;/span&gt;   &lt;span class="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;body&lt;/span&gt;                &lt;span class="o"&gt;|&lt;/span&gt;   &lt;span class="n"&gt;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;|&lt;/span&gt;  &lt;span class="o"&gt;...&lt;/span&gt;                 &lt;span class="o"&gt;|&lt;/span&gt;   &lt;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;/li&gt;
&lt;/ol&gt;
&lt;section id="drawbacks"&gt;
&lt;h3&gt;Drawbacks&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;cdyangzhenyu &amp;lt;&lt;a class="reference external" href="mailto:cdyangzhenyu%40gmail.com"&gt;cdyangzhenyu&lt;span&gt;@&lt;/span&gt;gmail&lt;span&gt;.&lt;/span&gt;com&lt;/a&gt;&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="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;Queens RC1&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 message body checksum support for Mongodb, Redis and Swift.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add release note for this feature.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update API reference.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add user/developer document for this feature.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Change unit, functional and tempest tests accordingly.&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="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;[1]:&lt;a class="reference external" href="https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_Message.html"&gt;https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_Message.html&lt;/a&gt;&lt;/p&gt;
&lt;/section&gt;
</description><pubDate>Wed, 04 Jul 2018 00:00:00 </pubDate></item><item><title>The title of your blueprint</title><link>https://specs.openstack.org/openstack/zaqar-specs/specs/backlog-template.html</link><description>
 
&lt;p&gt;Include the URL of your launchpad blueprint:&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/zaqar/+spec/example"&gt;https://blueprints.launchpad.net/zaqar/+spec/example&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Introduction paragraph – why are we doing anything?&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;A detailed description of the problem.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Here is where you cover the change you propose to make in detail. How do you
propose to solve this problem?&lt;/p&gt;
&lt;p&gt;If this is one part of a larger effort make it clear where this piece ends. In
other words, what’s the scope of this effort?&lt;/p&gt;
&lt;section id="drawbacks"&gt;
&lt;h3&gt;Drawbacks&lt;/h3&gt;
&lt;p&gt;Are there any drawbacks in this proposal? Does it change things in the
API? Will it have an impact in critical areas? Will it make other
areas more complex?&lt;/p&gt;
&lt;p&gt;Please, answer any of the questions above or elaborate on the
drawbacks of this proposal if there’re any.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;This is an optional section, where it does apply we’d just like a demonstration
that some thought has been put into why the proposed approach is the best one.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="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;/dl&gt;
&lt;p&gt;Can list additional ids if they intend on doing substantial implementation work
on this blueprint.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;p&gt;Work items or tasks – break the feature up into the things that need to be
done to implement it. Those parts might end up being done by different people,
but we’re mostly trying to understand the timeline for implementation.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Include specific references to specs and/or blueprints in zaqar, or in other
projects, that this one either depends on or is related to.&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, 17 Jan 2018 00:00:00 </pubDate></item><item><title>Email Notification Support</title><link>https://specs.openstack.org/openstack/zaqar-specs/specs/backlog/email-notification.html</link><description>
 
&lt;p&gt;As a notification service, email is one of the importants subscribers we
should support. Given email is the most way to get messages in the modern
world .&lt;/p&gt;
&lt;p&gt;blueprint: &lt;a class="reference external" href="https://blueprints.launchpad.net/zaqar/+spec/email-notification"&gt;https://blueprints.launchpad.net/zaqar/+spec/email-notification&lt;/a&gt;&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Now Zaqar just introduces the notification support in Kilo, but only suppport
webhook driver. The problem is users who do not have a webhook endpoint for
Zaqar to hit, but do have access to email, cannot currently benefit from Zaqar
notifications.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Add a new task driver under /notification/task, which will leverage the
built-in /usr/sbin/sendmail command to send messages.&lt;/p&gt;
&lt;p&gt;Proposed REST API request 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="n"&gt;POST&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;v2&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;queues&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;queue_name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;subscriptions&lt;/span&gt;

&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s1"&gt;'subscriber'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'mailto:fake@gmail.com'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'ttl'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3600&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'options'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;'subject'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'Alarm'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'cc'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt; &lt;span class="s1"&gt;'bcc'&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;The email notification driver will support the standard mailto protocol, that
said, such as subject, cc and bcc could be a part of the ‘subscriber’ attribue.
For example:&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="mailto:someone%40example.com?subject=This%20is%20the%20subject&amp;amp;cc="&gt;mailto:someone&lt;span&gt;@&lt;/span&gt;example&lt;span&gt;.&lt;/span&gt;com?subject=This%20is%20the%20subject&amp;amp;cc=&lt;/a&gt;
&lt;a class="reference external" href="mailto:someone_else%40example.com&amp;amp;body=This%20is%20the%20body"&gt;someone_else&lt;span&gt;@&lt;/span&gt;example&lt;span&gt;.&lt;/span&gt;com&amp;amp;body=This%20is%20the%20body&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Meanwhile, we can also support those email fields in the ‘options’ attribute.&lt;/p&gt;
&lt;p&gt;And to avoid spam, we can send a confirmation email firstly with a
confirm_token, then by default the subcription is in ‘inactive’ status, until
the email owner clicked the URL in the confirmation email. The URL will be like
below:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;/v2/queues/{queue_name}/subscriptions?subscriber=mailto:fake@gmail.com&amp;amp;confirm_token=22c4f150358e4ed287fa51e050d7f024
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Then Zaqar will update the subscription from ‘inactive’ to ‘active’.&lt;/p&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;From the design/architecture perspective, if we don’t have an email driver for
notification, that means we may need a email-sending-as-a-service to achieve
the same goal. It doesn’t make much sense to do that given we can easily do
that by leveraging the mailto in Zaqar’s notification service.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="deployer-impact"&gt;
&lt;h3&gt;Deployer impact&lt;/h3&gt;
&lt;p&gt;Deployers who deploy Zaqar will need to ensure that they have email systems
configured if the email notification is enabled in ‘subscriber_types’.&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;flwang (Feilong Wang)&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: L-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 a task driver for email&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Mail transfer agent needs to be configured on the host.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="testing"&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Unit tests&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Functional test, like sending to $(whoami)@$(hostname) and then check with
‘mail’.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Manual testing&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="documentation-impact"&gt;
&lt;h2&gt;Documentation Impact&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Feature need to be documented&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://docs.python.org/2/library/email-examples.html"&gt;https://docs.python.org/2/library/email-examples.html&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
</description><pubDate>Wed, 17 Jan 2018 00:00:00 </pubDate></item><item><title>Design wire protocol for non RESTFul transports</title><link>https://specs.openstack.org/openstack/zaqar-specs/specs/kilo/define-a-wire-protocol.html</link><description>
 
&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/zaqar/+spec/non-rest-wire-protocol"&gt;https://blueprints.launchpad.net/zaqar/+spec/non-rest-wire-protocol&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This specs represents the work to be done to design a wire protocol that will
respect the current API v1.1 and that will also be useful for non-RESTFul
transmission protocols.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;We currently have a well defined protocol that works well for HTTP. As a
project, we’re looking forward to welcome more transports that will work for
different use-cases but we don’t have a way to support them. This blueprint
aims to define such protocol and the work needed to make it happen.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Based on the existing protocol defined in this wiki page[0] and the rough spec
proposed here[1], I’m proposing we use similar to the one below and complete
the work started by the api-layer blueprint[2].&lt;/p&gt;
&lt;p&gt;This blueprint, however, does not propose an API layer that should be used by
&lt;em&gt;all&lt;/em&gt; transports. Instead, it proposes an API layer that will be used by
transports relying on lower-level transmission protocols like: websocket, raw
tcp, etc.&lt;/p&gt;
&lt;p&gt;Ideally, one would expect Zaqar to support existing protocols like
STOMP, AMQP, etc. While this may/may not be possible depending on the
protocol, we should have a protocol that sticks to the service goals
of being simple, straightforward and lightweight. Other protocols
could be implemented as separate transports in the future.&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;"action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"post_message"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"header"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="s2"&gt;"User-Agent"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"python/2.7 killer-rabbit/1.2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s2"&gt;"Date"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"Wed, 2    8 Nov 2012 21:14:19 GMT"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s2"&gt;"Accept"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"application/x-msgpack"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s2"&gt;"Client-ID"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;30387&lt;/span&gt;&lt;span class="n"&gt;f00&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;39&lt;/span&gt;&lt;span class="n"&gt;a0&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;11e2&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;be4d&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;a8d15f34bae2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s2"&gt;"X-Project-ID"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;518&lt;/span&gt;&lt;span class="n"&gt;b51ea133c4facadae42c328d6b77b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s2"&gt;"X-Auth-Token"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"7d2f63fd-4dcc-4752-8e9b-1d08f989cc00"&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="s2"&gt;"body"&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="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;[0] &lt;a class="reference external" href="https://wiki.openstack.org/wiki/Zaqar/specs/api/v1.1"&gt;https://wiki.openstack.org/wiki/Zaqar/specs/api/v1.1&lt;/a&gt;
[1] &lt;a class="reference external" href="https://wiki.openstack.org/wiki/Zaqar/specs/zmq/api/v1"&gt;https://wiki.openstack.org/wiki/Zaqar/specs/zmq/api/v1&lt;/a&gt;
[2] &lt;a class="reference external" href="https://blueprints.launchpad.net/zaqar/+spec/cross-transport-api-spec"&gt;https://blueprints.launchpad.net/zaqar/+spec/cross-transport-api-spec&lt;/a&gt;&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;Don’t do anything and let each transport implement it’s protocol.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Implement a transport on top of a different protocol&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;flaper87&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;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Define the wire protocol&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create an API manager that process messages&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;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, 17 Jan 2018 00:00:00 </pubDate></item><item><title>Zaqar’s notification semantics</title><link>https://specs.openstack.org/openstack/zaqar-specs/specs/kilo/notification-api.html</link><description>
 
&lt;p&gt;One of Zaqar’s goals, from an API semantics perspective, is to provide
support for push notifications - or subscriptions, if you will. After
having added support for all the queuing related semantcis to Zaqar’s
API, we can start adding support for other things that sit on top of
the existing semantics like the ones mentioned in this spec.&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/zaqar/+spec/notifications"&gt;https://blueprints.launchpad.net/zaqar/+spec/notifications&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Other references:
- &lt;a class="reference external" href="https://etherpad.openstack.org/p/marconi-notifications-brainstorm"&gt;https://etherpad.openstack.org/p/marconi-notifications-brainstorm&lt;/a&gt;
- &lt;a class="reference external" href="https://etherpad.openstack.org/p/juno-marconi-notifications-on-marconi"&gt;https://etherpad.openstack.org/p/juno-marconi-notifications-on-marconi&lt;/a&gt;
- &lt;a class="reference external" href="https://etherpad.openstack.org/p/IcehouseMarconiNotificationService"&gt;https://etherpad.openstack.org/p/IcehouseMarconiNotificationService&lt;/a&gt;
- &lt;a class="reference external" href="https://www.dropbox.com/s/d2q1viz4ejebg24/marconi-notifications.png"&gt;https://www.dropbox.com/s/d2q1viz4ejebg24/marconi-notifications.png&lt;/a&gt;&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Zaqar’s support for queuing semantics that allow users to publish and
consume messages to and from the service. These semantics cover
several use-cases but they leave out others like ‘listening’ for
messages. There are, as well as for prod/cons scenarios, many
use-cases for pub/sub that need to be supported. Some examples of such
use-cases are: mobile push notifications, support for events
triggering, meetering, etc.&lt;/p&gt;
&lt;p&gt;In order to cover the above scenarios, Zaqar needs to provide an API
that will allow users for subscribing to specific queues and get
messages from there without requiring to poll. This will allow for a
better architecture on the client side, a more reliable interaction
between Zaqar and the client in terms of connection management and it
also opens the doors for supporting other scenarios.&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 extend Zaqar’s API with support for subscriptions
without adding a separate service - please see the section below with
regards to both services being merged. This proposal introduces the
high-level changes required for this feature but the detailed API
specification has yet to be written.&lt;/p&gt;
&lt;p&gt;Here’s a, non-exahustive, list of resources required to support
notifications:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Subscriptions&lt;/strong&gt;: Subscriptions define what the subscriber wants to
listen on. It contains the data of the queues/topics, routing
parameters, maximum retries and other configirations required to
correctly filter messages and keep the high-level guarantees.&lt;/p&gt;
&lt;p&gt;A subscription is used by subscribers to listen on things. A non
persistent subscriber - webhooks, sms, mobile push protocols - are
configured in the subscription itself, whereas other subscribers using
persistent connection can load a specific subscription they want to
listen on.&lt;/p&gt;
&lt;p&gt;A subscription consists in a object containing the information of the
source, destination, expiration and a custom field that contains
information useful for the notifier.&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;POST&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;v2&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;queues&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;queue_name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;subscriptions&lt;/span&gt;

&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s1"&gt;'subscriber'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'http://trigger.me'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'ttl'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3600&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'options'&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;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;source&lt;/strong&gt;: The source queue for notifications&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;subscriber&lt;/strong&gt;: The subscriber URI. This can be any of the supported
subscriber URI and the implementation must be based on stevedore to
allow external contributions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;ttl&lt;/strong&gt;: time to live for this subscription. It’s a positive number
that expresses, in seconds, how long a subscription should exist. If
omitted the subscription won’t expire.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;options&lt;/strong&gt;: publisher specific options.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Publishers&lt;/strong&gt;: Publishers are users and/or third-party resources
publishing messages to the notification endpoints. Users publishing
messages to Zaqar don’t need any specialized endpoint for
this. Messages must go through the normal and already implemented
message publishing API. However, third-party publishers require a
specific configuration. Third-party publishers consume messages from
other services and publish them in zaqar’s queues.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Workers&lt;/strong&gt;: Publishing tasks need to be executed in a distributed -
or local to the node - fashion, they need to be reliable,
fault-tolerant and atomic. To do so, I’ve evaluated taskflow as a
valid library for this job. Taskflow has support for
local/distributed, blocking/concurrent task execution. It provides
support for several execution models, persistence layers - including
sqlite, mysql and zookeeper - and it has support for retries. The
alternative to taskflow is writing our on implementation for this
work, which doesn’t seem to be worth it at this stage.&lt;/p&gt;
&lt;section id="push-protocols"&gt;
&lt;h3&gt;Push Protocols&lt;/h3&gt;
&lt;p&gt;There are several types of push technologies that could be supported,
therefore the implementation must be generic enough to allow for new
implementations to be done easily and also as external plugins.&lt;/p&gt;
&lt;p&gt;Nonetheless, this spec proposes starting with just the first of the
plugins proposed below:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Webhooks&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Email&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Mobile push&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;SMS&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="why-not-2-services"&gt;
&lt;h3&gt;Why not 2 services&lt;/h3&gt;
&lt;p&gt;Zaqar has stated since its inception that it provides a single common
API for things that other cloud services like AWS have in 2 separate
services. Nonetheless, I think the real motivations for these 2 API’s
to be under the same service are:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Maintenance: It’s easier to maintain and scale just 1 service type
than a group of different services.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Consistency: It’ll help reducing the code needed to implement the
notification API since they both will be running under the same
structure and users will know where to find the services easily.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Performance: Implementing the notification API in a separte service
will require a communication between that service and the queuing
service. At least, it’ll require a constant polling from the backend
(if it doesn’t support push itself). By having everything under the
same service, we can trigger notification for messages as they come
in.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="future-improvements"&gt;
&lt;h3&gt;Future Improvements&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Support for subscription’s confirmation&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Split the above into 2 different services. As mentioned in the
previous section, 2 services don’t seem to be the ideal solution for
this.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;flwang&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Secondary assignees:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;flaper87&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="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;Work on the detailed API spec&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Write storage code for notifications&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Implement the API on top of the storage code.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Work on the publishers&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;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, 17 Jan 2018 00:00:00 </pubDate></item><item><title>Expose storage capabilities</title><link>https://specs.openstack.org/openstack/zaqar-specs/specs/kilo/storage-capabilities.html</link><description>
 
&lt;p&gt;Flavors allow operators to expose some of the internal storage capabilities
without giving the exact details of how the system is configured. As of now,
the operators has total control over what capabilities are exposed to the user
regardeless on whether these capabilities are indeed guaranteed or valid. A
&lt;cite&gt;capability&lt;/cite&gt; is a feature that is either specific to the storage or to
Zaqar - durable, fifo, in-memory, for example - and they can be enabled/exposed
in a per-flavor basis allowing end-users to choose the best flavor for a
specific queue.&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/zaqar/+spec/expose-storage-capabilities"&gt;https://blueprints.launchpad.net/zaqar/+spec/expose-storage-capabilities&lt;/a&gt;&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Flavors are very powerful when it comes to give choices to end-users without
taking control out from operators. However, there’s no way for operators to
know what capabilities each storage driver has, which makes this feature
completely custom to whatever the operator thinks makes more sense.&lt;/p&gt;
&lt;p&gt;It’s important to support operators on the choice of what features are exposed
to the end-users through the API by making it clear which are supported by the
drivers that have been deployed. Moreover, this is also important for doing a
proper capacity planning based on the use-cases the service is trying to
support.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;section id="capabilities"&gt;
&lt;h3&gt;Capabilities&lt;/h3&gt;
&lt;p&gt;This change request proposes defining a set of internal &lt;cite&gt;capabilities&lt;/cite&gt; and a
way for storage drivers to expose which capabilities are supported so that
operators may know in advance what a flavor would support and what storage
drivers they may need.&lt;/p&gt;
&lt;p&gt;The set of internal capabilities includes:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;FIFO&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;AOD (At least once delivery)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;high-throughput&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;claims&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="exposing-capabilities"&gt;
&lt;h3&gt;Exposing Capabilities&lt;/h3&gt;
&lt;p&gt;This capabilities should be exposed by the storage driver iff supported. This
spec proposes adding a new class method to the base class called &lt;cite&gt;capabilities&lt;/cite&gt;
that should return a set with a list of supported &lt;cite&gt;capabilities&lt;/cite&gt;. The
capabilities returned in this set cannot be custom, which means they must be
supported internally.:&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;@six&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add_metaclass&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;abc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ABCMeta&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;DataDriverBase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DriverBase&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="o"&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;capabilities&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;_CAPABILITIES&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="drivers-load"&gt;
&lt;h3&gt;Drivers Load&lt;/h3&gt;
&lt;p&gt;In addition to the above-mentioned changes, we also need a better way to load
drivers based on the capabilities. That is, when drivers are loaded, it’s
necessary to pass down to the driver the capabilities that have been enabled
per-flavor so that the driver itself can be specialized for some capabilities.
In most of the cases, loading a driver will end up in always loading the same
implementation. However, there are cases - FIFO, for example - where more
specialized implementations may be needed depending on the storage. Therefore,
instead of &lt;em&gt;always&lt;/em&gt; loading the &lt;cite&gt;DataDriver&lt;/cite&gt;, this spec proposes adding a new
&lt;cite&gt;get_driver&lt;/cite&gt; function that will let the storage itself load a driver according
to the capabilities passed there.:&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_driver&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;plane&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'data'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;capabilities&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="o"&gt;...&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;This means we won’t need to register neither &lt;cite&gt;DataDriver`s nor `ControlDriver`s
as `entry_points&lt;/cite&gt; but just the new &lt;cite&gt;get_driver&lt;/cite&gt; function. This will allow
storage driver’s to expose fewer things as public API’s. A variant for the
above &lt;cite&gt;get_driver&lt;/cite&gt; proposal would be.:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_driver&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;base&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;BaseDataDriver&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;capabilities&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="o"&gt;...&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;This way we can avoid giving ‘names’ to this planes and just ask what we need
in terms of ‘signature’. However, it makes loading the actual driver a bit more
complex and it’ll also duplicate some logic across different storage drivers.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="pools-and-flavors"&gt;
&lt;h3&gt;Pools and Flavors&lt;/h3&gt;
&lt;p&gt;Flavors have support for capabilities. As of now, these capabilities
are 100% custom. With the implementation of this spec, it’ll be
possible for flavors to know in advance what capabilities are
supported based on the stores registered in the pool.&lt;/p&gt;
&lt;p&gt;Pools, however, shouldn’t allow storage drivers with different
capabilities to co-exist under the same pool. That is to say that
pools will have to verify the storage capabilities when new nodes are
added to the pool and ensure that the capabilities supported by the
new node are consistent with the rest of the nodes in the pool.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Keep it custom and 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;flaper87&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Secondary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;vkmc&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;K-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;Define list of internal capabilities and document it&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add required abstractions to storage drivers to expose the supported
capabilities&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Let flavor’s pass the capabilities down to the storage driver when it’s being
loaded.&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;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, 17 Jan 2018 00:00:00 </pubDate></item><item><title>Authorization Policy Support</title><link>https://specs.openstack.org/openstack/zaqar-specs/specs/liberty/policy_support.html</link><description>
 
&lt;p&gt;OpenStack components are supposed to check user privileges to perform any
action. Generally these checks are role-based. See
&lt;a class="reference external" href="https://docs.openstack.org/keystone/latest/#approach-to-authorization-policy"&gt;https://docs.openstack.org/keystone/latest/#approach-to-authorization-policy&lt;/a&gt;.
Zaqar needs to support policies as well.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Presently Zaqar is missing fine-grained permissions for actions. For example,
it’s hard to allow one user only can get message from a queue but not be able
to post message to the queue, or something like that.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Add policy check for all Zaqar API endpoints. This could be done by following
the same way as in other OpenStack components, by leveraging the oslo.policy
module which will do all the underlying work.&lt;/p&gt;
&lt;p&gt;The implementation should be fairly simple, with oslo.policy’s &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Enforcer&lt;/span&gt;&lt;/code&gt;
class being instantiated with the policy file, then the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;enforce&lt;/span&gt;&lt;/code&gt; method used
to check each API call.&lt;/p&gt;
&lt;p&gt;Proposed content of the policy file:&lt;/p&gt;
&lt;div class="highlight-json notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nt"&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="nt"&gt;"admin_or_owner"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="s2"&gt;"is_admin:True or project_id:%(project_id)s"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nt"&gt;"default"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"rule:admin_or_owner"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="nt"&gt;"queues:get_all"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nt"&gt;"queues:put"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nt"&gt;"queues:get"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nt"&gt;"queues:delete"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="nt"&gt;"messages:post"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nt"&gt;"messages:get"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nt"&gt;"messages:bulk_get"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nt"&gt;"messages:bulk_delete"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nt"&gt;"messages:claim"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="nt"&gt;"subscriptions:get_all"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nt"&gt;"subscriptions:create"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nt"&gt;"subscriptions:get"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nt"&gt;"subscriptions:delete"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nt"&gt;"subscriptions:update"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="rest-api-impact"&gt;
&lt;h3&gt;REST API impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="other-end-user-impact"&gt;
&lt;h3&gt;Other end user impact&lt;/h3&gt;
&lt;p&gt;None.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="deployer-impact"&gt;
&lt;h3&gt;Deployer impact&lt;/h3&gt;
&lt;p&gt;An additional file, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;policy.json&lt;/span&gt;&lt;/code&gt; must be deployed. The deployer should
verify the settings in that file are correct for their deployment, such that
the correct users are allowed access.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="developer-impact"&gt;
&lt;h3&gt;Developer impact&lt;/h3&gt;
&lt;p&gt;If there is any new API endpoint added for Zaqar, then policy rules in the
json files should be updated accordingly.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;kragniz (Louis Taylor)&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: L-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 config options to point to control policy file and settings&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add policy check to all API calls&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add unit tests&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add documentation&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;oslo.policy&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://docs.openstack.org/keystone/latest/#approach-to-authorization-policy"&gt;https://docs.openstack.org/keystone/latest/#approach-to-authorization-policy&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://docs.openstack.org/keystone/latest/configuration/config-options.html#policy"&gt;https://docs.openstack.org/keystone/latest/configuration/config-options.html#policy&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://docs.openstack.org/keystone/latest/#keystone-api-protection-with-role-based-access-control-rbac"&gt;https://docs.openstack.org/keystone/latest/#keystone-api-protection-with-role-based-access-control-rbac&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
</description><pubDate>Wed, 17 Jan 2018 00:00:00 </pubDate></item><item><title>Pre-Signed URLs</title><link>https://specs.openstack.org/openstack/zaqar-specs/specs/liberty/pre-signed-url.html</link><description>
 
&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/zaqar/+spec/pre-signed-url"&gt;https://blueprints.launchpad.net/zaqar/+spec/pre-signed-url&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;There’s a need to have pre-signed URLs - ala Swift’s tempURL - that
would grant temporary access, to non-authenticated users, to specific
queues.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;In cases where there’s a need to allow “outsiders” of the system - i.e
guest-agents - to interact with Zaqar, it’s useful to have a way to
grant them access so that they can do whatever is needed without
giving these “outsiders” a username and password or any other kind of
permission in the system.&lt;/p&gt;
&lt;p&gt;This access, however, needs to be temporary, revocable and
granular. Outsiders shouldn’t get access to more than 1 resource at a
time and the permissions granted should identify what kind of
operations they can execute.&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 to the aforementioned problem is to use
pre-signed URLs. Services like Swift use a similar approach - called
temp URL there - to provide access to internal resources. The
pre-signed URL consists of a URL that contains a &lt;cite&gt;hash&lt;/cite&gt; with the
encoded permissions.&lt;/p&gt;
&lt;p&gt;In order to make it easier to read/write this spec, let’s split it in
several parts. The first part will describe the parts composing the
URL. The second part will describe how the URL will be generated and
the third part how it’ll be consumed.&lt;/p&gt;
&lt;section id="pre-signed-url"&gt;
&lt;h3&gt;Pre-Signed URL&lt;/h3&gt;
&lt;p&gt;A pre-signed URL ought to contain enough information for it to provide
enough control over the resource being shared, without compromising
security. Authorization is a must have and a huge part of this
URL. Therefore, the information present in this URL has to be
exhaustive in that perspective.&lt;/p&gt;
&lt;p&gt;As mentioned in a previous paragraph, the URL contains a hashed piece
of information that serializes the required fields. Those fields are:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Project: The &lt;cite&gt;keystone&lt;/cite&gt; tenant of the entity generating the URL&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;TTL: Expiration time (in seconds) for the URL&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Queue: &lt;cite&gt;Zaqar&lt;/cite&gt;’s queue name that this URL gives access to&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;HTTP Method: The &lt;cite&gt;HTTP&lt;/cite&gt; method(s) this &lt;cite&gt;URL&lt;/cite&gt; was created for. By
selecting the HTTP method, it’s possible to give either read or
read/write access to a specific resource.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The above fields will be part of the generated hash but they’ll also
be available as public information in the URL. The reason they’re
encoded is to have a way to verify that the URL has not been changed
by the user whenever a request is made to &lt;cite&gt;Zaqar&lt;/cite&gt;.&lt;/p&gt;
&lt;p&gt;The generated hash will be an HMAC-SHA1. To generate such signature,
it is required to have a secret key. In swift, it’s possible to have a
key per-account. Unfortunately, that’s not possible in Zaqar +
Keystone, therefore this spec proposes adding a new configuration
option that will contain the key to use.:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;signed_url&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;secret_key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;some&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;very&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;strong&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="url-generation"&gt;
&lt;h3&gt;URL Generation&lt;/h3&gt;
&lt;p&gt;This spec proposes adding a new endpoint in the queue namespace that
returns the generated signature and expiration time that’ll grant
access to this resource. The request and response for this operation:&lt;/p&gt;
&lt;p&gt;Request::&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;POST&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;v2&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;queues&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;shared_queue&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;share&lt;/span&gt; &lt;span class="n"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mf"&gt;1.1&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;

&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s1"&gt;'methods'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'GET'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'POST'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Response::&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;HTTP&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt; &lt;span class="mi"&gt;201&lt;/span&gt; &lt;span class="n"&gt;OK&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;

&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s1"&gt;'signature'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'518b51ea133c4facadae42c328d6b77b'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'expires'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2015&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;05&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;31&lt;/span&gt;&lt;span class="n"&gt;T19&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;00&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;17&lt;/span&gt;&lt;span class="n"&gt;Z&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="s1"&gt;'7d2f63fd4dcc47528e9b1d08f989cc00'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'url'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'/v2/queues/shared_queue/messages'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'methods'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'GET'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'POST'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;This request sets a different expiration date for the URL. Note that
the default method is &lt;cite&gt;GET&lt;/cite&gt;.&lt;/p&gt;
&lt;p&gt;Request::&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;POST&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;v2&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;queues&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;shared_queue&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;share&lt;/span&gt; &lt;span class="n"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mf"&gt;1.1&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;

&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s1"&gt;'expires'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2015&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;06&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;19&lt;/span&gt;&lt;span class="n"&gt;T19&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;00&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;00&lt;/span&gt;&lt;span class="n"&gt;Z&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Response::&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt; &lt;span class="mi"&gt;201&lt;/span&gt; &lt;span class="n"&gt;OK&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;

&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s1"&gt;'signature'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'518b51ea133c4facadae42c328d6b77b'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'expires'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2015&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;06&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;19&lt;/span&gt;&lt;span class="n"&gt;T19&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;00&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;00&lt;/span&gt;&lt;span class="n"&gt;Z&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="s1"&gt;'7d2f63fd4dcc47528e9b1d08f989cc00'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'url'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'/v2/queues/shared_queue/messages'&lt;/span&gt;
    &lt;span class="s1"&gt;'methods'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'GET'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;This request combines both parameters (methods and expires):&lt;/p&gt;
&lt;p&gt;Request::&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;POST&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;v2&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;queues&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;shared_queue&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;share&lt;/span&gt; &lt;span class="n"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mf"&gt;1.1&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;

&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s1"&gt;'methods'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'GET'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'POST'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="s1"&gt;'expires'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2015&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;06&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;19&lt;/span&gt;&lt;span class="n"&gt;T19&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;00&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;00&lt;/span&gt;&lt;span class="n"&gt;Z&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Response::&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt; &lt;span class="mi"&gt;201&lt;/span&gt; &lt;span class="n"&gt;OK&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;

&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s1"&gt;'signature'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'518b51ea133c4facadae42c328d6b77b'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'expires'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2015&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;06&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;19&lt;/span&gt;&lt;span class="n"&gt;T19&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;00&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;00&lt;/span&gt;&lt;span class="n"&gt;Z&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="s1"&gt;'7d2f63fd4dcc47528e9b1d08f989cc00'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'url'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'/v2/queues/shared_queue/messages'&lt;/span&gt;
    &lt;span class="s1"&gt;'methods'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'GET'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'POST'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="consuming-the-url"&gt;
&lt;h3&gt;Consuming the URL&lt;/h3&gt;
&lt;p&gt;First and foremost, it’s important to mention that &lt;strong&gt;NONE&lt;/strong&gt; of the
URL headers can/should be modified and/or omitted. As soon as one of
them is, the signature verification will fail and therefore the
request will respond 404.&lt;/p&gt;
&lt;p&gt;Requests for pre-signed URLs will be processed by a middleware that
should be placed &lt;strong&gt;before&lt;/strong&gt; keystone’s middleware. This will allow us
to authenticate the request in advance and skip keystone’s
authentication. A request using the signature generated in the
previous section would look like:&lt;/p&gt;
&lt;p&gt;Request::&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;GET&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;v2&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;queues&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;shared_queue&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;messages&lt;/span&gt; &lt;span class="n"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mf"&gt;1.1&lt;/span&gt;
&lt;span class="n"&gt;Host&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;zaqar&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;example&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;com&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;Agent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;python&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mf"&gt;2.7&lt;/span&gt; &lt;span class="n"&gt;killer&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;rabbit&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mf"&gt;1.2&lt;/span&gt;
&lt;span class="n"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Wed&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;28&lt;/span&gt; &lt;span class="n"&gt;Nov&lt;/span&gt; &lt;span class="mi"&gt;2012&lt;/span&gt; &lt;span class="mi"&gt;21&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;19&lt;/span&gt; &lt;span class="n"&gt;GMT&lt;/span&gt;
&lt;span class="n"&gt;Accept&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;application&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;
&lt;span class="n"&gt;Accept&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Encoding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;gzip&lt;/span&gt;
&lt;span class="n"&gt;URL&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Signature&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;518&lt;/span&gt;&lt;span class="n"&gt;b51ea133c4facadae42c328d6b77b&lt;/span&gt;
&lt;span class="n"&gt;URL&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Expires&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2015&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;05&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;31&lt;/span&gt;&lt;span class="n"&gt;T19&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;00&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;17&lt;/span&gt;&lt;span class="n"&gt;Z&lt;/span&gt;
&lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Project&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="n"&gt;d2f63fd4dcc47528e9b1d08f989cc00&lt;/span&gt;
&lt;span class="n"&gt;Client&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;30387&lt;/span&gt;&lt;span class="n"&gt;f00&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;39&lt;/span&gt;&lt;span class="n"&gt;a0&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;11e2&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;be4d&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;a8d15f34bae2&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Note that, in the above example, headers were chosen over query
parameters. The main 2 reasons behind this choice are:&lt;/p&gt;
&lt;p&gt;1. Consistency with other security related parameters - i.e
X-Project-Id - that are sent in HTTP headers.&lt;/p&gt;
&lt;p&gt;2. These new parameters don’t belong in the &lt;cite&gt;messages&lt;/cite&gt; request and
won’t affect &lt;cite&gt;messages&lt;/cite&gt; navigation.&lt;/p&gt;
&lt;p&gt;Similarly, other requests like the one below can be done.&lt;/p&gt;
&lt;p&gt;Request::&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;GET /v2/queues/shared_queue/messages?marker=1355-237242-783&amp;amp;limit=10 HTTP/1.1
Host: zaqar.example.com
User-Agent: python/2.7 killer-rabbit/1.2
Date: Wed, 28 Nov 2012 21:14:19 GMT
Accept: application/json
Accept-Encoding: gzip
URL-Signature: 518b51ea133c4facadae42c328d6b77b
URL-Expires: 2015-05-31T19:00:17Z
X-Project-Id: 7d2f63fd4dcc47528e9b1d08f989cc00
Client-ID: 30387f00-39a0-11e2-be4d-a8d15f34bae2
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Filtering and pagination are not part of the signature and fall into
the &lt;cite&gt;read&lt;/cite&gt; permissions that were granted on this.&lt;/p&gt;
&lt;p&gt;Posting messages will work the same way:&lt;/p&gt;
&lt;p&gt;Request::&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;POST&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;v2&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;queues&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;shared_queue&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;messages&lt;/span&gt; &lt;span class="n"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mf"&gt;1.1&lt;/span&gt;
&lt;span class="n"&gt;Host&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;zaqar&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;example&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;com&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;Agent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;python&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mf"&gt;2.7&lt;/span&gt; &lt;span class="n"&gt;killer&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;rabbit&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mf"&gt;1.2&lt;/span&gt;
&lt;span class="n"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Wed&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;28&lt;/span&gt; &lt;span class="n"&gt;Nov&lt;/span&gt; &lt;span class="mi"&gt;2012&lt;/span&gt; &lt;span class="mi"&gt;21&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;19&lt;/span&gt; &lt;span class="n"&gt;GMT&lt;/span&gt;
&lt;span class="n"&gt;Accept&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;application&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;
&lt;span class="n"&gt;Accept&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Encoding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;gzip&lt;/span&gt;
&lt;span class="n"&gt;URL&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Signature&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;518&lt;/span&gt;&lt;span class="n"&gt;b51ea133c4facadae42c328d6b77b&lt;/span&gt;
&lt;span class="n"&gt;URL&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Expires&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2015&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;05&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;31&lt;/span&gt;&lt;span class="n"&gt;T19&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;00&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;17&lt;/span&gt;&lt;span class="n"&gt;Z&lt;/span&gt;
&lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Project&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="n"&gt;d2f63fd4dcc47528e9b1d08f989cc00&lt;/span&gt;
&lt;span class="n"&gt;Client&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;30387&lt;/span&gt;&lt;span class="n"&gt;f00&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;39&lt;/span&gt;&lt;span class="n"&gt;a0&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;11e2&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;be4d&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;a8d15f34bae2&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="other-notes"&gt;
&lt;h3&gt;Other Notes&lt;/h3&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;In the case of pre-signed URLs, the queue cannot be created
lazily. This is to prevent cases where queues are deleted and
users still have a valid URL. This is not a big issues in cases
where there’s just 1 pool. However, if there’s a deployment using
more than 1 type of pool, the lazily created queue may end up in an
undesired pool and it’d be possible for an attacker to try a DoS on
that pool. Therefore, whenever a pre-signed URL is created, if a
pool doesn’t exist, one will be created.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I’m not a fan of passing the &lt;cite&gt;project-id&lt;/cite&gt; around but I can’t think
of another way to do this and still have the ability to preserve
multi-tenancy without passing the project.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I don’t like having the key set in the config file. In future
versions, we could think of making this information part of the
queue itself. The reason we can’t do that right now is because we
don’t have private fields in the metadata. It should be easy enough
to do it as an enhancement for this feature.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As a future enhancement, we could also use Barbican for key management.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
&lt;section id="drawbacks"&gt;
&lt;h3&gt;Drawbacks&lt;/h3&gt;
&lt;p&gt;Security issues may be added by this work. We ought to be extra
careful on reviews and create a vulnerability team that is ready to
address any issues that might come up.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;flaper87&lt;/p&gt;
&lt;/dd&gt;
&lt;/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;Write utilities to generate the signature with proper tests&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add the endpoint that generates the pre-signed URL&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create a middleware capable of processing these URL&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;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, 17 Jan 2018 00:00:00 </pubDate></item><item><title>Tests refactoring</title><link>https://specs.openstack.org/openstack/zaqar-specs/specs/liberty/tests-refactoring.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/zaqar/+spec/tests-refactoring"&gt;https://blueprints.launchpad.net/zaqar/+spec/tests-refactoring&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Zaqar tests are currently split into 2 different places, we want to reunite
them.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Tests currently exists in the tests top directory in the tree, but most of them
import abstract base classes from the zaqar.tests python package and set
attributes to be able to run them. There are also some tests definition in the
tests directory. It’s not obvious that tests in the zaqar.tests package are not
run when using tox and in the gate, and it creates confusion on where the tests
should properly live.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Move all the tests in the zaqar.tests package, and delete the tests directory.&lt;/p&gt;
&lt;p&gt;To be able to have a reviewable stream, we will slowly add directories in
zaqar/tests to the testrepository configuration, and move them in small chunks.&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&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;therve&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;Add one tests directory to .testr.conf and move the tests over&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Iterate over all the tests directories in zaqar/tests&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Move remaining tests out of tests/&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;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, 17 Jan 2018 00:00:00 </pubDate></item><item><title>More reserved queue attributes</title><link>https://specs.openstack.org/openstack/zaqar-specs/specs/mitaka/more-reserved-queue-attributes.html</link><description>
 
&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/zaqar/+spec/more-reserved-queue-attributes"&gt;https://blueprints.launchpad.net/zaqar/+spec/more-reserved-queue-attributes&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Currently Zaqar supports setting metadata/attributes when user creating queue.
However, the metadata/attributes are not used very much by Zaqar itself.
Now we only support ‘_flavor’ but it would be nice if we can support
more attributes to make the queue more flexible.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Now Zaqar supports max_messages_post_size, default_message_ttl,
default_claim_ttl and default_claim_grace. All of them defined in Zaqar’s
configuration file. That means it’s global setting, all queues have to share
the same configurations. It’s not really flexible from the end user
perspective. So it would be nice if we can let end user set them and use
the default value in configuration file if they are not defined.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;The changes are not complicated, which may change two actions: Post messages
and create claim for a queue.&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Post Message:
At line stable/liberty/zaqar/transport/wsgi/v2_0/messages.py#L182, we need
to get the queue’s metadata so as to get the queue’s max_messages_post_size
and ttl defined by user when creating the queue. If those aren’t exist,
then just use the global configuration defined in configuration file.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create Claim:
Similar thing like above, we need to get the queue’s metadata at line
stable/liberty/zaqar/transport/wsgi/v2_0/claims.py#L81 and then use that
to do the check.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;section id="drawbacks"&gt;
&lt;h3&gt;Drawbacks&lt;/h3&gt;
&lt;p&gt;It may introduce a tiny performance impact for message posting and claim
creating. For example, instead of just checking if the queue is existing or
not, Zaqar need to get the queue’s metadata so that to get those attributes.
But actually, we can use ‘get_metadata’ replace ‘exists’ to check if the queue
exist or not, and they’re calling the same collection.find_one() method, so
technically, there is no performance impact.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Just keep current way, let all the queues share the same configurations.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;flwang (&lt;a class="reference external" href="mailto:flwang%40catalyst.net.nz"&gt;flwang&lt;span&gt;@&lt;/span&gt;catalyst&lt;span&gt;.&lt;/span&gt;net&lt;span&gt;.&lt;/span&gt;nz&lt;/a&gt;)&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Support max_messages_size and ttl as queue attributes&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Support claim_ttl and claim_grace as queue attributes&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;N/A&lt;/p&gt;
&lt;/section&gt;
</description><pubDate>Wed, 17 Jan 2018 00:00:00 </pubDate></item><item><title>Support for binary data in the websocket transport</title><link>https://specs.openstack.org/openstack/zaqar-specs/specs/mitaka/websocket-binary-support.html</link><description>
 
&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/zaqar/+spec/websocket-binary-support"&gt;https://blueprints.launchpad.net/zaqar/+spec/websocket-binary-support&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Implement support for binary communications over websocket transport which will
allow to reduce network traffic between Zaqar and it’s clients and also to
increase performance.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Currently websocket transport uses only text messages packed in JSON format to
exchange data with clients.&lt;/p&gt;
&lt;p&gt;An attempt to send binary data to Zaqar’s websocket transport will lead to
receiving ‘bad request’ (HTTP error 400) response from Zaqar.&lt;/p&gt;
&lt;p&gt;But websocket protocol actually allows communication via binary messages.
Data packed(serialized) in binary format can be smaller and also may take less
CPU time to pack/unpack it.&lt;/p&gt;
&lt;p&gt;By using binary messages for communications it’s possible to reduce network
traffic between Zaqar and it’s clients and also to increase Zaqar’s
performance. It can also increase client performance if the client is not
written in JavaScript.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;We can serialize/deserialize data via MsgPack technology which was already
proposed and approved in &lt;a class="reference external" href="https://github.com/openstack/zaqar-specs/blob/master/specs/kilo/approved/persistent-transport.rst"&gt;persistent-transport&lt;/a&gt; specification.&lt;/p&gt;
&lt;section id="deserialization-of-incoming-messages-to-zaqar"&gt;
&lt;h3&gt;Deserialization of incoming messages to Zaqar&lt;/h3&gt;
&lt;p&gt;As you can see in &lt;a class="reference external" href="https://github.com/openstack/zaqar/blob/stable/liberty/zaqar/transport/websocket/protocol.py#L55"&gt;protocol.py#L55&lt;/a&gt;, Zaqar already can distinguish binary and
text messages.&lt;/p&gt;
&lt;p&gt;So we will make Zaqar try to deserialize each received binary message via
‘msgpack’ library into a python object, just like Zaqar currently deserializes
JSON messages via ‘json’ library. After successful deserialization the
message can be processed as usual.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="serialization-of-response-and-subscription-messages-from-zaqar"&gt;
&lt;h3&gt;Serialization of response and subscription messages from Zaqar&lt;/h3&gt;
&lt;p&gt;The response from Zaqar will be serialized in the same format as the incoming
request.&lt;/p&gt;
&lt;p&gt;The subscription messages from Zaqar will be serialized in binary or text
format based on the format of subscription create request.&lt;/p&gt;
&lt;p&gt;Let’s take a look at the case where the client suddenly changes it’s messaging
format while connection is open and subscription is still alive. There might
be a problem when the client will not be able to deserialize the messages
coming from the old subscription, because it has switched the format by
changing some boolean variable (switch). But this situation is nearly
impossible and, if not, the problem is solvable:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;It’s hard to imagine a situation when it might be useful for the client to
change it’s serialization format. Such client will probably never exist.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Even if such client will exist in the future, the client developer will
take care of it by adding the code checking the format of each incoming
message and deserializing the message accordingly inside “on message”
method. Zaqar does exactly this, for example. All websocket implementations
provide a convenient way to determine the format of each particular message.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Even if the client developer will not take care of this potential problem
(he is inexperienced, for example) and will make the client just expect
all incoming messages in the new format after switching while the old
subscription is still alive, the client will crash on the &lt;strong&gt;first incoming
message from this subscription&lt;/strong&gt; and the problem will not go unnoticed.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
&lt;section id="websocket-html-client-example-upgrade"&gt;
&lt;h3&gt;Websocket html client example upgrade&lt;/h3&gt;
&lt;p&gt;The websocket html &lt;a class="reference external" href="https://github.com/openstack/zaqar/blob/stable/liberty/examples/websocket.html"&gt;client example&lt;/a&gt; will be changed to make it also being able
to communicate with Zaqar via binary messages.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="drawbacks"&gt;
&lt;h3&gt;Drawbacks&lt;/h3&gt;
&lt;section id="the-performance-of-web-clients-on-javascript"&gt;
&lt;h4&gt;The performance of web clients on JavaScript&lt;/h4&gt;
&lt;p&gt;Seems like MsgPack serialization/deserialization works slower than JSON in
JavaScript. Well, no surprise since JSON abbreviation expands to “JavaScript
Object Notation”.
It’s a drawback for Zaqar web clients as it decreases their performance.&lt;/p&gt;
&lt;p&gt;How the change addresses this drawback:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;The server is one and clients are many. The server processes much more
messages than each particular client. So there are many cases when it’s
reasonable to use binary serialization to increase server performance by
sacrificing performance of JavaScript clients.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The additional delays on JavaScript clients are slightly compensated by
faster responses from the server.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;JavaScript clients can always use good old text format for communications
with the server, while other clients can use binary format with the same
server simultaneously.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;These alternatives completely exclude the nearly impossible case where the
client may suddenly switch it’s messaging format, while the connection is open
and the old subscription is still alive, and while proper deserialization of
incoming messages to the client is managed by some client’s boolean variable
(switch).&lt;/p&gt;
&lt;section id="alternatives-of-serialization-of-response-and-subscription-messages-from-zaqar"&gt;
&lt;h4&gt;Alternatives of serialization of response and subscription messages from Zaqar&lt;/h4&gt;
&lt;section id="optional-parameter-approach"&gt;
&lt;h5&gt;Optional parameter approach&lt;/h5&gt;
&lt;p&gt;The response from Zaqar will be serialized in the same format as the incoming
request.&lt;/p&gt;
&lt;p&gt;The subscription messages from Zaqar will be serialized in binary
or text format based on the new optional parameter passed in the message
body of subscription create request. We can add this parameter to websocket
API, name it &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;accept&lt;/span&gt;&lt;/code&gt;, allow it to have only two possible values: &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;json&lt;/span&gt;&lt;/code&gt;
and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;msgpack&lt;/span&gt;&lt;/code&gt; and make &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;json&lt;/span&gt;&lt;/code&gt; value as default if &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;accept&lt;/span&gt;&lt;/code&gt; parameter was
not passed.
By making &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;accept&lt;/span&gt;&lt;/code&gt; parameter optional, we are achieving backward
compatibility.&lt;/p&gt;
&lt;p&gt;Subscription request message example before 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="p"&gt;{&lt;/span&gt;
    &lt;span class="s1"&gt;'action'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'subscription_create'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'headers'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;'Client-ID'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;31209&lt;/span&gt;&lt;span class="n"&gt;ff3&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;ba03&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="n"&gt;cec&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;b4ca&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;655&lt;/span&gt;&lt;span class="n"&gt;f4899f8aa&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s1"&gt;'X-Project-ID'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;superproject&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="s1"&gt;'body'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;'queue_name'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'superqueue'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'ttl'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3600&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;Subscription request message after implementation can be the same as before or
it can also pass &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;accept&lt;/span&gt;&lt;/code&gt; parameter explicitly:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s1"&gt;'action'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'subscription_create'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'headers'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;'Client-ID'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;31209&lt;/span&gt;&lt;span class="n"&gt;ff3&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;ba03&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="n"&gt;cec&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;b4ca&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;655&lt;/span&gt;&lt;span class="n"&gt;f4899f8aa&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s1"&gt;'X-Project-ID'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;superproject&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="s1"&gt;'body'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;'queue_name'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'superqueue'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'ttl'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3600&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'accept'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'json'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section id="first-message-approach"&gt;
&lt;h5&gt;First message approach&lt;/h5&gt;
&lt;p&gt;The response and subscription messages from Zaqar will be serialized in binary
or text format based on in which format the particular client has sent it’s
first successfully parsed message to Zaqar since connecting.&lt;/p&gt;
&lt;p&gt;Once the format of communications between Zaqar and the client was
established by that way, the client will not be able to change it, unless the
client will reconnect to Zaqar and send the first message in other format.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="zaqar-configuration-approach"&gt;
&lt;h5&gt;Zaqar configuration approach&lt;/h5&gt;
&lt;p&gt;The response and subscription messages from Zaqar will be serialized in binary
or text format based on the boolean variable in Zaqar server configuration.&lt;/p&gt;
&lt;/section&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;ubershy&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;Mitaka-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;None&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;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, 17 Jan 2018 00:00:00 </pubDate></item><item><title>The title of your blueprint</title><link>https://specs.openstack.org/openstack/zaqar-specs/specs/new-storage-driver-template.html</link><description>
 
&lt;p&gt;Include the URL of your launchpad blueprint:&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/zaqar/+spec/example"&gt;https://blueprints.launchpad.net/zaqar/+spec/example&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Introduction paragraph – why are we doing anything?&lt;/p&gt;
&lt;section id="driver-description"&gt;
&lt;h2&gt;Driver description&lt;/h2&gt;
&lt;p&gt;A detailed description of the driver.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Here is where you cover the change you propose to make in detail. How do you
propose to solve this problem?&lt;/p&gt;
&lt;p&gt;If this is one part of a larger effort make it clear where this piece ends. In
other words, what’s the scope of this effort?&lt;/p&gt;
&lt;/section&gt;
&lt;section id="what-are-the-driver-s-guarantees-in-terms-of-reliability"&gt;
&lt;h2&gt;What are the driver’s guarantees in terms of reliability?&lt;/h2&gt;
&lt;p&gt;“Zaqar aims to be a fully-reliable service, therefore messages should  never be
lost under any circumstances except for when the message’s  expiration time
(ttl) is reached…”&lt;/p&gt;
&lt;/section&gt;
&lt;section id="what-are-the-driver-s-guarantees-in-terms-of-scalability"&gt;
&lt;h2&gt;What are the driver’s guarantees in terms of scalability?&lt;/h2&gt;
&lt;p&gt;Zaqar aims to be an easily scalable service. Zaqar provides an easy way to
scale web-heads and to balance queue’s load across several different storage
clusters. However, the real scalability is provided by the storage itself. If
the storage can’t be unlimitedly scaled or it’s hard to scale, it’ll break this
guarantee. Supported storage must be good for general use-cases and easy to
scale unlimitedly. It’s fine to have storage drivers for very specific
use-cases but it’s likely not going to be possible to maintain those drivers.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="what-are-the-driver-s-guarantees-in-terms-of-interoperability"&gt;
&lt;h2&gt;What are the driver’s guarantees in terms of interoperability?&lt;/h2&gt;
&lt;p&gt;In order for applications to easily talk to different clouds supporting Zaqar,
it is necessary for the service to guarantee interoperability as much as
possible. Lots of the interoperability guarantees depend on how the service
itself is deployed. However, the team strives to provide an interoperable
service and guide operators on what the best way to deploy the service is.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="what-are-the-driver-s-guarantees-in-terms-of-openness"&gt;
&lt;h2&gt;What are the driver’s guarantees in terms of openness?&lt;/h2&gt;
&lt;p&gt;Zaqar is an open-source software licensed under the Apache 2 license. It aims
to be able to be installed in any deployments and circumstances. In order to do
that, it tries to support technologies that will alow deployers to do so
without any constraint. In order for the team to be able to maintain and
support a storage driver, the driver has to be licensed under an open license
and so has to be the technology the driver supports. The team won’t be able to
maintain drivers relying on closed technologies that cannot be tested/deployed.&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;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;/dl&gt;
&lt;p&gt;Can list additional ids if they intend on doing substantial implementation work
on this blueprint.&lt;/p&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;Work items or tasks – break the feature up into the things that need to be
done to implement it. Those parts might end up being done by different people,
but we’re mostly trying to understand the timeline for implementation.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Include specific references to specs and/or blueprints in zaqar, or in other
projects, that this one either depends on or is related to.&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, 17 Jan 2018 00:00:00 </pubDate></item><item><title>Lazy queues in subscriptions</title><link>https://specs.openstack.org/openstack/zaqar-specs/specs/newton/lazy-queues-in-subscriptions.html</link><description>
 
&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/zaqar/+spec/lazy-queues-in-subscriptions"&gt;https://blueprints.launchpad.net/zaqar/+spec/lazy-queues-in-subscriptions&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Make queues lazy on operations with subscriptions, so the user will be able to
subscribe to yet unexisting queue.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Queues are designed to be lazy resources in Zaqar’s API v1.1 and API v2 in
messaging. That means, for example, that the user can post messages to
unexisting queue, and the queue will be automatically created. But now queues
do not behave like lazy resources on operations with subscriptions. Before
creating a subscription, the user must ensure the queue exists, or Zaqar will
send error response with HTTP code 400.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Make queues lazy on operations with subscriptions, so the user will be able
to subscribe to yet unexisting queue. Make Zaqar do not send error response
on queue creation operation in the case queue does not exists.&lt;/p&gt;
&lt;p&gt;Advantages:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;The behavior of API will be more consistent, because after the change
queues will be lazy in all situations.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It will be easier for the user to work with subscriptions. No need to do
pre-check for queue existence, or handle 400 error response from Zaqar, or
always pre-create queue.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;There will be no need to solve currently existing problem when the queue was
deleted, but subscriptions to it are still existing. Problem solving will
probably require storage driver code to delete also all subscriptions to
a queue, when deleting the queue. It may be very undesirable for the user,
because subscriptions will not guarantee to be existing till TTL expiration,
and will need to be renewed also after queue delete and queue create
operations. Proper solution to this problem will complicate behavior in many
ways in both Zaqar and client’s code. It will be probably backward
incompatible change.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The change is backward compatible. Client’s code should work after the change.&lt;/p&gt;
&lt;section id="drawbacks"&gt;
&lt;h3&gt;Drawbacks&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Two alternatives:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Keep the current behavior.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;There is opinion to make queues non-lazy resources in all situations like
it was in API v1. But it will be backward incompatible change to our API
v1.1 and API v2, so maybe make it in the distant future.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Both of them will require solving the problem about still active subscriptions
to a queue that was deleted.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;ubershy&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;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Remove checks for queue existence on operations with subscriptions from
storage drivers.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Remove the code that is catching &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;QueueDoesNotExist&lt;/span&gt;&lt;/code&gt; exception on
operations with subscriptions from transport drivers.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Change functional and unit tests accordingly.&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;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, 17 Jan 2018 00:00:00 </pubDate></item><item><title>Subscription confirmation support</title><link>https://specs.openstack.org/openstack/zaqar-specs/specs/newton/subscription-confirmation-support.html</link><description>
 
&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/zaqar/+spec/subscription-confirmation-support"&gt;https://blueprints.launchpad.net/zaqar/+spec/subscription-confirmation-support&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Support subscribers confirm that whether they want the notifications or not
before Zaqar sends them.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Currently Zaqar can post notifications to the subscriber once the subscription
is created. It doesn’t need the subscriber to confirm the subscription.
This will lead a problem that users could send junk information that whether
subscriber wants or not.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;With &lt;a class="reference internal" href="#amazon-sns"&gt;Amazon SNS&lt;/a&gt; as reference, we will support to send HTTP POST request
that contains subscription confirmation information(e.g. message type,
pre-signed confirmation URL, signature information) to subscription endpoint.
The endpoint needs to use the URL in notification to confirm subscription.
When the subscription is deleted, Zaqar server will send a notification that
the subscription with ID has been deleted. This mechanism tells endpoint no
need to wait notifications any more.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The message types will be SubscriptionConfirmation, Notification
and UnsubscribeConfirmation.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For backward compatibility, we also should add new option in Zaqar
configuration file like this:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;notification&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;require_confirmation&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;true&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;false&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If the user omits this option in config, it will be ‘false’ by default.
In further, we may change the default value to ‘true’ to let subscription
more secure.&lt;/p&gt;
&lt;p&gt;So the workflow will be this in webhook:&lt;/p&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;&lt;p&gt;User creates subscription in Zaqar.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Zaqar sends a HTTP POST request with subscription confirmation information.
This request is like this:&lt;/p&gt;
&lt;p&gt;POST URL:&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;http&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="n"&gt;endpointUrl&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Request Body:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="s1"&gt;'MessageType'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'SubscriptionConfirmation'&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;'You have chosen to subscribe to the queue: xxx.'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="s1"&gt;'URL-Signature'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'xxxx'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="s1"&gt;'URL-METHODS'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'PUT'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="s1"&gt;'URL-PATHS'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'/v2/queues/&lt;/span&gt;&lt;span class="si"&gt;{queue_name}&lt;/span&gt;&lt;span class="s1"&gt;/subscriptions/&lt;/span&gt;&lt;span class="si"&gt;{subscriptions_id}&lt;/span&gt;&lt;span class="s1"&gt;/confirm'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="s1"&gt;'X-PROJECT-ID'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'xxxx'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="s1"&gt;'URL-EXPIRES'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'3600-01-01T00:00:00'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="s1"&gt;'SubscribeURL'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'https://zaqar_server/v2/queues/&lt;/span&gt;&lt;span class="si"&gt;{queue_name}&lt;/span&gt;&lt;span class="s1"&gt;/subscriptions/&lt;/span&gt;&lt;span class="si"&gt;{subscriptions_id}&lt;/span&gt;&lt;span class="s1"&gt;/confirm'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="s1"&gt;'SubscribeBody'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;'confirmed'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
     &lt;span class="s1"&gt;'UnsubscribeBody'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;'confirmed'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Subscriber confirms this subscription by using those information
in request body, and sends the pre-signed confirmation request to Zaqar.
It’s a new endpoint in Zaqar.
This request is like this:&lt;/p&gt;
&lt;p&gt;PUT URL:&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;https&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="n"&gt;zaqar_server&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;queues&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;queue_name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;subscriptions&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;subscriptions_id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;confirm&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Request Body:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s1"&gt;'confirmed'&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;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Meanwhile, HTTP headers are also required by using pre-signed feature
in Zaqar. If subscriber wants to unsubscribe this subscription, just needs
to set ‘confirmed’ to False.
If Zaqar processes this request successfully, Zaqar will response with:&lt;/p&gt;
&lt;p&gt;Response 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="mi"&gt;204&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;If Zaqar has failed processsing this request because of some error, it will
return error message in response body.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Zaqar begins to send notifications to this endpoint after confirmation
workflow is finished.&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;If Zaqar server didn’t receive the response or subscriber didn’t sent it
since something wrong, subscription will keep ‘confirmed’ as false, and
Zaqar will support to resend confirmation request by calling subscription
creation API again.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;So the workflow will be this in email:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;User creates subscription in Zaqar.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Zaqar sends an email with subscription confirmation page link.
Email context is like this::
“You have chosen to subscribe to the queue: {queue name}.”
“This queue belongs to project: {project id}.”
“To confirm this subscription, click or visit this linke below:”
“{confirmation link}”&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When subscriber visits this link, he gets a page which calls
Zaqar by ajax request to confirm the subscription as same as
webhook way.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The page shows information about was the subscription successfully
confirmed or not.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Zaqar begins to send notifications to this endpoint.&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;About the confirmation page, Zaqar will host a sample page in Zaqar
tree, but it’s not a part of Zaqar service. Cloud administrator should
provide hosting for this page manually. After this page is hosted
successfully, cloud administrator should specify this page location
in Zaqar config “external_confirmation_url”.&lt;/p&gt;
&lt;/div&gt;
&lt;section id="drawbacks"&gt;
&lt;h3&gt;Drawbacks&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;Another option is when subscriber creates a subscription, he also need to
call Zaqar’s confirmation API to confirm it before confirmation is expired.
In this option, Zaqar will not send any confirmation notification by itself.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="data-model-impact"&gt;
&lt;h3&gt;Data model impact&lt;/h3&gt;
&lt;p&gt;Add new status “confirmed” into subscription model.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="comparison-aws-sns-api-and-zaqar-api"&gt;
&lt;h3&gt;Comparison AWS SNS API and Zaqar API&lt;/h3&gt;
&lt;p&gt;For developer to better understand this feature, this spec compares SNS API
and Zaqar API what difference between them.&lt;/p&gt;
&lt;p&gt;Subscription Confirmation Request
SNS is using GET request like this:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;GET https://sns.us-west-2.amazonaws.com/?Action=ConfirmSubscription&amp;amp;TopicArn={Topic}&amp;amp;Token={Token}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Zaqar is using PUT request like this:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;PUT&lt;/span&gt; &lt;span class="n"&gt;https&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="n"&gt;zaqar_server&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;queues&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;queue_name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;subscriptions&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;subscriptions_id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;confirm&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Request Body:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s1"&gt;'confirmed'&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;/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;wangxiyuan&amp;lt;&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;&amp;gt;&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Secondary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;wanghao&amp;lt;&lt;a class="reference external" href="mailto:wanghao749%40huawei.com"&gt;wanghao749&lt;span&gt;@&lt;/span&gt;huawei&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;dl class="simple"&gt;
&lt;dt&gt;Target Milestone for completion:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Newton-3&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 subscriber confirmation API in wsgi.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update subscription resource to add new property “confirmed”
on MongoDB driver.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add new config options.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update notification to send confirmation message in way email.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Implement subscriber confirmation API in websocket.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update subscription resource on other drivers.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update notification to send confirmation message in way webhook.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add message type.&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;&lt;span class="target" id="amazon-sns"&gt;Amazon SNS&lt;/span&gt;: &lt;a class="reference external" href="http://docs.aws.amazon.com/sns/latest/dg/SendMessageToHttp.html"&gt;http://docs.aws.amazon.com/sns/latest/dg/SendMessageToHttp.html&lt;/a&gt;&lt;/p&gt;
&lt;/section&gt;
</description><pubDate>Wed, 17 Jan 2018 00:00:00 </pubDate></item><item><title>Purge queue</title><link>https://specs.openstack.org/openstack/zaqar-specs/specs/ocata/purge-queue.html</link><description>
 
&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/zaqar/+spec/purge-queue"&gt;https://blueprints.launchpad.net/zaqar/+spec/purge-queue&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Though user can delete messages, claims or subscriptions from a queue, but
there is no way to delete many of them at once.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Now Zaqar is missing a fast way to delete many resources at once for a given
queue. This could be handy for user to clean the queue and keep all the
metadata of the queue.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;New endpoint for action ‘purge’ for queue:&lt;/p&gt;
&lt;p&gt;/v2/queues/myqueue/purge&lt;/p&gt;
&lt;p&gt;POST body:&lt;/p&gt;
&lt;div class="highlight-json notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nt"&gt;"resource_types"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"messages"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"subscriptions"&lt;/span&gt;&lt;span class="p"&gt;]}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;So the idea is if there is no POST body, by default, all the resources under
the queue will be delete. Otherwise, if the key ‘resource_types’ in the POST
body, then Zaqar will delete resources based on the given resource types. It’s
a list and it could be one of the combinations of the two types: ‘messages’,
and ‘subscriptions’.&lt;/p&gt;
&lt;p&gt;Currently, it’s hard to list “claims” under a queue, so this feature won’t
support clean “claims”.&lt;/p&gt;
&lt;section id="drawbacks"&gt;
&lt;h3&gt;Drawbacks&lt;/h3&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;User has to delete messages and subscriptions of the queue manually.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;flwang (&lt;a class="reference external" href="mailto:flwang%40catalyst.net.nz"&gt;flwang&lt;span&gt;@&lt;/span&gt;catalyst&lt;span&gt;.&lt;/span&gt;net&lt;span&gt;.&lt;/span&gt;nz&lt;/a&gt;)&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="work-items"&gt;
&lt;h3&gt;Work Items&lt;/h3&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Add a new method ‘purge’ for storage queue controller which will delete all
messages and subscriptions under the queue.&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;N/A&lt;/p&gt;
&lt;/section&gt;
</description><pubDate>Wed, 17 Jan 2018 00:00:00 </pubDate></item><item><title>Dead Letter Queue</title><link>https://specs.openstack.org/openstack/zaqar-specs/specs/pike/dead_letter_queue.html</link><description>
 
&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/zaqar/+spec/dead-letter-queue"&gt;https://blueprints.launchpad.net/zaqar/+spec/dead-letter-queue&lt;/a&gt;&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Currently, Zaqar can’t do anything if the message has been claimed many times
and still can’t be processed successfully. That could be nice if Zaqar can
provide the dead letter queue support so that user can provide an existing
queue A for queue B’s dead letter queue. Dead letter queue storing these
messages allows developers to look for common patterns and potential software
problems.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;1. Add three new reserved attributes for queue’s metadata: &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;_max_claim_count&lt;/span&gt;&lt;/code&gt;
and &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;_dead_letter_queue&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;_max_claim_count&lt;/span&gt;&lt;/code&gt; is the max number the message can be claimed. Generally,
it means the message cannot be processed successfully. There is no default
value for this attribute. If it’s not set, then that means this feature won’t
be enabled for current queue.&lt;/p&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;_dead_letter_queue&lt;/span&gt;&lt;/code&gt; is the target the message will be moved to when the
message can’t processed successfully after meet the max claim count. It’s not
supported to add queue C as the dead letter queue for queue B where queue B has
been set as a dead letter queue for queue A. It’s not the case we want to
address in this spec. Technically, even though user can set a dead letter queue
C for queue B(when queue B is a dead letter queue of queue A), because the
moving is triggered by claim, so that means if user won’t explicitly claim
messages in queue B, then nothing happened.&lt;/p&gt;
&lt;p&gt;&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;_dead_letter_queue_messages_ttl&lt;/span&gt;&lt;/code&gt; is the new TTL setting for messages when
moved to DLQ. If it’s not set, current TTL will be kept.&lt;/p&gt;
&lt;p&gt;2. Make sure the DLQ and current queue are in the same pool when doing
validation to get better performance.&lt;/p&gt;
&lt;p&gt;3. Add a new filed for message in database which can be used to save the claim
count.&lt;/p&gt;
&lt;ol class="arabic" start="4"&gt;
&lt;li&gt;&lt;p&gt;Changes for claim create method&lt;/p&gt;
&lt;p&gt;4.1. get current claim count from the message, update the claim count by
plus one.&lt;/p&gt;
&lt;p&gt;4.2. check if the claim count has exceeded the max claim count defined in
queue’s metadata. If it doesn’t exceed the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;_max_claim_count&lt;/span&gt;&lt;/code&gt;, just do
normal claim.&lt;/p&gt;
&lt;p&gt;4.3. If the claim count does exceed the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;_max_claim_count&lt;/span&gt;&lt;/code&gt;, move the
message to the dead letter queue directly. Given the goal of DLQ, we’d like
to keep the claim information of the message. So depends on the storage
backend, the “move” could introduce a limitation. For example, for MongoDB
backend, we may have to move the message from the source queue to DLQ by
changing the queue name directly. Which means the two have to be created on
same storage pool.&lt;/p&gt;
&lt;p&gt;After moved the message, Zaqar will do nothing against those
messages in dead letter queue. User could/will use these message to debug
why those messages can’t be processed successfully. In other words, allows
developers to look for common patterns and potential software problems from
those messages.&lt;/p&gt;
&lt;p&gt;4.4. messages moved to DLQ will be updated their TTL based on the setting
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;_dead_letter_queue_messages_ttl&lt;/span&gt;&lt;/code&gt;. If it’s not set, currentl TTL of
messages will be kept.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;section id="drawbacks"&gt;
&lt;h3&gt;Drawbacks&lt;/h3&gt;
&lt;p&gt;Based on current design, we may have a limitation because of the technical
trade off. When move the message from source queue to dead letter queue, it’d
be nice to keep the claim info, but if we want to do that, we have to make sure
the two queues are on same storage pool. The implementation could be different
on different back ends.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;None&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;flwang &amp;lt;&lt;a class="reference external" href="mailto:flwang%40catalyst.net.nz"&gt;flwang&lt;span&gt;@&lt;/span&gt;catalyst&lt;span&gt;.&lt;/span&gt;net&lt;span&gt;.&lt;/span&gt;nz&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;dl class="simple"&gt;
&lt;dt&gt;Target Milestone for completion:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Pike-3&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 _max_claim_count and _dead_letter_queue as reserved attributes in queue
metadata&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add validation for the new reserved attributes&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add a new filed for message to count the claim, this needs to be done
against maongoDB, swift and redis.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add change in claim create which will add the claim count for messages and
check if the count has exceed the max claim count defined in queue’s
metadata. If it has exceeded, move the message to the dead letter queue.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add release note for this feature&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update API reference&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add user/developer document for this feature&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Change unit, functional and tempest tests accordingly.&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;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, 17 Jan 2018 00:00:00 </pubDate></item><item><title>Notification Delivery Policy</title><link>https://specs.openstack.org/openstack/zaqar-specs/specs/pike/notification-delivery-policy.html</link><description>
 
&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/zaqar/+spec/notification-delivery-policy"&gt;https://blueprints.launchpad.net/zaqar/+spec/notification-delivery-policy&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Sometimes, because of network/internet connection issue or the load of the
target services/applications, the notification sent from Zaqar to the
subscriber may fail, so it would be nice if we can support a retry and
user can define the retry policy in the options of subscription.&lt;/p&gt;
&lt;p&gt;This feature is only for HTTP/HTTPS subscription way, not including the Email
notification.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Now Zaqar didn’t have notification delivery policy, that means there is no
retries if endpoint has some problem that can’t receive the notification.
For users or applications, it’s missing important message without notification.&lt;/p&gt;
&lt;p&gt;AWS SNS service has supported the policy, that would be a good reference for
Zaqar[1].&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;For clarification what we want to do, there is some questions to be answered:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;When do the notification delivery policy work?&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Zaqar only attempts a retry after a failed delivery attempt.
Those situations as a failed delivery attempt:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;HTTP status in the range 500-599.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;HTTP status outside the range 200-599.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A request timeout.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Any connection error such as connection timeout, endpoint unreachable, etc.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;ol class="arabic simple" start="2"&gt;
&lt;li&gt;&lt;p&gt;How do the notification delivery policy work?&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;You can use delivery policies to control not only the total number of retries,
but also the time delay between each retry.&lt;/p&gt;
&lt;p&gt;There are total four discrete phases that user can use to set policy of retry:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Immediate Retry Phase: Also called the no delay phase, this phase occurs
immediately after the initial delivery attempt. The value user set for
‘Retries with no delay’ determines the number of retries immediately after
the initial delivery attempt. There is no delay between retries in this
phase.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Pre-Backoff Phase: The pre-backoff phase follows the immediate retry phase.
Use this phase to create a set of retries that occur before a backoff
function applies to the retries. Use the ‘Minimum delay retries’ setting to
specify the number of retries in the Pre-Backoff Phase. User can control the
time delay between retries in this phase by using the ‘Minimum delay’
setting.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Backoff Phase: This phase is called the backoff phase because user can
control the delay between retries in this phase using the retry backoff
function. Set the ‘Minimum delay’ and the ‘Maximum delay’, and then select a
Retry backoff function to define how quickly the delay increases from the
minimum delay to the maximum delay.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Post-Backoff Phase: The post-backoff phase follows the backoff phase.
Use the ‘Maximum delay retries’ setting to specify the number of retries in
the post-backoff phase. You can control the time delay between retries in
this phase by using the ‘Maximum delay’ setting.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;User can create and apply the retry policies to queues and subscriptions when
creating them. So when Zaqar send the notification to those subscribers,
it will use those policies to make retried after initial delivery attempt
failed.&lt;/p&gt;
&lt;p&gt;..note:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;By&lt;/span&gt; &lt;span class="n"&gt;default&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;there&lt;/span&gt; &lt;span class="n"&gt;are&lt;/span&gt; &lt;span class="n"&gt;retry&lt;/span&gt; &lt;span class="n"&gt;policies&lt;/span&gt; &lt;span class="n"&gt;on&lt;/span&gt; &lt;span class="n"&gt;both&lt;/span&gt; &lt;span class="n"&gt;queue&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;subscription&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="n"&gt;Zaqar&lt;/span&gt; &lt;span class="n"&gt;will&lt;/span&gt; &lt;span class="n"&gt;use&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;subscription&lt;/span&gt;&lt;span class="s1"&gt;'s policy. If user don'&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="n"&gt;want&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;override&lt;/span&gt;
&lt;span class="n"&gt;he&lt;/span&gt; &lt;span class="n"&gt;can&lt;/span&gt; &lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;ignore_subscription_override&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;_retry_policy&lt;/span&gt; &lt;span class="n"&gt;metadata&lt;/span&gt;
&lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;queue&lt;/span&gt;&lt;span class="o"&gt;.&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;What changes will bring into Zaqar?&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;First, user can create retry policies in metadata which’s in request body of
queue creation.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Second, user also can create retry policies in options which’s in request
body of subscription creation. If retry policy are set to both queue and
subscription, Zaqar will use subscription policy instead of queue policy
by default, but if ignore_subscription_override is True in queue’s metadata
then Zaqar will still use the retry policy in queue.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Third, change the logic of notification, when fail is existing when sending
notification to endpoint, then use the policy which has binded to this
subscription to make retries, if subscription doesn’t have retry policy, then
Zaqar will use the policy in queue’s metadata.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Since ‘metadata’ in queue and ‘options’ in subscription are dict, the data
model of retry policy should be like this:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="s1"&gt;'_retry_policy'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                       &lt;span class="s1"&gt;'retries_with_no_delay'&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;Integer&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;optional&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                       &lt;span class="s1"&gt;'minimum_delay_retries'&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;Integer&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;optional&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                       &lt;span class="s1"&gt;'minimum_delay'&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;Interger&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;optional&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                       &lt;span class="s1"&gt;'maximum_delay'&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;Interger&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;optional&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                       &lt;span class="s1"&gt;'maximum_delay_retries'&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;Integer&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;optional&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                       &lt;span class="s1"&gt;'retry_backoff_function'&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;String&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;optional&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                       &lt;span class="s1"&gt;'ignore_subscription_override'&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;Bool&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;optional&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
                    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="s1"&gt;'minimum_delay'&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="s1"&gt;'maximum_delay'&lt;/span&gt; &lt;span class="n"&gt;mean&lt;/span&gt; &lt;span class="n"&gt;delay&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;seconds&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
&lt;span class="s1"&gt;'retry_backoff_function'&lt;/span&gt; &lt;span class="n"&gt;mean&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="n"&gt;retry&lt;/span&gt; &lt;span class="n"&gt;backoff&lt;/span&gt; &lt;span class="n"&gt;function&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
&lt;span class="n"&gt;There&lt;/span&gt; &lt;span class="n"&gt;will&lt;/span&gt; &lt;span class="n"&gt;be&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;enum&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;Zaqar&lt;/span&gt; &lt;span class="n"&gt;that&lt;/span&gt; &lt;span class="n"&gt;contain&lt;/span&gt; &lt;span class="nb"&gt;all&lt;/span&gt; &lt;span class="n"&gt;valid&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;At&lt;/span&gt; &lt;span class="n"&gt;first&lt;/span&gt; &lt;span class="n"&gt;step&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="n"&gt;Zaqar&lt;/span&gt; &lt;span class="n"&gt;only&lt;/span&gt; &lt;span class="n"&gt;supports&lt;/span&gt; &lt;span class="n"&gt;one&lt;/span&gt; &lt;span class="n"&gt;function&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'linear'&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
&lt;span class="n"&gt;If&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="n"&gt;retry_policy&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;empty&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;that&lt;/span&gt; &lt;span class="n"&gt;Zaqar&lt;/span&gt; &lt;span class="n"&gt;will&lt;/span&gt; &lt;span class="n"&gt;use&lt;/span&gt; &lt;span class="n"&gt;default&lt;/span&gt;
&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;those&lt;/span&gt; &lt;span class="n"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;retries_with_no_delay&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;
&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;minimum_delay_retries&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;
&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;minimum_delay&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;
&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;maximum_delay&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;
&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;maximum_delay_retries&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;
&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;retry_backoff_function&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;linear&lt;/span&gt;
&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;ignore_subscription_override&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;False&lt;/span&gt;
&lt;span class="n"&gt;Those&lt;/span&gt; &lt;span class="n"&gt;default&lt;/span&gt; &lt;span class="n"&gt;values&lt;/span&gt; &lt;span class="n"&gt;will&lt;/span&gt; &lt;span class="n"&gt;be&lt;/span&gt; &lt;span class="n"&gt;configurable&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;Queens&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;..note:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span/&gt;&lt;span class="n"&gt;Retry&lt;/span&gt; &lt;span class="n"&gt;policy&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;only&lt;/span&gt; &lt;span class="n"&gt;applied&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;webhook&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;https&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;subscriber&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
&lt;span class="n"&gt;Zaqar&lt;/span&gt; &lt;span class="n"&gt;will&lt;/span&gt; &lt;span class="n"&gt;support&lt;/span&gt; &lt;span class="n"&gt;linear&lt;/span&gt; &lt;span class="n"&gt;retry&lt;/span&gt; &lt;span class="n"&gt;backoff&lt;/span&gt; &lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="n"&gt;only&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;Pike&lt;/span&gt; &lt;span class="n"&gt;release&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="n"&gt;will&lt;/span&gt; &lt;span class="n"&gt;increase&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;delay&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt; &lt;span class="n"&gt;linearly&lt;/span&gt; &lt;span class="n"&gt;within&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="n"&gt;times&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;minimum&lt;/span&gt; &lt;span class="n"&gt;delay&lt;/span&gt;
&lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;maximum&lt;/span&gt; &lt;span class="n"&gt;delay&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="n"&gt;We&lt;/span&gt; &lt;span class="n"&gt;will&lt;/span&gt; &lt;span class="n"&gt;support&lt;/span&gt; &lt;span class="n"&gt;more&lt;/span&gt; &lt;span class="n"&gt;retry&lt;/span&gt; &lt;span class="n"&gt;backoff&lt;/span&gt; &lt;span class="n"&gt;functions&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;future&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
&lt;span class="n"&gt;For&lt;/span&gt; &lt;span class="n"&gt;avoiding&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="n"&gt;receive&lt;/span&gt; &lt;span class="n"&gt;notification&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="n"&gt;repeatedly&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;connection&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;reconnected&lt;/span&gt; &lt;span class="n"&gt;during&lt;/span&gt; &lt;span class="n"&gt;retry&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;once&lt;/span&gt; &lt;span class="n"&gt;Zaqar&lt;/span&gt; &lt;span class="n"&gt;sends&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt;
&lt;span class="n"&gt;notification&lt;/span&gt; &lt;span class="n"&gt;successfully&lt;/span&gt; &lt;span class="n"&gt;when&lt;/span&gt; &lt;span class="n"&gt;doing&lt;/span&gt; &lt;span class="n"&gt;retry&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="n"&gt;will&lt;/span&gt; &lt;span class="n"&gt;stop&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;whole&lt;/span&gt; &lt;span class="n"&gt;retry&lt;/span&gt;
&lt;span class="n"&gt;process&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;section id="example"&gt;
&lt;h3&gt;Example&lt;/h3&gt;
&lt;p&gt;For better to know how does this work, there is an example case.
Assume user use the default value of retry policy in a queue A,
and create a subscription with HTTP subscriber: &lt;a class="reference external" href="http://192.168.1.100:8080"&gt;http://192.168.1.100:8080&lt;/a&gt;.
When Zaqar send the notifications to this subscriber, it get a response with
HTTP code 500, then the retry policy will go to work:&lt;/p&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Phase 1: Immediate Retry. Zaqar will call the subscriber with no delay by 3&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;times. If there is no one successful, then go to Phase 2. If one of
retries is successful, the retry process will be end.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Phase 2: Pre-Backoff. According to the minimum_delay_retries and minimum_delay.&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;Zaqar will make a total of 3 retries with a 5 second delay between
each retry. If there is no one successful, then go to Phase 3.
If one of retries is successful, the retry process will be end.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Phase 3: Backoff. By using the linear function, Zaqar will make the delay&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;between retries to increase at a constant rate over the course of the
backoff phase. So as the constant rate is 5, Zaqar will call
subscriber 12 times with delay time:
[5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60].
If there is on one successful, then go to Phase 4.
If one of retries is successful, the retry process will be end.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;Phase 4: Post-Backoff. According to the maximum_delay and&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;maximum_delay_retries, Zaqar will make a total of 3 retries with a
60 second delay between each retry. After this phase, no matter the
call is successful or not, the retry process will be end.&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/section&gt;
&lt;section id="drawbacks"&gt;
&lt;h3&gt;Drawbacks&lt;/h3&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;wanghao (&lt;a class="reference external" href="mailto:sxmatch1986%40gmail.com"&gt;sxmatch1986&lt;span&gt;@&lt;/span&gt;gmail&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;P-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;Add verification for retry policy when creating queue and subscription.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Change the notification process for applying the policy.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;UTs for this feature.&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;[1]: &lt;a class="reference external" href="http://docs.aws.amazon.com/sns/latest/dg/DeliveryPolicies.html"&gt;http://docs.aws.amazon.com/sns/latest/dg/DeliveryPolicies.html&lt;/a&gt;&lt;/p&gt;
&lt;/section&gt;
</description><pubDate>Wed, 17 Jan 2018 00:00:00 </pubDate></item><item><title>Support More Backoff Functions</title><link>https://specs.openstack.org/openstack/zaqar-specs/specs/queens/support-more-backoff-functions.html</link><description>
 
&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/zaqar/+spec/support-more-backoff-functions"&gt;https://blueprints.launchpad.net/zaqar/+spec/support-more-backoff-functions&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Sometimes, because of network/internet connection issue or the load of the
target services/applications, the notification sent from Zaqar to the
subscriber may fail. That means there is no retries if endpoint has some
problem that can’t receive the notification. For users or applications,
it’s missing important message without notification. To solve this problem,
Zaqar has supported notification delivery policy in pike release [1].&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Now that Zaqar has supported only linear retry backoff function in Pike
release,it increases the delay time linearly from minimum delay to maximum
delay. We will support more retry backoff functions in Zaqar now.&lt;/p&gt;
&lt;p&gt;Fortunately, AWS SNS service has supported the policy, that would be a good
reference for Zaqar[2].&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;For clarification what we want to do, there are some questions to be answered:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;How many retry backoff functions Will Zaqar support?&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;You can choose from four retry backoff functions as follows:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Linear.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Arithmetic.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Geometric.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Exponential.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;ol class="arabic simple" start="2"&gt;
&lt;li&gt;&lt;p&gt;What difference between these four retry backoff functions?&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;As we can see the picture in chapter Backoff Phase in [2], The screen shot
shows how each retry backoff function affects the delay associated with
messages during the backoff period. The vertical axis represents the delay
in seconds associated with each of the 10 retries. The horizontal axis
represents the retry number. The  minimum delay is 5 seconds, and the
maximum delay is 260 seconds.&lt;/p&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;ol class="arabic simple" start="3"&gt;
&lt;li&gt;&lt;p&gt;The formula of these four retry backoff functions&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;Generally, we assume that the minimum delay is MIN, the maximum delay is
MAX, and the total retry number is NUM. From three element above, we can
conclude the formula of these four retry backoff functions.&lt;/p&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Linear.&lt;/p&gt;
&lt;p&gt;LINEAR_INTERVAL = ( MAX - MIN ) / NUM
time1 = MIN
time2 = MIN + LINEAR_INTERVAL*1
time3 = MIN + LINEAR_INTERVAL*2
timen = MIN + LINEAR_INTERVAL*(n-1)
timeN = MAX&lt;/p&gt;
&lt;p&gt;The Linear retry backoff functions has already been implemented in Pike
release, we only list here for reference and comparing.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Geometric&lt;/p&gt;
&lt;p&gt;we assume the common ratio of a geometric series is K:
time1 = MIN
time2 = K * MIN
time3 = K^2 * MIN
timen = K^(n-1) * MIN
timeN = K^(NUM-1) * MIN = MAX&lt;/p&gt;
&lt;p&gt;so :&lt;/p&gt;
&lt;p&gt;K^(NUM-1) = MAX/MIN
lg[ K^(NUM-1) ] = lg( MAX/MIN )
(NUM-1) * lg(K) = lg( MAX/MIN )
lg(K) = lg( MAX/MIN ) / (NUM-1)
K = 10^[  lg( MAX/MIN ) / (NUM-1) ]&lt;/p&gt;
&lt;p&gt;Finally:&lt;/p&gt;
&lt;p&gt;timen = {10^[  lg( MAX/MIN ) / (NUM-1) ]}^(n-1) * MIN&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Exponential.&lt;/p&gt;
&lt;p&gt;we assume the  power exponent of a exponential series is k, coefficient is p:&lt;/p&gt;
&lt;p&gt;the general function of power exponent of a exponential series is:
y = p * k^x&lt;/p&gt;
&lt;p&gt;time1 = MIN = p*k^1
timeN = MAX = p*k^NUM
MAX/MIN = k^(NUM-1)
lg(MAX/MIN) = (NUM-1)*lg(k)
lg(k) = lg(MAX/MIN)/ (NUM-1)
k = 10^[lg(MAX/MIN)/ (NUM-1)]
p = MIN/{10^[lg(MAX/MIN)/ (NUM-1)]}&lt;/p&gt;
&lt;p&gt;Finally:&lt;/p&gt;
&lt;p&gt;timen = p*k^n
timen = MIN/{10^[lg(MAX/MIN)/ (NUM-1)]} * {10^[lg(MAX/MIN)/ (NUM-1)]} ^n&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Arithmetic.&lt;/p&gt;
&lt;p&gt;we assume the common difference of a arithmetic series is d:&lt;/p&gt;
&lt;p&gt;time1 = MIN
time2 = time1 + d*1
time3 = time2 + d*2
time4 = time3 + d*3&lt;/p&gt;
&lt;p&gt;timen = timen-1 + d*(n-1)&lt;/p&gt;
&lt;p&gt;timeN = timeN-1 + d*(NUM-1) = MAX&lt;/p&gt;
&lt;p&gt;So:
timeN - time1 = NUM*(NUM-1)/2*d&lt;/p&gt;
&lt;p&gt;d = 2*(MAX-MIN)/[NUM*(NUM-1)]&lt;/p&gt;
&lt;p&gt;timen - time1 = n*(n-1)/2 * { 2*(MAX-MIN)/[NUM*(NUM-1)] }&lt;/p&gt;
&lt;p&gt;Finally:&lt;/p&gt;
&lt;p&gt;timen  = n*(n-1)/2 * { 2*(MAX-MIN)/[NUM*(NUM-1)] } + MIN&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ol class="arabic simple" start="4"&gt;
&lt;li&gt;&lt;p&gt;What changes will bring into Zaqar?&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;First, we will define three functions according to formula of these retry
backoff functions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Second, change the logic of notification, when fail is existing when sending
notification to endpoint, then use the policy which has binded to this
subscription to make retries. In Backoff Phase, we will select the retry
backoff functions according to user choice to resend notification.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;section id="drawbacks"&gt;
&lt;h3&gt;Drawbacks&lt;/h3&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;N/A&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;gecong (&lt;a class="reference external" href="mailto:ge.cong%40zte.com.cn"&gt;ge&lt;span&gt;.&lt;/span&gt;cong&lt;span&gt;@&lt;/span&gt;zte&lt;span&gt;.&lt;/span&gt;com&lt;span&gt;.&lt;/span&gt;cn&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;Q-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 three functions according to formula of these retry
backoff functions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Change the Backoff Phase of notification process for applying the retry
backoff functions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;UTs for this feature.&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;[1]:&lt;a class="reference external" href="https://specs.openstack.org/openstack/zaqar-specs/specs/pike/notification-delivery-policy.html"&gt;https://specs.openstack.org/openstack/zaqar-specs/specs/pike/notification-delivery-policy.html&lt;/a&gt;
[2]:&lt;a class="reference external" href="http://docs.aws.amazon.com/sns/latest/dg/DeliveryPolicies.html"&gt;http://docs.aws.amazon.com/sns/latest/dg/DeliveryPolicies.html&lt;/a&gt;&lt;/p&gt;
&lt;/section&gt;
</description><pubDate>Wed, 17 Jan 2018 00:00:00 </pubDate></item><item><title>Contributing to: zaqar-specs</title><link>https://specs.openstack.org/openstack/zaqar-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/zaqar"&gt;https://bugs.launchpad.net/zaqar&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;&lt;/blockquote&gt;
</description><pubDate>Wed, 13 Sep 2017 00:00:00 </pubDate></item><item><title>Persistent transport</title><link>https://specs.openstack.org/openstack/zaqar-specs/specs/backlog/persistent-transport.html</link><description>
 
&lt;p&gt;Persistent connections allow a single TCP connection to send and receive
multiple requests/responses instead of opening a new TCP connection for
each pair. When an application opens fewer TCP connections and keeps them
open for a longer period, it causes less network traffic, use less time
establishing new connections, and allows the TCP protocol to work more
efficiently.&lt;/p&gt;
&lt;p&gt;Currently Zaqar has support for a non-persistent transport, leaving aside
some use cases that would be covered in a more efficient and reliable way
with a persistent transport solution.&lt;/p&gt;
&lt;p&gt;Some use cases that will be positively impacted by this change are:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Communication with browsers: Websocket will enhance the communication
between browsers and Zaqar, a key factor in the integration of Zaqar with
the OpenStack Dashboard (Horizon).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Notifications: this type of transport will constitute a better protocol
for notifications, a feature planned for Kilo as well.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/zaqar/+spec/persistent-transport"&gt;https://blueprints.launchpad.net/zaqar/+spec/persistent-transport&lt;/a&gt;&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Currently there is no way to establish persistent connections in Zaqar.
This spec proposes adding this feature through a websocket implementation.&lt;/p&gt;
&lt;p&gt;During Kilo release we refactored the code to make the addition of this driver
feasible, and we worked on adding the queues endpoint.&lt;/p&gt;
&lt;p&gt;To provide full support for the data plane, we should add the messages endpoint
and the claims endpoint.&lt;/p&gt;
&lt;p&gt;The control plane operations do not require the performance that a websocket
driver can provide, hence we are not going to add websocket support for the
control plane.&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, as stated in previous sections, is to add a persistent
transport alternative to Zaqar. This can be done by using websocket.&lt;/p&gt;
&lt;p&gt;Websocket provide a full-duplex communication channel operating over a single
socket that will remove overhead and significantly reduce complexity.&lt;/p&gt;
&lt;section id="fallback"&gt;
&lt;h3&gt;Fallback&lt;/h3&gt;
&lt;p&gt;In case WebSocket is not available, the client will fallback to short-polling
the REST API.&lt;/p&gt;
&lt;p&gt;Some of the reasons of WebSockets not being available are:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Firewalls could be configured to kill HTTP connections after a certain
amount of time.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Concerns from a security standpoint will lead to killing any traffic
over port 80 or 443 that doesn’t look like HTTP.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="messages-serialization"&gt;
&lt;h3&gt;Messages serialization&lt;/h3&gt;
&lt;p&gt;A serialization technology is needed in order to transport data. There are
several alternatives, including JSON, MsgPack, Protobuf, Apache Avro and
Cap’n Proto.&lt;/p&gt;
&lt;p&gt;In the previous cycle we noted that the whereas MsgPack was the best candidate
-considering overall performance, easiness to use, languages support,
data structures support-, it doesn’t have good support for Javascript. Using
MsgPack would impose a significative constraint to the Zaqar use cases,
considering that many web applications nowaways are written with Javascript.
For that reason, we decided to stick with JSON and maybe talk about a more
performant serialization technology in a future change.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Establish persistent connections enabling WSGI keep-alive&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Long polling&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: vkmc&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;Implement messages controller&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Implement claims controller&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Write messages unit tests&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Write claims unit tests&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Would like to have: write functional tests&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Perform benchmarks with the new driver&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="websocket-libraries"&gt;
&lt;h3&gt;WebSocket Libraries&lt;/h3&gt;
&lt;p&gt;After discussing several alternatives, including SockJS, SocketIO, Autobahn,
ws4py and Tornado, it has been decided that Autobahn is going to be used to
implement this feature. More details on this decision will be available in
the &lt;a class="reference external" href="https://wiki.openstack.org/wiki/Zaqar/specs/websockets"&gt;WebSockets wiki&lt;/a&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="dependencies"&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/zaqar/+spec/cross-transport-api-spec"&gt;https://blueprints.launchpad.net/zaqar/+spec/cross-transport-api-spec&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>Finish client support for v1.1 features</title><link>https://specs.openstack.org/openstack/zaqar-specs/specs/liberty/finish-client-support-for-v1.1-features.html</link><description>
 
&lt;p&gt;&lt;a class="reference external" href="https://blueprints.launchpad.net/zaqar/+spec/finish-client-support"&gt;https://blueprints.launchpad.net/zaqar/+spec/finish-client-support&lt;/a&gt;-
for-v1.1-features&lt;/p&gt;
&lt;p&gt;Several endpoints have been added without being reflected on
the client side. This endpoints include:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Pools&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Flavors&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Notifications&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Adding support for these features would make developing applications with Zaqar
easier.&lt;/p&gt;
&lt;section id="problem-description"&gt;
&lt;h2&gt;Problem description&lt;/h2&gt;
&lt;p&gt;Python-zaqarclient currently has some missing features that need to be
added. This spec describes which endpoints are missing and how those are going
to be added to the client side.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="proposed-change"&gt;
&lt;h2&gt;Proposed change&lt;/h2&gt;
&lt;p&gt;Based on the endpoints that are currently missing to the python-zaqarclient
v1.1,the proposed change is to add support for the following features:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Pools:&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;pool_update&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;pool_list&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;ol class="arabic simple" start="2"&gt;
&lt;li&gt;&lt;p&gt;flavors:&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;flavor_update&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;flavor_list&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;ol class="arabic simple" start="3"&gt;
&lt;li&gt;&lt;p&gt;Notifications&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;section id="alternatives"&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="implementation"&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;section id="assignee-s"&gt;
&lt;h3&gt;Assignee(s)&lt;/h3&gt;
&lt;dl class="simple"&gt;
&lt;dt&gt;Primary assignee:&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;dynarro&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-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;Add support to:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;pools&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;flavors&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;notifications&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Add unit testing for:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;pools&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;flavors&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;notifications&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Add developers documentation for:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;pools&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;flavors&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;notifications&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;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, 23 Nov 2016 00:00:00 </pubDate></item><item><title>zaqar-specs</title><link>https://specs.openstack.org/openstack/zaqar-specs/readme.html</link><description>
 
&lt;p&gt;Queuing Service (Zaqar) 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="http://specs.openstack.org/openstack/zaqar-specs"&gt;http://specs.openstack.org/openstack/zaqar-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>Sun, 17 Aug 2014 00:00:00 </pubDate></item></channel></rss>