PK G6wN wN murano-specs-latest/rss.xmlMurano Specshttp://murano-specs.readthedocs.orgen2015, OpenStack Murano TeamMurano unified logginghttp://murano-specs.readthedocs.org/specs/liberty/murano-log-guildelines.html
<p><a class="reference external" href="https://blueprints.launchpad.net/murano/+spec/unified-style-logging">https://blueprints.launchpad.net/murano/+spec/unified-style-logging</a></p>
<p>Rewrite murano logging in unified OpenStack style proposed by
<a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/log-guidelines">https://blueprints.launchpad.net/nova/+spec/log-guidelines</a></p>
<div class="section" id="problem-description">
<h2>Problem description</h2>
<p>Now log levels and messages in murano are mixed and don’t match the OpenStack
logging guideliness.</p>
</div>
<div class="section" id="proposed-change">
<h2>Proposed change</h2>
<p>The good way to unify our log system would be to follow the major guidelines.
Here is a brief description of log levels:</p>
<ul class="simple">
<li>Debug: Shows everything and is likely not suitable for normal production
operation due to the sheer size of logs generated (e.g. scripts executions,
process execution, etc.).</li>
<li>Info: Usually indicates successful service start/stop, versions and such
non-error related data. This should include largely positive units of work
that are accomplished (e.g. service setup, environment create, successful
application deployment).</li>
<li>Warning: Indicates that there might be a systemic issue;
potential predictive failure notice (e.g. package execution problems,
problems with categories listing).</li>
<li>Error: An error has occurred and an administrator should research the event
(e.g. deployment failed, app add failed).</li>
<li>Critical: An error has occurred and the system might be unstable, anything
that eliminates part of murano’s intended functionality; immediately get
administrator assistance (e.g. failed to access keystone/database, plugin
load failed).</li>
</ul>
<p>As far as murano-dashboard has it own notification system all notifications
should be duplicated at log messages and should follow this spec in the selection
of log level.</p>
<p>Here are examples of log levels depending on environment execution:</p>
<ul class="simple">
<li>Action execution:</li>
</ul>
<div class="code python highlight-python"><div class="highlight"><pre><span class="n">LOG</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s">'Action:Execute <ActionId: {0}>'</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">action_id</span><span class="p">))</span>
</pre></div>
</div>
<ul class="simple">
<li>Environment creation:</li>
</ul>
<div class="code python highlight-python"><div class="highlight"><pre><span class="n">LOG</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="n">_LI</span><span class="p">(</span><span class="s">'Environments:Create {id} succeed>'</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="nb">id</span><span class="o">=</span><span class="n">environment</span><span class="o">.</span><span class="n">id</span><span class="p">)))</span>
</pre></div>
</div>
<ul class="simple">
<li>Package execution problems</li>
</ul>
<div class="code python highlight-python"><div class="highlight"><pre><span class="n">LOG</span><span class="o">.</span><span class="n">warning</span><span class="p">(</span><span class="n">_LW</span><span class="p">(</span><span class="s">"Class is defined in multiple packages!"</span><span class="p">))</span>
</pre></div>
</div>
<ul class="simple">
<li>Environment is not found</li>
</ul>
<div class="code python highlight-python"><div class="highlight"><pre><span class="n">LOG</span><span class="o">.</span><span class="n">error</span><span class="p">(</span><span class="n">_LE</span><span class="p">(</span><span class="s">'Environment {id} is not found'</span><span class="p">)</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="nb">id</span><span class="o">=</span><span class="n">environment_id</span><span class="p">))</span>
</pre></div>
</div>
<p>Additional step for our logging system should be usage of pep3101 as unified
format for all our logging messages. As soon as we try to make our code more
readable please use {<smthg>} instead of {0} in log messages.</p>
<div class="section" id="alternatives">
<h3>Alternatives</h3>
<p>We need to follow OpenStack guidelines, but if needed we can move plugin logs
to DEBUG level instead of INFO. It should be discussed separately in each case.</p>
</div>
<div class="section" id="data-model-impact">
<h3>Data model impact</h3>
<p>None</p>
</div>
<div class="section" id="rest-api-impact">
<h3>REST API impact</h3>
<p>None</p>
</div>
<div class="section" id="other-end-user-impact">
<h3>Other end user impact</h3>
<p>None</p>
</div>
<div class="section" id="deployer-impact">
<h3>Deployer impact</h3>
<p>None</p>
</div>
<div class="section" id="developer-impact">
<h3>Developer impact</h3>
<p>None</p>
</div>
<div class="section" id="murano-image-elements-impact">
<h3>murano-image-elements impact</h3>
<p>None</p>
</div>
<div class="section" id="murano-dashboard-horizon-impact">
<h3>murano-dashboard / Horizon impact</h3>
<p>None</p>
</div>
</div>
<div class="section" id="implementation">
<h2>Implementation</h2>
<div class="section" id="assignee-s">
<h3>Assignee(s)</h3>
<dl class="docutils">
<dt>Primary assignee:</dt>
<dd>starodubcevna</dd>
</dl>
</div>
<div class="section" id="work-items">
<h3>Work Items</h3>
<ul class="simple">
<li>Unify existing logging system</li>
<li>Unify logging messages</li>
<li>Synchronize dasboard notifications and log entries</li>
<li>Add additional logs if needed</li>
</ul>
</div>
</div>
<div class="section" id="dependencies">
<h2>Dependencies</h2>
<p>None</p>
</div>
<div class="section" id="testing">
<h2>Testing</h2>
<p>None</p>
</div>
<div class="section" id="documentation-impact">
<h2>Documentation Impact</h2>
<p>None</p>
</div>
<div class="section" id="references">
<h2>References</h2>
<p><a class="reference external" href="https://blueprints.launchpad.net/nova/+spec/log-guidelines">https://blueprints.launchpad.net/nova/+spec/log-guidelines</a>
<a class="reference external" href="https://www.python.org/dev/peps/pep-3101/">https://www.python.org/dev/peps/pep-3101/</a></p>
</div>
Thu, 23 Jul 2015 00:00:00 Add network selection element to UI formhttp://murano-specs.readthedocs.org/specs/liberty/ui-network-selection.html
<p>Include the URL of your launchpad blueprint:</p>
<p><a class="reference external" href="https://blueprints.launchpad.net/murano/+spec/ui-network-selection">https://blueprints.launchpad.net/murano/+spec/ui-network-selection</a></p>
<p>Sometime a VM should be placed to existing network rather then to a new network
created during deployment. While our workflows support this, there is no way
for the end user to select this network in the easy way in the UI. It will be
great if there is a special form element which will pre-populate a list of
available networks and provide an easy option to select desired network for the
application.</p>
<div class="section" id="problem-description">
<h2>Problem description</h2>
<p>Currently murano supports only so called “Default Scenario” when it comes to
networking: it creates a single network per environment, picks a router,
allocates an IP range and creates a subnet with this range within a created
network. This behavior is fine for most of the cases, however it may be
insufficient in complicated scenarios and topologies.</p>
<p>For example, an application may require some pre-configured networks to exist
so it may manipulate with the resources associated to them, allocate floating
IPs from the specific net etc. In this case, the existing net becomes a valid
input property for the application, so its developer may ask the users to
specify it before the deployment.</p>
<p>Another scenario is the need to have all the VMs of the environment to join
some pre-configured network - regardless of their configuration and the
applications they run for. This may be caused by some specific networking
requirements of a particular cloud (a frequent example is a custom proxy to
access the internet which is reachable only from a specific network segment).</p>
<p>When the Network Management scenarios were initially introduced in murano
<a class="reference external" href="https://wiki.openstack.org/wiki/Murano/Specifications/Network_Management">[1]</a>
we planed to have a so-called “Advanced scenario”, i.e to provide the users
with an ability to use existing networks, subnets, routers etc, or configure
some sophisticated combination of them.</p>
<p>This scenario was properly supported at engine and at the level of the Core
Library: the <cite>io.murano.resources.Instance</cite> class has a <cite>networks</cite> field which
allows to specify <cite>customNetworks</cite> as a collection of objects inheriting from
<cite>io.murano.resources.Network</cite>, which may include the existing networks or
new networks with non-default configuration.</p>
<p>However, there is no support of this functionality at the UI level: the object
model being generated by the Dynamic UI contains the default networking
definitions only: i.e. the directive to join Environment’s default network,
which is - in its turn - is hardcoded to be a newly created network and a
subnet in it.</p>
</div>
<div class="section" id="proposed-change">
<h2>Proposed change</h2>
<p>A new field will be added to the Dynamic UI framework which will allow to pick
the network and a subnet from the ones available to the current user. This will
be a drop-down list populated when the form is rendered.
The value selected by the user in this field will be a tuple, consisting of
the network id and a subnet id. This ids may be passed to the application
either as plain strings or as part of a more complicated Object Model, for
example as the properties of <cite>io.murano.resources.ExistingNeutronNetwork</cite>
objects. It is up to application developer to properly interpret and use these
values. The existing applications will not be affected by this change, as their
“configure instance” step of the UI dialog will not include any networking
settings. In future some of our standard apps may be updated to utilize this
new field, but those updates are out of the scope of this spec.</p>
<p>A similar field (but a static one rather then defined as part of Dynamic UI
framework) should be added to the <cite>New Environment</cite> dialog form, so the user
may choose an existing network to be the default network of a given
environment. The default value in that choice should lead to the creation of a
new environment’s network (i.e. to replicate the existing behavior), while any
other choice should lead to a generation of a new object of type
<cite>io.murano.resources.ExistingNeutronNetwork</cite> which will be passed to murano-api
as part of <cite>defaultNetworks</cite> dictionary as the default environment’s network.</p>
<p>Both these fields should share the same logic for value population.
Additionally, the dynamic UI field should have the following options, defined
as constructor arguments and exposed to dynamic ui as yaml attributes:</p>
<ul class="simple">
<li><em>include_subnets</em> - <cite>True</cite> by default. If <cite>True</cite>, the dropdown includes all
the possible combinations of network and subnet. E.g. if there are two
available networks X and Y, and X has two subnets A and B, while Y has a
single subnet C, then the dropdown will include 3 item: (X, A), (X, B),
(Y, C). If set to <cite>False</cite> the subnet info will not be retrieved, and <cite>None</cite>
values will be returned as second items in output tuples, so only network ids
are available.</li>
<li><em>filter</em> - <cite>None</cite> by default. If set to a regexp string, will be used to
display only the networks with names matching the given regexp.</li>
<li><em>murano_networks</em> - <cite>None</cite> by default. May have values <cite>None</cite>, <cite>exclude</cite> or
<cite>translate</cite>. Defines the handling of networks which are created by murano.
Such networks usually have very long randomly generated names, and thus look
ugly when displayed in dropdown. If this value is set to <cite>exclude</cite> then these
networks are not shown in the dropdown at all. If set to <cite>translate</cite> the
names of such networks are replaced by a string <cite>Network of %env_name%</cite>.
Note that this functionality is based on the simple string matching of the
network name prefix and the names of all the accessible murano environments.
If the environment is renamed after the initial deployment this feature will
not be able to properly translate or exclude its network name.</li>
<li><em>allow_auto</em> - <cite>True</cite> by default. Defines if the default value of the
dropdown (labeled “Auto”) should be present in the list. The default value is
a tuple consisting of two <cite>None</cite> values. The logic on how to treat this value
is up to application developer. It is suggested to use this field to indicate
that the instance should join default environment network. For use-cases
where such behavior is not desired, this parameter should be set to <cite>False</cite>.</li>
</ul>
<p>The string representation of the dropdown items should look like
<cite>%NetworkName%: %cidr% (%SubnetName%)</cite>, where <cite>%SubnetName%</cite> part is optional
and may be not present if the subnet’s name is not set.</p>
<p>If neutron is not available (so murano falls back to nova-network support) the
dropdown (both the static and dynamic ones) are not populated and appropriate
hints are available in the <cite>New Environment</cite> dialog.</p>
<div class="section" id="alternatives">
<h3>Alternatives</h3>
<p>Currently the only way to change the default networking behavior is the usage
of <cite>networking.yaml</cite> file which allows to override the networking setting at
the environment level, for all the murano environments of all the tenants. This
is not flexible enough and does not provide the desired user experience.</p>
<p>However this method will remain, as it allows to override the network setting
globally.</p>
</div>
<div class="section" id="data-model-impact">
<h3>Data model impact</h3>
<p>No impact. The existing data structures will be used.</p>
</div>
<div class="section" id="rest-api-impact">
<h3>REST API impact</h3>
<p>No impact. The existing API methods will be used.</p>
</div>
<div class="section" id="versioning-impact">
<h3>Versioning impact</h3>
<p>As this feature adds a new type of Dynamic UI fields this will bump the minor
version of Dynamic UI format version. The version will change from 2.0 to 2.1</p>
</div>
<div class="section" id="other-end-user-impact">
<h3>Other end user impact</h3>
<p>The user will see the new field in the “Create Environment” dialog. It will
also be shown when the environment is created inline in the environments grid.
The default value of this new field will follow the old behavior.</p>
<p>The user experience with the existing applications will not be changed.</p>
</div>
<div class="section" id="deployer-impact">
<h3>Deployer impact</h3>
<p>The dropdown in Dashboard will be calling public neutron APIs. If they are not
accessible due to some reason, the UI will guess that neutron is not installed
at all so nova network usage will be assumed.
However, the actual decision on the fallback to nova-network is done at the
murano-api. So, if the dashboard is unable to connect to neutron while the api
is then the behavior is inconsistent: the UI tells user that nova-network is
used, while this is not true. No error occur in this case though.</p>
</div>
<div class="section" id="developer-impact">
<h3>Developer impact</h3>
<p>The application developers may need to modify their apps to use the new
feature. Patch [2] may be used as an example.
Existing apps will not be affected, they will just have the old default
behavior.</p>
</div>
<div class="section" id="murano-dashboard-horizon-impact">
<h3>Murano-dashboard / Horizon impact</h3>
<p>The whole change proposed in this spec is a change of murano-dashboard.
No other components are modified.</p>
</div>
</div>
<div class="section" id="implementation">
<h2>Implementation</h2>
<div class="section" id="assignee-s">
<h3>Assignee(s)</h3>
<dl class="docutils">
<dt>Primary assignee:</dt>
<dd>ativelkov</dd>
<dt>Other contributors:</dt>
<dd>ddovbii</dd>
</dl>
</div>
<div class="section" id="work-items">
<h3>Work Items</h3>
<ul class="simple">
<li>Implement the shared logic to retrieve and filter the list of networks</li>
<li>Implement the DynamicUI control to select networks in apps</li>
<li>Add a dropdown field to a static Create Environment form to select the
default network of the environment.</li>
<li>Add the support of the new control in the existing murano apps in murano-apps
repository.</li>
</ul>
</div>
</div>
<div class="section" id="dependencies">
<h2>Dependencies</h2>
<ul class="simple">
<li>Include specific references to specs and/or blueprints in murano, or in other
projects, that this one either depends on or is related to.</li>
<li>If this requires functionality of another project that is not currently used
by Murano, document that fact.</li>
<li>Does this feature require any new library dependencies or code otherwise not
included in OpenStack? Or does it depend on a specific version of library?</li>
</ul>
</div>
<div class="section" id="testing">
<h2>Testing</h2>
<p>There should be an acceptance testing implemented on this feature:</p>
<ul class="simple">
<li>We should test deploying the apps with existing network selected and with the
default option.</li>
<li>Modified application (for example [2]) should be deployed both with “Auto” as
instance network or with some existing network selected.</li>
<li>The test cases above should verify the ability to assign floating IPs to the
VMs</li>
<li>The networks being used as an options for the manual selection should be
connected to a router uplinked to the external network (otherwise app
deployment will fail). Also the DNS nameservers has to be manually assigned
on those networks.</li>
</ul>
</div>
<div class="section" id="documentation-impact">
<h2>Documentation Impact</h2>
<p>A new Dynamic UI field type has to be documented at <cite>Dynamic UI definition
specification</cite> guide at [3]</p>
</div>
<div class="section" id="references">
<h2>References</h2>
<ul class="simple">
<li>[1] <a class="reference external" href="https://wiki.openstack.org/wiki/Murano/Specifications/Network_Management">https://wiki.openstack.org/wiki/Murano/Specifications/Network_Management</a></li>
<li>[2] <a class="reference external" href="https://review.openstack.org/#/c/201659/">https://review.openstack.org/#/c/201659/</a></li>
<li>[3] <a class="reference external" href="https://murano.readthedocs.org/en/latest/draft/appdev-guide/muranopackages/dynamic_ui.html#dynamicuispec">https://murano.readthedocs.org/en/latest/draft/appdev-guide/muranopackages/dynamic_ui.html#dynamicuispec</a></li>
</ul>
</div>
Tue, 21 Jul 2015 00:00:00 Add support for heat environmentshttp://murano-specs.readthedocs.org/specs/liberty/add-support-for-heat-environments.html
<p><a class="reference external" href="https://blueprints.launchpad.net/murano/+spec/add-support-for-heat-environments-and-files">https://blueprints.launchpad.net/murano/+spec/add-support-for-heat-environments-and-files</a></p>
<p>Add support for using Heat environments, when saving and deploying Heat
templates.</p>
<div class="section" id="problem-description">
<h2>Problem description</h2>
<p>Today there is no option to create stacks neither with an environment nor with
nested stacks via Murano. Only basic stacks are supported.</p>
<p>Use cases for deploying a stack with an environment:</p>
<ul class="simple">
<li>Supporting resource registry</li>
<li>Supporting saving ‘test’ and ‘production’ parameter profiles for the same
template</li>
</ul>
</div>
<div class="section" id="proposed-change">
<h2>Proposed change</h2>
<p>The change described here will focus on supporting Heat environments. Another
spec was submitted for Heat files.</p>
<p>In this spec no UI changes are included. A UI part that can be added in future
specs, and in any case is out of the scope of this spec.</p>
<p>Allowing Heat environments to be saved and deployed as part of a Murano Heat
package. Adding environments to a package should be optional. Heat environment
files should be placed in the package under ‘/Resources/HotEnvironments’ When a
user request to add a Heat-generated package to a Murano environment, he should
have an option to specify one of the hot-environment-files located at
‘/Resources/HotEnvironments’ in the package, and this heat environment file
should be sent to Heat with the template during Murano environment deployment.
If no heat environment file was specified, the template will be deployed
without a Heat environment.
The stage where the Heat environment for the deployment should be specified
is when adding a package to a Murano environment as part of a configuration
session.
The heat environment should be referenced by name.</p>
<p>In the future, there can be an API to list the hot environments of a package.
This might be done by using the existing API of getting the UI of a package.</p>
<div class="section" id="alternatives">
<h3>Alternatives</h3>
<ul class="simple">
<li>The package structure can be different.</li>
<li>Words that can replace the word environments to reference heat environments:
configurations, profiles, settings. The problem is that in Heat they use the
word environments.</li>
<li>Specifying the heat environment to be deployed with the Heat template as
part of a Murano environment when deploying the environment (instead of
specifying it when adding a package to an environment). If we will wait to
this point, we will have to give a map of packages and the environments to be
deployed with them. this alternative requires more validations.</li>
</ul>
</div>
<div class="section" id="data-model-impact">
<h3>Data model impact</h3>
<p>new data objects:</p>
<ul class="simple">
<li>hotEnvironment - This parameter will be passed as part of the
/environments/{env-id}/services POST API request body. The value of this
parameter will be an environment file name.</li>
<li>templateParameters - All heat parameters that were passed in the root of the
/environments/{env-id}/services POST API request body, will be moved under
this property.</li>
</ul>
</div>
<div class="section" id="rest-api-impact">
<h3>REST API impact</h3>
<p>None</p>
</div>
<div class="section" id="versioning-impact">
<h3>Versioning impact</h3>
<p>None</p>
</div>
<div class="section" id="other-end-user-impact">
<h3>Other end user impact</h3>
<p>User will now have the option to add heat environments and additional files to
the package, and have them deployed with the package as part of the Murano
environment. The Heat environment will be deployed when it is requested in the
relevant API, while the additional files will always be deployed.</p>
<p>At this point there will be no change in the python-muranoclient. If the user
will wish to add environments or additional files to a heat generated package.
He can edit the package and continue via API. If the user only added additional
files, he can continue via python-muranoclient/UI as well.</p>
</div>
<div class="section" id="deployer-impact">
<h3>Deployer impact</h3>
<p>None</p>
</div>
<div class="section" id="developer-impact">
<h3>Developer impact</h3>
<p>None</p>
</div>
<div class="section" id="murano-dashboard-horizon-impact">
<h3>Murano-dashboard / Horizon impact</h3>
<p>New features must not break UI. So since it was proposed to move the user
defined parameters from the root of the request body to the property
“templateParameters”, the UI must change the way it build the request to add a
package to a Murano environment.</p>
<p>The new feature for sending a hot environment with the template will be exposed
in the UI the following way:
The user will be able to choose an environment file from a drop-down list
during the same wizard actions he uses to enter heat template parameters.</p>
</div>
</div>
<div class="section" id="implementation">
<h2>Implementation</h2>
<p>new data objects:
* envs
* env_name</p>
<p>envs will be generated when parsing the package, so if there is nothing in the
package, the new data objects will be empty. If an API to list the environments
will be implemented an empty list will return, same as in other Murano APIs.</p>
<p>A new object called envs of type dictionary will be added in HeatStack class
in the init method. It can be referenced from inside HeatStack by using
self._envs before/when sending the create request to Heat. This object will be
initialized to be empty.</p>
<p>A new method called setEnvs will be added in HeatStack class. It will allow to
enter a value into _envs just like setParameters allows to enter values into
_parameters.</p>
<p>env_name will take the value passed by the user in the parameter
heatEnvironment. It will be initialized and passed to class HeatStack the same
way parameters are passed today.</p>
<p>When sending the create stack request to heat the selected environment content
should be passed. If all is configured and passed correctly the environment
file content can be accessed from class HeatStack by using the next command:
self._envs[self._env_name]</p>
<p>A new method called _translate_envs will be add to HotPackage class. it will
get a path to the envs directory and will return a dictionary of environments
locations and files values. It will be in the next format:
environmentRelativePathStartingHeatEnvironmentsDirectory -> stringFileContent
For example if there is an environment with a full path of
/Resources/HeatEnvironments/my_heat_env.yaml and content of:
“heat_template_version: 2013-05-23nnparameters:n” and it
is the only file in the folder, than this will be the dictionary returned:
{“my_heat_env.yaml”: “heat_template_version: 2013-05-23nnparameters:n”}</p>
<p>A very similar function was proposed for the Heat files feature. There will be
a reuse of the code there, if it will be implemented first.</p>
<div class="section" id="assignee-s">
<h3>Assignee(s)</h3>
<dl class="docutils">
<dt>Primary assignee:</dt>
<dd>michal-gershenzon</dd>
<dt>Other contributors:</dt>
<dd>noa-koffman</dd>
</dl>
</div>
<div class="section" id="work-items">
<h3>Work Items</h3>
<ul class="simple">
<li>Add support for adding a package to a Murano environment with a Heat
environment specified in the request.</li>
<li>Add support for Heat environments when deploying a Murano environment. If
a Heat environment is saved in the session for the package, it should be
parsed and send with the template, when deploying a Murano environment.</li>
<li>make sure that when ui generate a POST request for API:
/environments/{env-id}/services the user defined parameters are located under
templateParameters in the request body.</li>
</ul>
</div>
</div>
<div class="section" id="dependencies">
<h2>Dependencies</h2>
<p>None</p>
</div>
<div class="section" id="testing">
<h2>Testing</h2>
<p>Unit tests should cover API calls changes:</p>
<ul class="simple">
<li>Test sending a Heat environment when adding a package to a Murano environment
(positive and negative).</li>
<li>Test that the request for Heat is build correctly with Heat environment</li>
</ul>
</div>
<div class="section" id="documentation-impact">
<h2>Documentation Impact</h2>
<p>None</p>
</div>
<div class="section" id="references">
<h2>References</h2>
<ul class="simple">
<li><a class="reference external" href="http://docs.openstack.org/developer/heat/template_guide/environment.html">http://docs.openstack.org/developer/heat/template_guide/environment.html</a></li>
</ul>
</div>
Thu, 16 Jul 2015 00:00:00 Add support for heat environments and fileshttp://murano-specs.readthedocs.org/specs/liberty/add-support-for-heat-files.html
<p><a class="reference external" href="https://blueprints.launchpad.net/murano/+spec/add-support-for-heat-environments-and-files">https://blueprints.launchpad.net/murano/+spec/add-support-for-heat-environments-and-files</a></p>
<p>Add support for using Heat additional files, when saving and deploying Heat
templates.</p>
<div class="section" id="problem-description">
<h2>Problem description</h2>
<p>Today there is no option to create stacks neither with an environment nor with
nested stacks via Murano. Only basic stacks are supported.</p>
<p>Use cases for deploying a stack with additional files:</p>
<ul class="simple">
<li>Supporting Heat nested stacks</li>
<li>Supporting scripts</li>
</ul>
<p>For more information see references section of this spec</p>
</div>
<div class="section" id="proposed-change">
<h2>Proposed change</h2>
<p>The change described here will focus on supporting additional files. Another
spec will be submitted for Heat environments.</p>
<p>Allowing Heat additional files to be saved and deployed as part of a Murano
Heat applications. Adding additional files to a package should be optional.
Such files should be placed in the package under ‘/Resources/HeatFiles’. When a
Heat generated package is being deployed, if the package contains Heat files,
they should be sent to Heat together with the template and params. If there are
any Heat additional files located in the package under ‘/Resources/HeatFiles’,
they should all be sent with the template during stack creation in Heat.</p>
<p>There can be more nested directories under ‘/Resources/HeatFiles’, and if they
have files in them, those should be send to heat as well together with their
relative path.</p>
<p>This part does not require any UI nor API changes.</p>
<div class="section" id="alternatives">
<h3>Alternatives</h3>
<ul class="simple">
<li>The package structure can be different.</li>
</ul>
</div>
<div class="section" id="data-model-impact">
<h3>Data model impact</h3>
<p>None</p>
</div>
<div class="section" id="rest-api-impact">
<h3>REST API impact</h3>
<p>None</p>
</div>
<div class="section" id="versioning-impact">
<h3>Versioning impact</h3>
<p>None</p>
</div>
<div class="section" id="other-end-user-impact">
<h3>Other end user impact</h3>
<p>User will have the option to add Heat files to the package, and have them
deployed with the package as part of the Murano environment.</p>
<p>At this point there will be no change in the python-muranoclient. If the user
will wish to add files to a heat generated package, he can edit the package and
continue normally from there.</p>
</div>
<div class="section" id="deployer-impact">
<h3>Deployer impact</h3>
<p>None</p>
</div>
<div class="section" id="developer-impact">
<h3>Developer impact</h3>
<p>None</p>
</div>
<div class="section" id="murano-dashboard-horizon-impact">
<h3>Murano-dashboard / Horizon impact</h3>
<p>None.</p>
</div>
</div>
<div class="section" id="implementation">
<h2>Implementation</h2>
<p>new data objects:
* files</p>
<p>This new data object will be generated when parsing the package, so if there
is nothing in the package, the new data objects will be empty.</p>
<p>A new object called files of type dictionary will be added in HeatStack class
in the init method. It can be referenced from inside HeatStack by using
self._files when sending the create request to Heat. This object will be
initialized to be empty.</p>
<p>A new method called setFiles will be added in HeatStack class. It will allow to
enter a value into _files just like setParameters allows to enter values into
_parameters.</p>
<p>A new method called _translate_files will be add to HotPackage class. it will
get a path to the files directory and will return a dictionary of files
locations and files values. It will be in the next format:
fileRelativePathStartingHeatFilesDirectory -> stringFileContent
For example if there is a file with a full path of
/Resources/HeatFiles/my_heat_file.yaml and content of “echo hello world” and it
is the only file in the folder, than this will be the dictionary returned:
{“my_heat_file.yaml”: “echo hello world”}</p>
<p>A new parameter of called files will be added to _generate_workflow method that
can be found inside HotPackage class. It will be included in the deploy
variable in the same way the template_parameters is included.</p>
<div class="section" id="assignee-s">
<h3>Assignee(s)</h3>
<dl class="docutils">
<dt>Primary assignee:</dt>
<dd>michal-gershenzon</dd>
<dt>Other contributors:</dt>
<dd>noa-koffman</dd>
</dl>
</div>
<div class="section" id="work-items">
<h3>Work Items</h3>
<ul class="simple">
<li>Add support for Heat additional-files. If such files exist in the package,
they should be parsed and send with the template, when deploying a Murano
environment.</li>
</ul>
</div>
</div>
<div class="section" id="dependencies">
<h2>Dependencies</h2>
<p>None</p>
</div>
<div class="section" id="testing">
<h2>Testing</h2>
<p>Unit tests should cover API calls changes:</p>
<ul class="simple">
<li>Test that the request for Heat is build correctly with Heat files</li>
</ul>
</div>
<div class="section" id="documentation-impact">
<h2>Documentation Impact</h2>
<p>None</p>
</div>
<div class="section" id="references">
<h2>References</h2>
<ul class="simple">
<li><a class="reference external" href="http://docs.openstack.org/developer/heat/template_guide/hot_spec.html#get-file">http://docs.openstack.org/developer/heat/template_guide/hot_spec.html#get-file</a></li>
</ul>
</div>
Wed, 15 Jul 2015 00:00:00 Download bundle of packages to local directory using muranoclienthttp://murano-specs.readthedocs.org/specs/liberty/bundle-save.html
<p><a class="reference external" href="https://blueprints.launchpad.net/murano/+spec/bundle-save">https://blueprints.launchpad.net/murano/+spec/bundle-save</a></p>
<p>The purpose is to add command to muranoclient which allows to download the
bundle from application catalog to local dir.</p>
<div class="section" id="problem-description">
<h2>Problem description</h2>
<p>There are cases when there is no Internet access cloud with murano installed.
Then if user wants to add some bundle of packages into murano, he has to
download all of them one-by-one from application catalog using local computer
with access to the Internet. After that he saves them somewhere on data storage
device and moves all files to cloud.</p>
<p>It is necessary to simplify process of saving packages to avoid manual
downloading.</p>
</div>
<div class="section" id="proposed-change">
<h2>Proposed change</h2>
<p>It’s proposed to add new CLI command <em>bundle-save</em> to murano-client.</p>
<p>Method <em>do_bundle_save</em> will corresponds with new command. It will take three
arguments:</p>
<ul class="simple">
<li><em>filename</em> is a bundle name, bundle url or path to the bundle file;</li>
<li><em>–path</em> (optional) is a path to directory in which user wants save packages.
If it is not specified, current directory will be used;</li>
<li><em>–no-images</em> (optional) is flag. If it is set, downloading of all required
images will be skipped.</li>
</ul>
<p>Method will build whole list of packages and its dependencies. This ability is
already implemented and used in ‘bundle-import’. Then method will save bundle
file and each package to specified path. For this, method ‘save’ will be added
to <em>FileWrapperMixin</em> – the parent class for <em>Bundle</em> and <em>Package</em> classes.
This method will take one argument <em>dst</em> – destination for file. It will copy
already downloaded file to the specified path.</p>
<p>Method <em>do_bundle_save</em> will also save images which packages require.
<em>save_image_local</em> method will be used for that. All images will be downloaded
if <em>–no-images</em> is not set.</p>
<p>After bundle saving directory with packages can be moved to lab with murano
where all of them can be imported to murano application catalog in one
command.</p>
<p>CLI command <em>package-save</em> also must be implemented. It will give to user the
opportunity to download specific package or several packages he need.
The implementation of command will be based on the methods described above.</p>
<div class="section" id="alternatives">
<h3>Alternatives</h3>
<p>None</p>
</div>
<div class="section" id="data-model-impact">
<h3>Data model impact</h3>
<p>None</p>
</div>
<div class="section" id="rest-api-impact">
<h3>REST API impact</h3>
<p>None</p>
</div>
<div class="section" id="versioning-impact">
<h3>Versioning impact</h3>
<p>None</p>
</div>
<div class="section" id="other-end-user-impact">
<h3>Other end user impact</h3>
<p>User will have access to a new command.</p>
</div>
<div class="section" id="deployer-impact">
<h3>Deployer impact</h3>
<p>None</p>
</div>
<div class="section" id="developer-impact">
<h3>Developer impact</h3>
<p>None</p>
</div>
<div class="section" id="murano-dashboard-horizon-impact">
<h3>Murano-dashboard / Horizon impact</h3>
<p>None</p>
</div>
</div>
<div class="section" id="implementation">
<h2>Implementation</h2>
<div class="section" id="assignee-s">
<h3>Assignee(s)</h3>
<p>Dmytro Dovbii</p>
<dl class="docutils">
<dt>Primary assignee:</dt>
<dd>ddovbii</dd>
</dl>
</div>
<div class="section" id="work-items">
<h3>Work Items</h3>
<ul class="simple">
<li>Add method <em>save_image_local</em></li>
<li>Add method <em>save()</em> to <em>FileWrapperMixin</em> class</li>
<li>Implement CLI command <em>bundle-save</em></li>
<li>Implement CLI commamd <em>package-save</em></li>
</ul>
</div>
</div>
<div class="section" id="dependencies">
<h2>Dependencies</h2>
<p>None</p>
</div>
<div class="section" id="testing">
<h2>Testing</h2>
<p>Unit tests for CLI client must be updated</p>
</div>
<div class="section" id="documentation-impact">
<h2>Documentation Impact</h2>
<p>CLI reference should be updated manually</p>
</div>
<div class="section" id="references">
<h2>References</h2>
<p>None</p>
</div>
Thu, 09 Jul 2015 00:00:00 Logging API for MuranoPLhttp://murano-specs.readthedocs.org/specs/liberty/logging-api-for-muranopl.html
<p><a class="reference external" href="https://blueprints.launchpad.net/murano/+spec/logging-api-for-muranopl">https://blueprints.launchpad.net/murano/+spec/logging-api-for-muranopl</a></p>
<p>The purpose is to add an ability to log actions while developing MuranoPL
applications</p>
<div class="section" id="problem-description">
<h2>Problem description</h2>
<p>It is good practice to log basic stages during application execution.
Logging API should make debugging and troubleshooting processes easier.</p>
</div>
<div class="section" id="proposed-change">
<h2>Proposed change</h2>
<p>Implemention key points</p>
<ol class="arabic">
<li><p class="first">New MuranoPL class <cite>io.murano.system.Logger</cite></p>
<blockquote>
<div><p>Class <cite>Logger</cite> will be part of the MuranoPL core library.</p>
<p>This class should contain basic logging functionality.
Usage example in MuranoPL:</p>
<div class="highlight-python"><div class="highlight"><pre>$.log: logger('logger_name')
$.log.info('message: {0}', 'checkpoint')
</pre></div>
</div>
<p>that code should be equivalent of python code:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">oslo_log</span> <span class="kn">import</span> <span class="n">log</span> <span class="k">as</span> <span class="n">logging</span>
<span class="n">LOG</span> <span class="o">=</span> <span class="n">logging</span><span class="o">.</span><span class="n">getLogger</span><span class="p">(</span><span class="s">'logger_name'</span><span class="p">)</span>
<span class="n">LOG</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="n">_LI</span><span class="p">(</span><span class="s">'message: {0}'</span><span class="p">)</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="s">'checkpoint'</span><span class="p">))</span>
</pre></div>
</div>
<p>Others logging methods are <cite>Logger.debug</cite>, <cite>Logger.info</cite>, <cite>Logger.warning</cite>,
<cite>Logger.error</cite>, <cite>Logger.critical</cite>. Each method corresponds to the oslo.log
logging level.</p>
<p>There is also separate method for exception stack trace output described
below.</p>
</div></blockquote>
</li>
<li><p class="first">Exceptions logging</p>
<blockquote>
<div><p>Method <cite>Logger.exception</cite> intended to log a stack trace:</p>
<div class="highlight-python"><div class="highlight"><pre>$.log.exception(exc, 'Something bad happened: {0}', 'Oops!')
</pre></div>
</div>
</div></blockquote>
<p><cite>exception</cite> method uses the same log level as <cite>Logger.error</cite>.</p>
</li>
<li><p class="first">New global MuranoPL function <cite>logger()</cite></p>
<blockquote>
<div><p>Call of the function <cite>logger(‘logger_name’)</cite> returns new instance of the
<cite>io.murano.system.Logger</cite>. If function with the same <cite>logger_name</cite> was
called previously then the same logger instance should be returned instead of
building new one.</p>
</div></blockquote>
</li>
<li><p class="first">Logging configuration</p>
<blockquote>
<div><p>Logging should use standard Murano Engine logging subsystem.</p>
<p>Application itself cannot set logging settings at runtime.</p>
<p>All of appenders, formatters an etc. may be configured via standard way
as others loggers in Murano Engine.</p>
<p>Prefix <cite>applications</cite> should be added to each logger name which created by
application. As example, logger named <cite>active_directory</cite> in the MuranoPL
should be identified as <cite>applications.active_directory</cite> at the python side
and in the system config. This is for separation loggers used by
applications and engine system loggers. Also it will allow us to specify
settings for the application loggers separately from others loggers.</p>
</div></blockquote>
</li>
<li><p class="first">Default configuration</p>
<blockquote>
<div><p>All logs written in the one file by default. Log rotation should be used,
so maximum size of logs is limited.</p>
</div></blockquote>
</li>
<li><p class="first">Logging naming conventions</p>
<blockquote>
<div><p>A note about the logging naming conventions should be added to the MuranoPL
tutorial.</p>
</div></blockquote>
</li>
</ol>
<div class="section" id="alternatives">
<h3>Alternatives</h3>
<p>None</p>
</div>
<div class="section" id="data-model-impact">
<h3>Data model impact</h3>
<p>None</p>
</div>
<div class="section" id="rest-api-impact">
<h3>REST API impact</h3>
<p>None</p>
</div>
<div class="section" id="versioning-impact">
<h3>Versioning impact</h3>
<p>None</p>
</div>
<div class="section" id="other-end-user-impact">
<h3>Other end user impact</h3>
<p>None</p>
</div>
<div class="section" id="deployer-impact">
<h3>Deployer impact</h3>
<p>Deployer will get more information about application execution stages and additional
tool for more precise troubleshooting</p>
</div>
<div class="section" id="developer-impact">
<h3>Developer impact</h3>
<p>Logging API will allow developer to debug application in a more effective manner
getting information from logs.</p>
</div>
<div class="section" id="murano-dashboard-horizon-impact">
<h3>Murano-dashboard / Horizon impact</h3>
<p>None</p>
</div>
</div>
<div class="section" id="implementation">
<h2>Implementation</h2>
<div class="section" id="assignee-s">
<h3>Assignee(s)</h3>
<p>Alexey Khivin</p>
<dl class="docutils">
<dt>Primary assignee:</dt>
<dd><<a class="reference external" href="mailto:akhivin%40mirantis.com">akhivin<span>@</span>mirantis<span>.</span>com</a>></dd>
</dl>
</div>
<div class="section" id="work-items">
<h3>Work Items</h3>
<ul class="simple">
<li>Create new MuranoPL class <cite>io.murano.system.Logger</cite></li>
<li>Create new global MuranoPL function <cite>logger()</cite></li>
<li>Create method <cite>Logger.exception</cite></li>
<li>Add new section for logging parameters into the Murano Engine config</li>
<li>Describe naming conventions for loggers in the Murano docs</li>
</ul>
</div>
</div>
<div class="section" id="dependencies">
<h2>Dependencies</h2>
<p>None</p>
</div>
<div class="section" id="testing">
<h2>Testing</h2>
<p>Functional tests for MuranoPL must be updated.</p>
</div>
<div class="section" id="documentation-impact">
<h2>Documentation Impact</h2>
<p>MuranoPL</p>
</div>
<div class="section" id="references">
<h2>References</h2>
<p>None</p>
</div>
Tue, 07 Jul 2015 00:00:00 Rework package class loader logichttp://murano-specs.readthedocs.org/specs/liberty/change-murano-class-loader.html
<p><a class="reference external" href="https://blueprints.launchpad.net/murano/+spec/change-murano-class-loader">https://blueprints.launchpad.net/murano/+spec/change-murano-class-loader</a></p>
<p>This spec describes rework of murano package class loader as part of the
another blueprint <a class="reference external" href="https://blueprints.launchpad.net/murano/+spec/simulated-execution-mode-murano-engine">simulated-execution-mode-murano-engine</a>.</p>
<p>The detailed logic regarding class modification would be described in this
specification.</p>
<div class="section" id="problem-description">
<h2>Problem description</h2>
<p>Class loader should be able to load packages not only from the external
repository, but from a local directory. It’s needed not only for testing new
packages, but for accepting packages on-the-fly.
During the development phase the package gets frequently updated, and the need
to upload it to the repository on each update complicates the development.
Ability to load it from the local filesystem will streamline the process</p>
<p>Another case, when there is no connection to the external repository.</p>
</div>
<div class="section" id="proposed-change">
<h2>Proposed change</h2>
<p>Need to create one more class, responsible for loading packages.
It will look up at the provided directory for a package, that name was requested.
It worth noting, that packages should not be zipped.</p>
<p>Class loader from repository (RCL) and new class loader from local dir (LCL)
will provide the following logic:</p>
<ul>
<li><p class="first">If local dir is not provided, LCL is not operating.
Logic stays same as it’s now. RCL do all the work.</p>
</li>
<li><p class="first">If directory path or several paths to load local packages from are provided,
LCL will check all packages in dir and compare with requested name.
If the desired class is found, package gets loaded. If not - next dir in the
provided list will be scaned.</p>
<p>If is not found in all the provided directories - RCL sends API call to find
it in the repository as usual.</p>
</li>
</ul>
<p>We do have both class loader implemented, we need an ability to combine two
(or more) package loaders in one, with the ability to prioritize the queries.
For example, a <tt class="docutils literal"><span class="pre">CombinedPackageLoader</span></tt> may be created with an instances of
<tt class="docutils literal"><span class="pre">DirectoryPackageLoader</span></tt> and <tt class="docutils literal"><span class="pre">ApiPackageLoader</span></tt> underneath. When a
request for a package or class comes in, it is first executed against loader
with the highest priority (say, <tt class="docutils literal"><span class="pre">DirectoryPackageLoader</span></tt>), and if it is not
found there, then goes to the next one.</p>
<div class="section" id="alternatives">
<h3>Alternatives</h3>
<p>Use separate class loader in test framework.
But support two different class loaders is not good.</p>
<p>Also as an alternative we can also mention
<a class="reference external" href="https://docs.djangoproject.com/en/1.7/ref/settings/#std:setting-TEMPLATE_LOADERS">this</a>
approach.
That is: introduce package_loaders config parameter. It can be a list of
python-dot-notation class names, that murano would import and try to import pkg
from each loader. This could further be modified to a list of lists, to allow params
like this:
<cite>package_loaders: [pkg_loader1, [pkg_loader2, param1, param2]]</cite>
This would allow to easily add custom loaders without changing murano code itself.</p>
</div>
<div class="section" id="data-model-impact">
<h3>Data model impact</h3>
<p>None</p>
</div>
<div class="section" id="rest-api-impact">
<h3>REST API impact</h3>
<p>None</p>
</div>
<div class="section" id="versioning-impact">
<h3>Versioning impact</h3>
<p>None</p>
</div>
<div class="section" id="other-end-user-impact">
<h3>Other end user impact</h3>
<p>None</p>
</div>
<div class="section" id="deployer-impact">
<h3>Deployer impact</h3>
<p>Enabling loading packages from local directory will be set up in config file.</p>
<p>New key in config file will be added under <em>[engine]</em> section and look
like that:</p>
<p># Directory used as a way to load packages from. (string value)
# local_packages_dir = <None></p>
</div>
<div class="section" id="developer-impact">
<h3>Developer impact</h3>
<p>None</p>
</div>
<div class="section" id="murano-dashboard-horizon-impact">
<h3>Murano-dashboard / Horizon impact</h3>
<p>None</p>
</div>
</div>
<div class="section" id="implementation">
<h2>Implementation</h2>
<div class="section" id="assignee-s">
<h3>Assignee(s)</h3>
<dl class="docutils">
<dt>Primary assignee:</dt>
<dd><efedorova></dd>
<dt>Other contributors:</dt>
<dd><ativelkov>, <slagun></dd>
</dl>
</div>
<div class="section" id="work-items">
<h3>Work Items</h3>
<ul class="simple">
<li>Implement <tt class="docutils literal"><span class="pre">CombinedPackageLoader</span></tt>:</li>
<li>Perform testing</li>
</ul>
</div>
</div>
<div class="section" id="dependencies">
<h2>Dependencies</h2>
<ul class="simple">
<li>Murano Simulation Mode:
<a class="reference external" href="https://blueprints.launchpad.net/murano/+spec/simulated-execution-mode-murano-engine">https://blueprints.launchpad.net/murano/+spec/simulated-execution-mode-murano-engine</a></li>
</ul>
</div>
<div class="section" id="testing">
<h2>Testing</h2>
<p>Unit tests should be added/updated.</p>
</div>
<div class="section" id="documentation-impact">
<h2>Documentation Impact</h2>
<p>Opportunity to load apps from local directory should be described in the
documentation.</p>
</div>
<div class="section" id="references">
<h2>References</h2>
<p>None</p>
</div>
Mon, 06 Jul 2015 00:00:00 Configure environments from CLIhttp://murano-specs.readthedocs.org/specs/liberty/env-configuration-from-cli.html
<p>Blueprint for this specification:</p>
<p><a class="reference external" href="https://blueprints.launchpad.net/python-muranoclient/+spec/env-configuration-from-cli">https://blueprints.launchpad.net/python-muranoclient/+spec/env-configuration-from-cli</a></p>
<p>Currently there is no way to configure and/or deploy a murano environment from
the command line. This specification describes how this issue can be addressed
and what steps have to be taken in order to implement this abilities.</p>
<div class="section" id="problem-description">
<h2>Problem description</h2>
<p>Currently the only possible way to deploy a murano environment is through
interaction with horizon. CLI client currently lacks commands to add apps to
environment or deploy an environment. This makes murano useless without horizon
and murano-dashboard.
It also means, that scripting and/or automating deployment of murano
apps/environments is currently problematic to say the least.</p>
</div>
<div class="section" id="proposed-change">
<h2>Proposed change</h2>
<p>This spec proposes to add several new CLI commands and modify existing to
allow user to add apps to the env, configure it and send it to deploy.</p>
<p>Command <tt class="docutils literal"><span class="pre">environment-create</span></tt> currently only supports adding the name of the
environment, while the api call supports setting aditional params, such as
defaultNetworks. <tt class="docutils literal"><span class="pre">environment-create</span></tt> should be updated to allow setting
custom keys to environment model.</p>
<p><tt class="docutils literal"><span class="pre">environment-edit</span></tt> command should perform all the editing (adding, deleting,
modifying of existing apps)
This command should be non-interctive, adding an interactive mode is a
good idea as of itself, but is out of scope of this spec.</p>
<p><tt class="docutils literal"><span class="pre">environment-edit</span></tt> would use jsonpatch format for input (as described by
RFC 6902). This is a well known and powerfull instrument to manipulate json,
and object model is currently stored in json.
This would allow easy addition, modification and deletion of apps.
Editing of environment attributes is not allowed by API, so it’s beyond the
scope of this spec.</p>
<p>During command execution, env configuration parameters should be read from
stdin or a file.
Supporting stdin as input source means it should be possible to issue a
command like <tt class="docutils literal"><span class="pre">murano</span> <span class="pre">environment-edit</span> <span class="pre">env_id</span> <span class="pre"><</span> <span class="pre">app_patch.json</span></tt></p>
<p>An example <tt class="docutils literal"><span class="pre">app_patch.json</span></tt> might look like:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="p">[</span>
<span class="p">{</span> <span class="s">"op"</span><span class="p">:</span> <span class="s">"add"</span><span class="p">,</span> <span class="s">"path"</span><span class="p">:</span> <span class="s">"/services/-"</span><span class="p">,</span>
<span class="s">"value"</span><span class="p">:</span>
<span class="p">{</span><span class="s">'?'</span><span class="p">:</span>
<span class="p">{</span><span class="s">'id'</span><span class="p">:</span> <span class="s">'2fc3005d-b4f8-420d-9e15-f961b41f49ee'</span><span class="p">,</span>
<span class="s">'type'</span><span class="p">:</span> <span class="s">'io.murano.apps.App1'</span>
<span class="p">},</span>
<span class="s">'instance'</span><span class="p">:</span>
<span class="p">{</span><span class="s">'?'</span><span class="p">:</span> <span class="p">{</span><span class="s">'id'</span><span class="p">:</span> <span class="s">'53366263-04e9-49d1-829d-50e27158749c'</span><span class="p">,</span>
<span class="s">'type'</span><span class="p">:</span> <span class="s">'io.murano.resources.LinuxMuranoInstance'</span><span class="p">},</span>
<span class="s">'assignFloatingIp'</span><span class="p">:</span> <span class="bp">True</span><span class="p">,</span>
<span class="s">'availabilityZone'</span><span class="p">:</span> <span class="s">'nova'</span><span class="p">,</span>
<span class="s">'flavor'</span><span class="p">:</span> <span class="s">'m1.medium'</span><span class="p">,</span>
<span class="s">'image'</span><span class="p">:</span> <span class="s">'afc1aa61-f623-4c66-bbd8-5359261c5272'</span><span class="p">,</span>
<span class="s">'name'</span><span class="p">:</span> <span class="s">'ilphvibwqyu6h1'</span> <span class="p">},</span>
<span class="s">'name'</span><span class="p">:</span> <span class="s">'App1'</span>
<span class="p">}</span>
<span class="p">},</span>
<span class="p">]</span>
</pre></div>
</div>
<p>All operations would only apply to services field, so the <cite>/services/</cite> part of
the path can be ommited.</p>
<dl class="docutils">
<dt>note::</dt>
<dd>This means, that a user has to generate unique ids. This can be a difficult
task and may hinder scripting capabilities. We might think of a way to
mitigate this issue, by introducing a way to generate ids. This can be done
by introducing an optional parameter <tt class="docutils literal"><span class="pre">--id-format</span></tt>. It would accept a
template for strings to be replaced with generated ids. For example:
<tt class="docutils literal"><span class="pre">--id-format=##id##</span></tt> would replace all occurrences of ##id##-1 with fist
generated id, all occurrences of ##id##-2 with second generated id and all
occurrences of ##id## with a unique id. uuids should be used for id
generation.</dd>
</dl>
<p>Command should perform validation of its input. This can be done using
MuranoPL classes and property contracts.
If an error happens during non-interactive mode (for example validation fails
for some field) <tt class="docutils literal"><span class="pre">murano</span></tt> should return a non-zero status, to facilitate
scipting and error-detecting.</p>
<p>Command <tt class="docutils literal"><span class="pre">environment-edit</span></tt> should support optional <tt class="docutils literal"><span class="pre">--session</span></tt> parameter,
that allows user to specify a session for editing an environment.
It should also
warn user in case more than one session is open. If the session parameter is
omitted: last open session for given environment is used.
If there are no open sessions — a new session would be opened.</p>
<dl class="docutils">
<dt>note::</dt>
<dd>This means that to deploy a simple application one has to know jsonpatch
syntax. We might think about optional <cite>syntax sugar</cite> commands, that would
allow adding a single app to the environment. These would use predefined
jsonpatch patch documents and would accept only value to be added to
/Objects/services/- path.</dd>
</dl>
<p>We should implement session controlling commands during
implementation of this spec, for example:</p>
<ol class="arabic simple">
<li><tt class="docutils literal"><span class="pre">session-list</span></tt> Show list of open sessions for a given environment.</li>
<li><tt class="docutils literal"><span class="pre">session-show</span></tt> Show details of currently configured session..</li>
<li><tt class="docutils literal"><span class="pre">session-delete</span></tt> Discard an open session for a given environment.</li>
</ol>
<p>In case an error occurs during environment deployment this would allow to
rollback the changes to the previous version of environment.
This should also allow to handle cases, when a single environment is edited
simultaneously by different users.</p>
<p><tt class="docutils literal"><span class="pre">environment-action</span></tt> command should be implemented to allow performing
actions against an environment. One example of actions is a deploy action, so
<tt class="docutils literal"><span class="pre">murano</span> <span class="pre">environment-action</span> <span class="pre">deploy</span></tt> should deploy the environment.</p>
<div class="section" id="alternatives">
<h3>Alternatives</h3>
<p>Alternatively we can implement an interactive mode, that would mimic current
dashboard behaviour. This would not allow scripting, but would allow us to
build a more user-friendly CLI interface. The dowside is that current UI
definitions are scheduled to be changed and would most likely be replaced in
the forseable future. This means, that most of the work would go to waste.</p>
</div>
<div class="section" id="data-model-impact">
<h3>Data model impact</h3>
<p>None</p>
</div>
<div class="section" id="rest-api-impact">
<h3>REST API impact</h3>
<p>None, CLI should reuse API calls, already used by dashboard</p>
</div>
<div class="section" id="versioning-impact">
<h3>Versioning impact</h3>
<p>Since we’re adding functionality — None</p>
</div>
<div class="section" id="other-end-user-impact">
<h3>Other end user impact</h3>
<p>None</p>
</div>
<div class="section" id="deployer-impact">
<h3>Deployer impact</h3>
<p>It is possible that implementation of this spec would require setting and
reading intermediate environment variables to work correctly with sessions,
during app addition, env deployment.</p>
<p>Overall deployment of murano would not be affected.</p>
</div>
<div class="section" id="developer-impact">
<h3>Developer impact</h3>
<p>None</p>
</div>
<div class="section" id="murano-dashboard-horizon-impact">
<h3>Murano-dashboard / Horizon impact</h3>
<p>None</p>
</div>
</div>
<div class="section" id="implementation">
<h2>Implementation</h2>
<div class="section" id="assignee-s">
<h3>Assignee(s)</h3>
<dl class="docutils">
<dt>Primary assignee:</dt>
<dd><kzaitsev></dd>
</dl>
</div>
<div class="section" id="work-items">
<h3>Work Items</h3>
<ol class="arabic simple">
<li><tt class="docutils literal"><span class="pre">environment-edit</span></tt> command
(should create session, check permissions, add
patch resulting model into ).</li>
<li>Input validation for <tt class="docutils literal"><span class="pre">envieonment-edit</span></tt>
(request packages from API, check ID
uniqueness, check input field adequacy).</li>
<li>(optional) <tt class="docutils literal"><span class="pre">--format-id</span></tt> option support</li>
<li>(optional) syntax sugar command, that would allow easy addition of a package
to an environment.</li>
<li>Session controlling commands.</li>
<li><tt class="docutils literal"><span class="pre">environment-action</span></tt> command.</li>
<li>Shell unit tests.</li>
<li>Integration tests.</li>
</ol>
</div>
</div>
<div class="section" id="dependencies">
<h2>Dependencies</h2>
<p>None</p>
</div>
<div class="section" id="testing">
<h2>Testing</h2>
<p>We shall need Unit tests for new commands introduced.</p>
<p>Also, since this change introduces a way to deploy an env from CLI. This means
that integration tests for murano client should be implemented. A typical test
should upload and app, configure a simple environment with 1-2 apps and set
some custom parameters, like access port and optionally deploy the env in
question. This tests should probably take place in murano-ci.</p>
</div>
<div class="section" id="documentation-impact">
<h2>Documentation Impact</h2>
<p>New python-muranoclient commands would have to get a proper documentation. It’s
also possible, that we would want to document the whole process of deploying an
app or scripting of such a deployment as a separate article in murano
documentattion.</p>
</div>
<div class="section" id="references">
<h2>References</h2>
<ul class="simple">
<li><a class="reference external" href="http://jsonpatch.com">http://jsonpatch.com</a></li>
<li><a class="reference external" href="https://tools.ietf.org/html/rfc6902">https://tools.ietf.org/html/rfc6902</a></li>
<li><a class="reference external" href="https://tools.ietf.org/html/rfc7159">https://tools.ietf.org/html/rfc7159</a></li>
<li><a class="reference external" href="https://pypi.python.org/pypi/jsonpatch">https://pypi.python.org/pypi/jsonpatch</a></li>
</ul>
</div>
Thu, 25 Jun 2015 00:00:00 Implement Cloud Foundry Service Broker APIhttp://murano-specs.readthedocs.org/specs/liberty/cloud-foundry-service-broker-api.html
<p><a class="reference external" href="https://blueprints.launchpad.net/murano/+spec/cloudfoundry-api-support">https://blueprints.launchpad.net/murano/+spec/cloudfoundry-api-support</a></p>
<p>Cloud Foundry is PaaS which supports full lifecycle from initial development,
through all testing stages, to deployment. As far as Cloud Foundry comes in
three flavours such as Cloud Foundry OSS, Pivotal Cloud Foundry and Pivotal
Web Services.</p>
<p>If we implement Cloud Foundry Service Broker API in murano, murano apps will
get an ability to be deployed through CloudFoundry itself. This will improve
PaaS user experience as it will have an ability to integrate his app with
existing apps in murano and deploy really complex configurations on top of
OpenStack.</p>
<div class="section" id="problem-description">
<h2>Problem description</h2>
<p>Typical scenario of Cloud Foundry and murano collaboration will look like:</p>
<ol class="arabic simple" start="0">
<li>While configuring murano enable Service Broker. It will be deployed at the
same nodes but on the different port.</li>
<li>Deploy Cloud Foundry on the node using murano or manually.</li>
<li>Configure Cloud Foundry to use murano Service Broker.</li>
<li>Deploy murano apps through Cloud Foundry API.</li>
</ol>
<p>NOTE: as far as we want Cloud Foundry to use murano app catalog the end-user
will use Cloud Foundry for provisioning.</p>
</div>
<div class="section" id="proposed-change">
<h2>Proposed change</h2>
<p>We need to write Cloud Foundry Service Broker implementation for murano. One of
the parts of this implementation should be some mapping function between Cloud
Foundry and OpenStack resources. Now it’s planned to map Cloud Foundry
Organizations to Openstack tenants and Cloud Foundry spaces to murano
environments. So, all tenant users will be granted with the privileges based on
their existing roles in OpenStack tenant. And now it looks like we need to have
to run a murano environment for every single service provisioned in Cloud Foundry.
The parameters which is needed to murano for successful application deployment
will store in service object section parameters. The Service Broker itself will
parse them as soon as Cloud Foundry can’t do it. It will be parsed during Provision
request. The request body will look like that:
.. code-block:: javascript</p>
<blockquote>
<div><dl class="docutils">
<dt>{</dt>
<dd><p class="first">“service_id”: “service-guid-here”,
“plan_id”: “plan-guid-here”,
“organization_guid”: “org-guid-here”,
“space_guid”: “space-guid-here”,
“parameters”:{</p>
<blockquote class="last">
<div><blockquote>
<div>“parameter1”: 1,
“parameter2”: “value”</div></blockquote>
<p>}</p>
</div></blockquote>
</dd>
</dl>
<p>}</p>
</div></blockquote>
<p>It’s planned to setup a Service Broker as a separate service which will be deployed
on the same nodes as murano. Additional options should be added to the configs.
Also we want to use Cloud Foundry experimental asynchronous operations[3].</p>
<div class="section" id="alternatives">
<h3>Alternatives</h3>
<p>None</p>
</div>
<div class="section" id="data-model-impact">
<h3>Data model impact</h3>
<p>None</p>
</div>
<div class="section" id="rest-api-impact">
<h3>REST API impact</h3>
<p>No existing API of murano service is going to be changed. New service will be
created implementing the standard Cloud Foundry Service Broker API. Its API
methods are as follows:</p>
<p><strong>GET /v2/catalog</strong></p>
<p><em>Request</em></p>
<table border="1" class="docutils">
<colgroup>
<col width="13%"/>
<col width="44%"/>
<col width="44%"/>
</colgroup>
<thead valign="bottom">
<tr class="row-odd"><th class="head">Method</th>
<th class="head">URI</th>
<th class="head">Description</th>
</tr>
</thead>
<tbody valign="top">
<tr class="row-even"><td>GET</td>
<td>/v2/catalog</td>
<td>List all available apps</td>
</tr>
</tbody>
</table>
<p><em>Parameters:</em></p>
<ul class="simple">
<li>None</li>
</ul>
<p><em>Response</em></p>
<table border="1" class="docutils">
<colgroup>
<col width="21%"/>
<col width="79%"/>
</colgroup>
<thead valign="bottom">
<tr class="row-odd"><th class="head">Code</th>
<th class="head">Description</th>
</tr>
</thead>
<tbody valign="top">
<tr class="row-even"><td>200</td>
<td>OK. The expected resource body as below</td>
</tr>
</tbody>
</table>
<div class="highlight-python"><div class="highlight"><pre><span class="p">{</span><span class="s">"services"</span><span class="p">:</span> <span class="p">[{</span>
<span class="s">"id"</span><span class="p">:</span> <span class="s">"service-guid-here"</span><span class="p">,</span>
<span class="s">"name"</span><span class="p">:</span> <span class="s">"mysql"</span><span class="p">,</span>
<span class="s">"description"</span><span class="p">:</span> <span class="s">"A MySQL-compatible relational database"</span><span class="p">,</span>
<span class="s">"bindable"</span><span class="p">:</span> <span class="n">true</span><span class="p">,</span>
<span class="s">"plans"</span><span class="p">:</span> <span class="p">[{</span>
<span class="s">"id"</span><span class="p">:</span> <span class="s">"plan1-guid-here"</span><span class="p">,</span>
<span class="s">"name"</span><span class="p">:</span> <span class="s">"small"</span><span class="p">,</span>
<span class="s">"description"</span><span class="p">:</span> <span class="s">"A small shared database with 100mb storage quota and 10 connections"</span>
<span class="p">},{</span>
<span class="s">"id"</span><span class="p">:</span> <span class="s">"plan2-guid-here"</span><span class="p">,</span>
<span class="s">"name"</span><span class="p">:</span> <span class="s">"large"</span><span class="p">,</span>
<span class="s">"description"</span><span class="p">:</span> <span class="s">"A large dedicated database with 10GB storage quota, 512MB of RAM, and 100 connections"</span><span class="p">,</span>
<span class="s">"free"</span><span class="p">:</span> <span class="n">false</span>
<span class="p">}],</span>
<span class="s">"dashboard_client"</span><span class="p">:</span> <span class="p">{</span>
<span class="s">"id"</span><span class="p">:</span> <span class="s">"client-id-1"</span><span class="p">,</span>
<span class="s">"secret"</span><span class="p">:</span> <span class="s">"secret-1"</span><span class="p">,</span>
<span class="s">"redirect_uri"</span><span class="p">:</span> <span class="s">"https://dashboard.service.com"</span>
<span class="p">}</span>
<span class="p">}]</span>
<span class="p">}</span>
</pre></div>
</div>
<p><strong>PUT /v2/service_instances/:instance_id?accepts_incomplete=true</strong></p>
<p><em>Request</em></p>
<table border="1" class="docutils">
<colgroup>
<col width="9%"/>
<col width="53%"/>
<col width="38%"/>
</colgroup>
<thead valign="bottom">
<tr class="row-odd"><th class="head">Method</th>
<th class="head">URI</th>
<th class="head">Description</th>
</tr>
</thead>
<tbody valign="top">
<tr class="row-even"><td>PUT</td>
<td>/v2/service_instances/:instance_id?accepts_incomplete=true</td>
<td>Create new service resources for developer</td>
</tr>
</tbody>
</table>
<div class="highlight-python"><div class="highlight"><pre><span class="p">{</span>
<span class="s">"service_id"</span><span class="p">:</span> <span class="s">"service-guid-here"</span><span class="p">,</span>
<span class="s">"plan_id"</span><span class="p">:</span> <span class="s">"plan-guid-here"</span><span class="p">,</span>
<span class="s">"organization_guid"</span><span class="p">:</span> <span class="s">"org-guid-here"</span><span class="p">,</span>
<span class="s">"space_guid"</span><span class="p">:</span> <span class="s">"space-guid-here"</span>
<span class="p">}</span>
</pre></div>
</div>
<p><em>Response</em></p>
<table border="1" class="docutils">
<colgroup>
<col width="21%"/>
<col width="79%"/>
</colgroup>
<thead valign="bottom">
<tr class="row-odd"><th class="head">Code</th>
<th class="head">Description</th>
</tr>
</thead>
<tbody valign="top">
<tr class="row-even"><td>200</td>
<td>OK. May be returned if the service instance already exists
and the requested parameters are identical to the existing
service instance.</td>
</tr>
<tr class="row-odd"><td>202</td>
<td>Accepted. Service instance creation is in progress.</td>
</tr>
<tr class="row-even"><td>409</td>
<td>Conflict. Should be returned if the requested service
instance already exists. The expected response body is “{}”</td>
</tr>
<tr class="row-odd"><td>422</td>
<td>Should be returned if the request did not include
?accepts_incomplete=true</td>
</tr>
</tbody>
</table>
<div class="highlight-python"><div class="highlight"><pre><span class="p">{</span>
<span class="s">"dashboard_url"</span><span class="p">:</span> <span class="s">"http://example-dashboard.com/9189kdfsk0vfnku"</span>
<span class="p">}</span>
</pre></div>
</div>
<p><strong>PATCH /v2/service_instances/:instance_id?accepts_incomplete=true</strong></p>
<p><em>Request</em></p>
<table border="1" class="docutils">
<colgroup>
<col width="10%"/>
<col width="57%"/>
<col width="33%"/>
</colgroup>
<thead valign="bottom">
<tr class="row-odd"><th class="head">Method</th>
<th class="head">URI</th>
<th class="head">Description</th>
</tr>
</thead>
<tbody valign="top">
<tr class="row-even"><td>PATCH</td>
<td>/v2/service_instances/:instance_id?accepts_incomplete=true</td>
<td>Update existing service instance</td>
</tr>
</tbody>
</table>
<div class="highlight-python"><div class="highlight"><pre><span class="p">{</span>
<span class="s">"plan_id"</span><span class="p">:</span> <span class="s">"plan_guid_here"</span>
<span class="p">}</span>
</pre></div>
</div>
<p><em>Response</em></p>
<table border="1" class="docutils">
<colgroup>
<col width="21%"/>
<col width="79%"/>
</colgroup>
<thead valign="bottom">
<tr class="row-odd"><th class="head">Code</th>
<th class="head">Description</th>
</tr>
</thead>
<tbody valign="top">
<tr class="row-even"><td>200</td>
<td>Return if only the new plan matches the old one completely</td>
</tr>
<tr class="row-odd"><td>202</td>
<td>Accepted. Service instance update is in progress.</td>
</tr>
<tr class="row-even"><td>422</td>
<td>Should be returned if the request did not include
?accepts_incomplete=true</td>
</tr>
</tbody>
</table>
<p><strong>DELETE /v2/service_instances/:instance_id?accepts_incomplete=true</strong></p>
<table border="1" class="docutils">
<colgroup>
<col width="10%"/>
<col width="57%"/>
<col width="34%"/>
</colgroup>
<thead valign="bottom">
<tr class="row-odd"><th class="head">Method</th>
<th class="head">URI</th>
<th class="head">Description</th>
</tr>
</thead>
<tbody valign="top">
<tr class="row-even"><td>DELETE</td>
<td>/v2/service_instances/:instance_id?accepts_incomplete=true</td>
<td>Delete all resources create during
the provision.</td>
</tr>
</tbody>
</table>
<p><em>Response</em></p>
<table border="1" class="docutils">
<colgroup>
<col width="17%"/>
<col width="8%"/>
<col width="75%"/>
</colgroup>
<thead valign="bottom">
<tr class="row-odd"><th class="head">Code</th>
<th class="head" colspan="2">Description</th>
</tr>
</thead>
<tbody valign="top">
<tr class="row-even"><td>202</td>
<td colspan="2">Accepted. Service instance deletion in progress.</td>
</tr>
<tr class="row-odd"><td colspan="3">410 | Returned if service does not exist</td>
</tr>
<tr class="row-even"><td colspan="3"><dl class="first last docutils">
<dt>422 | Should be returned if the request did not include</dt>
<dd><div class="first last line-block">
<div class="line">?accepts_incomplete=true</div>
</div>
</dd>
</dl>
</td>
</tr>
</tbody>
</table>
<p><strong>PUT /v2/service_instances/:instance_id/service_bindings/:binding_id</strong></p>
<p><em>Request</em></p>
<table border="1" class="docutils">
<colgroup>
<col width="9%"/>
<col width="59%"/>
<col width="31%"/>
</colgroup>
<thead valign="bottom">
<tr class="row-odd"><th class="head">Method</th>
<th class="head">URI</th>
<th class="head">Description</th>
</tr>
</thead>
<tbody valign="top">
<tr class="row-even"><td>PUT</td>
<td>/v2/service_instances/:instance_id/service_bindings/:binding_id</td>
<td>Bind service</td>
</tr>
</tbody>
</table>
<div class="highlight-python"><div class="highlight"><pre><span class="p">{</span><span class="s">"plan_id"</span><span class="p">:</span> <span class="s">"plan_guid_here"</span><span class="p">,</span>
<span class="s">"service_id"</span><span class="p">:</span> <span class="s">"service_guid_here"</span><span class="p">,</span>
<span class="s">"app_guid"</span><span class="p">:</span> <span class="s">"app_guid_here"</span>
<span class="p">}</span>
</pre></div>
</div>
<p><em>Response</em></p>
<table border="1" class="docutils">
<colgroup>
<col width="20%"/>
<col width="80%"/>
</colgroup>
<thead valign="bottom">
<tr class="row-odd"><th class="head">Code</th>
<th class="head">Description</th>
</tr>
</thead>
<tbody valign="top">
<tr class="row-even"><td>201</td>
<td>Binding has been created. The expected response body is below.</td>
</tr>
<tr class="row-odd"><td>200</td>
<td>May be returned if the binding already exists and the requested
parameters are identical to the existing binding. The expected
response body is below.</td>
</tr>
<tr class="row-even"><td>409</td>
<td>Should be returned if the requested binding already exists. The
expected response. body is <cite>{}</cite>, though the description field can
be used to return a user-factorin error message.</td>
</tr>
</tbody>
</table>
<div class="highlight-python"><div class="highlight"><pre><span class="p">{</span>
<span class="s">"credentials"</span><span class="p">:</span> <span class="p">{</span>
<span class="s">"uri"</span><span class="p">:</span> <span class="s">"mysql://mysqluser:pass@mysqlhost:3306/dbname"</span><span class="p">,</span>
<span class="s">"username"</span><span class="p">:</span> <span class="s">"mysqluser"</span><span class="p">,</span>
<span class="s">"password"</span><span class="p">:</span> <span class="s">"pass"</span><span class="p">,</span>
<span class="s">"host"</span><span class="p">:</span> <span class="s">"mysqlhost"</span><span class="p">,</span>
<span class="s">"port"</span><span class="p">:</span> <span class="mi">3306</span><span class="p">,</span>
<span class="s">"database"</span><span class="p">:</span> <span class="s">"dbname"</span>
<span class="p">}</span>
<span class="p">}</span>
</pre></div>
</div>
<p><strong>DELETE /v2/service_instances/:instance_id/service_bindings/:binding_id</strong></p>
<p><em>Request</em></p>
<table border="1" class="docutils">
<colgroup>
<col width="9%"/>
<col width="59%"/>
<col width="31%"/>
</colgroup>
<thead valign="bottom">
<tr class="row-odd"><th class="head">Method</th>
<th class="head">URI</th>
<th class="head">Description</th>
</tr>
</thead>
<tbody valign="top">
<tr class="row-even"><td>DELETE</td>
<td>/v2/service_instances/:instance_id/service_bindings/:binding_id</td>
<td>Unbind service</td>
</tr>
</tbody>
</table>
<p><em>Response</em></p>
<table border="1" class="docutils">
<colgroup>
<col width="22%"/>
<col width="78%"/>
</colgroup>
<thead valign="bottom">
<tr class="row-odd"><th class="head">Code</th>
<th class="head">Description</th>
</tr>
</thead>
<tbody valign="top">
<tr class="row-even"><td>200</td>
<td>Binding was deleted</td>
</tr>
<tr class="row-odd"><td>410</td>
<td>Returned if binding does not exist</td>
</tr>
</tbody>
</table>
<p><strong>GET /v2/service_instances/:instance_id/last_operation</strong></p>
<p><em>Request</em></p>
<table border="1" class="docutils">
<colgroup>
<col width="11%"/>
<col width="55%"/>
<col width="34%"/>
</colgroup>
<thead valign="bottom">
<tr class="row-odd"><th class="head">Method</th>
<th class="head">URI</th>
<th class="head">Description</th>
</tr>
</thead>
<tbody valign="top">
<tr class="row-even"><td>GET</td>
<td>/v2/service_instances/:instance_id/last_operation</td>
<td>Polling status of the last 202
operation</td>
</tr>
</tbody>
</table>
<p><em>Response</em></p>
<table border="1" class="docutils">
<colgroup>
<col width="15%"/>
<col width="85%"/>
</colgroup>
<thead valign="bottom">
<tr class="row-odd"><th class="head">Code</th>
<th class="head">Description</th>
</tr>
</thead>
<tbody valign="top">
<tr class="row-even"><td>200</td>
<td>OK</td>
</tr>
<tr class="row-odd"><td>410</td>
<td>GONE. Appropriate only for asynchronous delete requests
Cloud Foundry will consider this response a success and
remove the resource from its database.</td>
</tr>
</tbody>
</table>
<dl class="docutils">
<dt>::</dt>
<dd><dl class="first docutils">
<dt>{</dt>
<dd>“state”: “in progress”,
“description”: “Creating service (10% complete).”</dd>
</dl>
<p class="last">}</p>
</dd>
</dl>
</div>
<div class="section" id="versioning-impact">
<h3>Versioning impact</h3>
<p>None</p>
</div>
<div class="section" id="other-end-user-impact">
<h3>Other end user impact</h3>
<p>None</p>
</div>
<div class="section" id="deployer-impact">
<h3>Deployer impact</h3>
<p>Service Broker should be deployed and enabled in the murano config.</p>
</div>
<div class="section" id="developer-impact">
<h3>Developer impact</h3>
<p>None</p>
</div>
<div class="section" id="murano-dashboard-horizon-impact">
<h3>Murano-dashboard / Horizon impact</h3>
<p>None</p>
</div>
</div>
<div class="section" id="implementation">
<h2>Implementation</h2>
<div class="section" id="assignee-s">
<h3>Assignee(s)</h3>
<dl class="docutils">
<dt>Primary assignee:</dt>
<dd>starodubcevna</dd>
</dl>
</div>
<div class="section" id="work-items">
<h3>Work Items</h3>
<p>Changes can be split to this parts:</p>
<ul class="simple">
<li>Implement the stub of Service Broker itself. Add needed config opts and starting point.</li>
<li>Implement basic Cloud Foundry API calls such as list and provision. Also on this step we
should add murano specific API calls.</li>
<li>Series of extensions for Cloud Foundry API support:
* Add update and deprovision API calls
* Add bind/unbind API calls</li>
</ul>
</div>
</div>
<div class="section" id="dependencies">
<h2>Dependencies</h2>
<p>None</p>
</div>
<div class="section" id="testing">
<h2>Testing</h2>
<p>Unit tests should cover new API calls.</p>
</div>
<div class="section" id="documentation-impact">
<h2>Documentation Impact</h2>
<p>Document “Murano and Cloud Foundry HowTo”. It should be step by step guide for
Cloud Foundry and murano cooperation.</p>
</div>
<div class="section" id="references">
<h2>References</h2>
<p>[1] <a class="reference external" href="https://youtu.be/ezq9P1WN2LY">https://youtu.be/ezq9P1WN2LY</a>
[2] <a class="reference external" href="http://docs.cloudfoundry.org/services/api.html">http://docs.cloudfoundry.org/services/api.html</a>
[3] <a class="reference external" href="https://docs.cloudfoundry.org/services/asynchronous-operations.html">https://docs.cloudfoundry.org/services/asynchronous-operations.html</a></p>
</div>
Tue, 16 Jun 2015 00:00:00 Environment abandoning supporthttp://murano-specs.readthedocs.org/specs/liberty/environment-abandon.html
<p><a class="reference external" href="https://blueprints.launchpad.net/murano/+spec/environment-abandon">https://blueprints.launchpad.net/murano/+spec/environment-abandon</a></p>
<p>The purpose is to add an ability to abandon the environment, which hangs during
deployment or deleting in order to hide it from the list of other environments.</p>
<div class="section" id="problem-description">
<h2>Problem description</h2>
<p>There are cases when the process of deleting or deploying environment may hang.
Then the user has to release all used resources and manually clean the database
in order to get rid of the list of failed environments.</p>
<p>Manual cleaning of the database is unsafe and inconvenient operation. That’s
why <cite>abandon</cite> feature has to be provided. It should improve usability and
allows to user to avoid direct database editing. But it is necessary to notify
the user that all resources used by abandoned environment must be also released
manually as previously.</p>
</div>
<div class="section" id="proposed-change">
<h2>Proposed change</h2>
<p>The implementation of this feature consists of three stages:</p>
<ol class="arabic simple">
<li>Modify environment-delete API endopoint to have <em>abandon</em> feature</li>
</ol>
<p>The method <em>delete</em> must be changed. Depending on the parameter “abandon”,
obtained from request data, the method should work differently. This parameter
has a boolean type. If it equals <em>True</em> enviroment will be directly removed
from the database without object model cleanup.</p>
<ol class="arabic simple" start="2">
<li>Provide corresponding changes in the python-muranoclient</li>
</ol>
<p>Method <em>delete</em> of environment manager should be modified. New boolean
parameter <em>abandon</em> with default value <em>False</em> should be added. The value of
parameter affects the building of url, which is sent to murano-api.</p>
<ol class="arabic simple" start="3">
<li>Add new button <em>Abandon</em> to murano-dashboard</li>
</ol>
<p>This button should be available with any environment state.</p>
<p>Proposed change doesn’t solve problem of deployment process hanging.
Murano-engine may continue to deploy abandoned environment. It is
necessary to find a way how to stop murano-engine in this case.</p>
<div class="section" id="alternatives">
<h3>Alternatives</h3>
<p>None</p>
</div>
<div class="section" id="data-model-impact">
<h3>Data model impact</h3>
<p>None</p>
</div>
<div class="section" id="rest-api-impact">
<h3>REST API impact</h3>
<p><strong>DELETE /environments/<environment_id>?abandon</strong></p>
<p><em>Request</em></p>
<table border="1" class="docutils">
<colgroup>
<col width="13%"/>
<col width="44%"/>
<col width="44%"/>
</colgroup>
<thead valign="bottom">
<tr class="row-odd"><th class="head">Method</th>
<th class="head">URI</th>
<th class="head">Description</th>
</tr>
</thead>
<tbody valign="top">
<tr class="row-even"><td>DELETE</td>
<td>/environments/{id}?abandon</td>
<td>Remove specified environment.</td>
</tr>
</tbody>
</table>
<p><em>Parameters:</em></p>
<ul class="simple">
<li><cite>abandon</cite> - boolean, indicates how to delete environment. <em>False</em> is used if
all resources used by environment must be destroyed; <em>True</em> is used when just
database must be cleaned</li>
</ul>
<p><em>Response</em></p>
<table border="1" class="docutils">
<colgroup>
<col width="21%"/>
<col width="79%"/>
</colgroup>
<thead valign="bottom">
<tr class="row-odd"><th class="head">Code</th>
<th class="head">Description</th>
</tr>
</thead>
<tbody valign="top">
<tr class="row-even"><td>200</td>
<td>OK. Environment deleted successfully</td>
</tr>
<tr class="row-odd"><td>403</td>
<td>User is not allowed to delete this resource</td>
</tr>
<tr class="row-even"><td>404</td>
<td>Not found. Specified environment doesn`t exist</td>
</tr>
</tbody>
</table>
</div>
<div class="section" id="versioning-impact">
<h3>Versioning impact</h3>
<p>Murano dashboard will support only the version of the client, that includes
corresponding changes.</p>
</div>
<div class="section" id="other-end-user-impact">
<h3>Other end user impact</h3>
<p>None</p>
</div>
<div class="section" id="deployer-impact">
<h3>Deployer impact</h3>
<p>None</p>
</div>
<div class="section" id="developer-impact">
<h3>Developer impact</h3>
<p>None</p>
</div>
<div class="section" id="murano-dashboard-horizon-impact">
<h3>Murano-dashboard / Horizon impact</h3>
<p>New action <cite>Abandon</cite> will be added to murano-dashboard. It will be always
available in the row of other action.</p>
<p>Dialog with warning should appear when user executes action</p>
</div>
</div>
<div class="section" id="implementation">
<h2>Implementation</h2>
<div class="section" id="assignee-s">
<h3>Assignee(s)</h3>
<p>Dmytro Dovbii</p>
<dl class="docutils">
<dt>Primary assignee:</dt>
<dd><<a class="reference external" href="mailto:ddovbii%40mirantis.com">ddovbii<span>@</span>mirantis<span>.</span>com</a>></dd>
</dl>
</div>
<div class="section" id="work-items">
<h3>Work Items</h3>
<ul class="simple">
<li>Modify method ‘delete’ of environment API to support two delete modes</li>
<li>Implement adding ‘abandon’ parameter to url in ‘delete’ method of environment
manager in muranoclient</li>
<li>Add flag ‘–abandon’ to CLI command ‘environment-delete’</li>
<li>Add new class ‘AbandonEnvironment’ which provide new button ‘Abandon’ in
murano-dashboard</li>
</ul>
<p>Implementation is acutally completed.</p>
</div>
</div>
<div class="section" id="dependencies">
<h2>Dependencies</h2>
<p>None</p>
</div>
<div class="section" id="testing">
<h2>Testing</h2>
<p>Functional tests for murano-dashboard must be updated.
Unit tests should cover API call and CLI client
Tempest tests are out of the scope of this spec.</p>
</div>
<div class="section" id="documentation-impact">
<h2>Documentation Impact</h2>
<p>API specification should be updated</p>
</div>
<div class="section" id="references">
<h2>References</h2>
<p>None</p>
</div>
Thu, 11 Jun 2015 00:00:00 Simulated Execution Mode For Murano Enginehttp://murano-specs.readthedocs.org/specs/liberty/simulated-execution-mode-murano-engine.html
<p><a class="reference external" href="https://blueprints.launchpad.net/murano/+spec/simulated-execution-mode-murano-engine">https://blueprints.launchpad.net/murano/+spec/simulated-execution-mode-murano-engine</a></p>
<div class="section" id="problem-description">
<h2>Problem description</h2>
<p>As an Application Developer I’d like to execute my workflows without actual
deployment and interaction with murano-dashboard in order to verify my workflow
before actual deployment by those increasing my application development
speed.</p>
</div>
<div class="section" id="proposed-change">
<h2>Proposed change</h2>
<p>Verifying application packages should be simple and fast.
User doesn’t have to re-upload package and add app to the environment on every
change.</p>
<ul class="simple">
<li>Allow application author to validate his application using unit-tests</li>
<li>Those tests will be put to the application package to allow anyone to test
this app at any time</li>
<li>Tests will look like regular unit tests. Testing framework, witch will
run unit-tests will support commands, that will allow to load test package
from directory, to call class methods and configure deployments parameters.
That will make deployment test run easier. Also, test writer may run
deployment several times, examine and compare results with different
parameters</li>
<li>Tests should be able to produce complete object model with some parameters
of deployment:<ul>
<li>environment attributes (such as tokens) (or overwriting values, defined in
config);</li>
<li>mock the methods of system classes which include various kinds of external
communications. Dependent applications, system resources and various API
clients and also be mocked. It should be allowed to specify a returned
value. There would be separate specification for mocking, where the
details will be described.</li>
</ul>
</li>
</ul>
<p>Test-case prototype may look like that:</p>
<div class="highlight-python"><div class="highlight"><pre>Namespaces:
=: io.murano.apps.foo.tests
sys: io.murano.system
pckg: io.murano.apps.foo
Extends: io.murano.tests.TestFixture
Name: FooTest
Methods:
initialize:
Body:
# - $.appJson: new(sys:Resources).json('foo-test-object-model.json')
- $.appJson:
- ?:
id: 123
type: io.murano.apps.foo.FooApp
name: my-foo-obj
instance:
?:
type: io.murano.resources.Instance
id: 42
...
setUp:
Body:
- $.env: $.createEnvironment($.appJson) # creates an instance of std:Environment
- $.myApp: $.env.applications.where($.name='my-foo-obj').first()
- mock($.myApp.instance, "deploy", "mockInstanceDeploy", $this)
- mock(res:Instance, deploy, "mockInstanceDeploy", $this)
testFooApp:
Body:
- $.env.deploy()
- $.assertEqual(true, $.myApp.getAttr('deployed'))
tearDown:
Body:
mockInstanceDeploy:
Arguments:
- mockContext
Body:
- Return:
# heat template
</pre></div>
</div>
<div class="section" id="alternatives">
<h3>Alternatives</h3>
<p>Provide one CLI command, that will mock creation of VMs and other things and
returns the deployment result.</p>
<p>Cons:
Impossible to verify deployments, where execution plan returns a value, which
is used in future app workflow. Compare results of several deployments would be
inconvenient Real VM’s can’t be</p>
</div>
<div class="section" id="data-model-impact">
<h3>Data model impact</h3>
<p>None</p>
</div>
<div class="section" id="rest-api-impact">
<h3>REST API impact</h3>
<p>None</p>
</div>
<div class="section" id="versioning-impact">
<h3>Versioning impact</h3>
<p>Tests will be placed to a package, so manifest version need to be updated.
This functionality should be described in a separate spec.
For now, there will be no impact on project itself.</p>
</div>
<div class="section" id="other-end-user-impact">
<h3>Other end user impact</h3>
<p>None</p>
</div>
<div class="section" id="deployer-impact">
<h3>Deployer impact</h3>
<p>None</p>
</div>
<div class="section" id="developer-impact">
<h3>Developer impact</h3>
<p>None</p>
</div>
<div class="section" id="murano-dashboard-horizon-impact">
<h3>Murano-dashboard / Horizon impact</h3>
<p>None</p>
</div>
</div>
<div class="section" id="implementation">
<h2>Implementation</h2>
<div class="section" id="assignee-s">
<h3>Assignee(s)</h3>
<dl class="docutils">
<dt>Primary assignee:</dt>
<dd><<a class="reference external" href="mailto:efedorova%40mirantis.com">efedorova<span>@</span>mirantis<span>.</span>com</a>></dd>
</dl>
</div>
<div class="section" id="work-items">
<h3>Work Items</h3>
<p>#. Add ‘simulation’ mode (new entry-point) to Murano Engine, where
packages would be uploaded from the provided path there would be no
interconnection with RabbitMQ</p>
<ol class="arabic simple">
<li>Make changes to the class-loader, located in engine, to not use API.
Separate spec is provided for this change (<a class="reference external" href="https://review.openstack.org/#/c/198745/">https://review.openstack.org/#/c/198745/</a>).</li>
<li>Implement testing framework, written in MuranoPL that will include the
classes, described below. The structure would be taken from python unittest
module. Framework will include test-runner</li>
<li>Implement mock support.</li>
<li>Define what is needed to change in MuranoPL itself</li>
</ol>
<p>Testing framework may contain the following classes and methods.
This are base classes for simple testing framework.</p>
<ul class="simple">
<li><tt class="docutils literal"><span class="pre">TestCase</span></tt> class</li>
</ul>
<table border="1" class="docutils">
<colgroup>
<col width="23%"/>
<col width="77%"/>
</colgroup>
<thead valign="bottom">
<tr class="row-odd"><th class="head">Method</th>
<th class="head">Description</th>
</tr>
</thead>
<tbody valign="top">
<tr class="row-even"><td>setUp()</td>
<td>Method called immediately before calling the test method.</td>
</tr>
<tr class="row-odd"><td>tearDown()</td>
<td>Method called immediately after the test method has been
called and the result recorded.</td>
</tr>
<tr class="row-even"><td>run(result=None)</td>
<td>Run the test, collecting the result into the test result
object passed as result.</td>
</tr>
<tr class="row-odd"><td>assert...</td>
<td>Different asserts (assertEqual, assertNotEqual, assertTrue,
assertFalse).</td>
</tr>
</tbody>
</table>
<ul class="simple">
<li><tt class="docutils literal"><span class="pre">TestResult</span></tt> class: This class is used to compile information about which tests have succeeded and which have failed.</li>
</ul>
<table border="1" class="docutils">
<colgroup>
<col width="19%"/>
<col width="81%"/>
</colgroup>
<thead valign="bottom">
<tr class="row-odd"><th class="head">Attribute</th>
<th class="head">Description</th>
</tr>
</thead>
<tbody valign="top">
<tr class="row-even"><td>errors</td>
<td>A list containing 2-tuples of TestCase instances and strings
holding formatted tracebacks. Each tuple represents a test
which raised an unexpected exception.</td>
</tr>
<tr class="row-odd"><td>failures</td>
<td>A list containing 2-tuples of TestCase instances and strings
holding formatted tracebacks. Each tuple represents a test
where a failure was explicitly signalled using the
TestCase.assert*() methods.</td>
</tr>
<tr class="row-even"><td>testsRun</td>
<td>The total number of tests run so far.</td>
</tr>
</tbody>
</table>
<ul class="simple">
<li><tt class="docutils literal"><span class="pre">TestRunner(stream=sys.stderr,</span> <span class="pre">descriptions=True,</span> <span class="pre">verbosity=1)</span></tt> A basic test runner
implementation which prints results on standard error.
Has <em>run</em> method, witch executes the given test case. Also stores the execution result.</li>
</ul>
<p>For the fist time test may be run only one by one. Later we can add <tt class="docutils literal"><span class="pre">TestSuite</span></tt> class and
<tt class="docutils literal"><span class="pre">TestLoader</span></tt> class:
* <tt class="docutils literal"><span class="pre">TestLoader</span></tt> class is responsible for loading tests according to various criteria
and returning them wrapped in a TestSuite (or TestSuite if will add this class).</p>
<table border="1" class="docutils">
<colgroup>
<col width="42%"/>
<col width="58%"/>
</colgroup>
<thead valign="bottom">
<tr class="row-odd"><th class="head">Methods</th>
<th class="head">Description</th>
</tr>
</thead>
<tbody valign="top">
<tr class="row-even"><td>loadTestsFromTestCase(testCaseClass)</td>
<td>Return a suite of all tests cases contained in the
TestCase-derived testCaseClass.</td>
</tr>
</tbody>
</table>
<ol class="arabic simple">
<li>Implement simple mocking machinery</li>
</ol>
<p>All mockes are separated into NonCallable and Callable mocks</p>
<p><tt class="docutils literal"><span class="pre">Mock</span></tt> class</p>
<p>Public methods</p>
<table border="1" class="docutils">
<colgroup>
<col width="31%"/>
<col width="69%"/>
</colgroup>
<thead valign="bottom">
<tr class="row-odd"><th class="head">Methods</th>
<th class="head">Description</th>
</tr>
</thead>
<tbody valign="top">
<tr class="row-even"><td>start()</td>
<td>Activate a patch, returning any created mock.</td>
</tr>
<tr class="row-odd"><td>stop()</td>
<td>Stop an active patch.</td>
</tr>
<tr class="row-even"><td>patch(target)</td>
<td>The <cite>target</cite> is patched with a <cite>new</cite> object. <cite>target</cite> should be
a string in the form <cite>package.module.ClassName</cite>.</td>
</tr>
<tr class="row-odd"><td>attach_mock(mock, attribute)</td>
<td>Attach a mock as an attribute of this one, replacing its name
and parent</td>
</tr>
<tr class="row-even"><td>configure_mock(kwargs)</td>
<td>Set attributes on the mock through keyword arguments</td>
</tr>
</tbody>
</table>
<p>Private methods:</p>
<p>initialize, __call__, _patch, __enter__, __exit__</p>
</div>
</div>
<div class="section" id="dependencies">
<h2>Dependencies</h2>
<p>None</p>
</div>
<div class="section" id="testing">
<h2>Testing</h2>
<p>None</p>
</div>
<div class="section" id="documentation-impact">
<h2>Documentation Impact</h2>
<p>New testing framework will be documented from scratch.</p>
</div>
<div class="section" id="references">
<h2>References</h2>
<p>Discussions in IRC will be provided</p>
</div>
Thu, 11 Jun 2015 00:00:00 Liberty specificationshttp://murano-specs.readthedocs.org/specs/liberty/README.html
<p>This directory is supposed to hold approved specifications for the ‘Liberty’ release.
You are welcome in contributing to Murano!</p>
<div class="section" id="murano">
<h2>Murano</h2>
<p>Murano Project introduces an application catalog, which allows application
developers and cloud administrators to publish various cloud-ready
applications in a browsable categorized catalog. Cloud users
– including inexperienced ones – can then use the catalog to
compose reliable application environments with the push of a button.</p>
</div>
<div class="section" id="murano-project-resources">
<h2>Murano Project Resources</h2>
<ul class="simple">
<li><a class="reference external" href="http://murano.readthedocs.org">Murano Official Documentation</a></li>
<li>Project status, bugs, and blueprints are tracked on
<a class="reference external" href="https://launchpad.net/murano">Launchpad</a></li>
<li>Additional resources are linked from the project
<a class="reference external" href="https://wiki.openstack.org/wiki/Murano">Wiki</a> page</li>
<li><a class="reference external" href="https://github.com/openstack/python-muranoclient">Python client</a></li>
</ul>
</div>
<div class="section" id="license">
<h2>License</h2>
<p>Apache License Version 2.0 <a class="reference external" href="http://www.apache.org/licenses/LICENSE-2.0">http://www.apache.org/licenses/LICENSE-2.0</a></p>
</div>
Tue, 09 Jun 2015 00:00:00 Policy Based Modification of Environmenthttp://murano-specs.readthedocs.org/specs/liberty/policy-based-env-modification.html<blockquote>
<div><p>This work is licensed under a Creative Commons Attribution 3.0 Unported
License.</p>
<p><a class="reference external" href="http://creativecommons.org/licenses/by/3.0/legalcode">http://creativecommons.org/licenses/by/3.0/legalcode</a></p>
</div></blockquote>
<div class="section" id="policy-based-modification-of-environment">
<p><a class="reference external" href="https://blueprints.launchpad.net/murano/+spec/policy-based-env-modification">https://blueprints.launchpad.net/murano/+spec/policy-based-env-modification</a></p>
<p>Goal is to be able to define modification of an environment by Congress policies prior
deployment. This allows to add components (for example monitoring), change/set properties
(for example to enforce given zone, flavors, ...) and relationships into environment,
so modified environment is after that deployed.</p>
<div class="section" id="problem-description">
<h2>Problem description</h2>
<p>Currently it is possible to reject deployment of an environment if it does not follows
set of so called pre-deployment policies set by admin. Administrator wants to also modify
environment prior it is deployed:</p>
<ul class="simple">
<li>add/set/remove component properties</li>
<li>add/remove relationships</li>
<li>add/remove objects</li>
</ul>
<p><strong>Example Use Case: Policy Based Monitoring</strong></p>
<p>Admin wants to monitor an environment, so he wants to</p>
<ul class="simple">
<li>install monitoring agent on each Instance</li>
</ul>
<blockquote>
<div><ul class="simple">
<li>it is done by adding component with the agent and creating relationship between
agent and Instance. It is done at pre-deploy time</li>
</ul>
</div></blockquote>
<ul class="simple">
<li>register monitoring agent on Monitoring server</li>
</ul>
<blockquote>
<div><ul class="simple">
<li>it is done by calling monitoring server API during deployment of monitoring agent.</li>
</ul>
</div></blockquote>
</div>
<div class="section" id="proposed-change">
<h2>Proposed change</h2>
<p><strong>Changes</strong></p>
<ul>
<li><p class="first">Introduce new Congress policy rule <em>predeploy_modify(eid,oid,modify-action-id,priority,
[key-val]*)</em></p>
<p><em>predeploy_modify</em> policy rule is queried on all actions.
Simulation Congress API is used like in case of <em>predeploy_errors</em> policy rule.</p>
<p>If it returns non empty list of <em>modifications</em> for given environment, then</p>
</li>
</ul>
<blockquote>
<div><ul class="simple">
<li><em>deploy</em> action is temporarily paused, until all modifications are processed</li>
</ul>
<blockquote>
<div><ul class="simple">
<li>if any of modification fails, then environment <em>deploy</em> fails</li>
</ul>
</div></blockquote>
</div></blockquote>
<ul>
<li><p class="first">Pluggable modification actions
Modification actions can be plug using setup <em>entry_points</em>.</p>
<p>Out of box, there will be following modification actions</p>
</li>
</ul>
<blockquote>
<div><ul class="simple">
<li>add_property( name=name, value=value)</li>
<li>remove_property( name=name)</li>
<li>set_property( name=name, value=value)</li>
<li>add_relationship( name=name, source=source-uuid, target=target-uuid)</li>
<li>remove_relationship( name=name, object=object-uuid)</li>
<li>add_object( type=type, owner=owner-uuid, owner-rel-name=name, [name=val]*)</li>
<li>remove_object( object=object-uuid)</li>
</ul>
</div></blockquote>
<div class="section" id="alternatives">
<h3>Alternatives</h3>
<p>Alternative can be usage of <em>executes[]</em> of Congress policy, which executes modify
actions. In this approach</p>
<ul class="simple">
<li>modify action has to be implemented as Congress datasource action</li>
<li>triggering of executes[] has to be solved</li>
<li>it is not possible to order modify action ordering</li>
<li>Murano session-id of REST API must be passed to Congress</li>
<li>actions can be executed only as asynchronous, so it is not possible to postpone
<em>deploy</em> environment action until all modify actions are finished</li>
</ul>
<p>Thus it is not alternative.</p>
</div>
<div class="section" id="data-model-impact">
<h3>Data model impact</h3>
<p>None</p>
</div>
<div class="section" id="rest-api-impact">
<h3>REST API impact</h3>
<p>None</p>
</div>
<div class="section" id="versioning-impact">
<h3>Versioning impact</h3>
<p>None</p>
</div>
<div class="section" id="other-end-user-impact">
<h3>Other end user impact</h3>
<p>User (admin) can control modification by creating <em>predeploy_modify</em> Congress policy
rules.</p>
</div>
<div class="section" id="deployer-impact">
<h3>Deployer impact</h3>
<p>None</p>
</div>
<div class="section" id="developer-impact">
<h3>Developer impact</h3>
<p>None</p>
</div>
<div class="section" id="murano-dashboard-horizon-impact">
<h3>Murano-dashboard / Horizon impact</h3>
<p>None</p>
</div>
</div>
<div class="section" id="implementation">
<h2>Implementation</h2>
<div class="section" id="assignee-s">
<h3>Assignee(s)</h3>
<dl class="docutils">
<dt>Primary assignee:</dt>
<dd>filip-blaha</dd>
</dl>
</div>
<div class="section" id="work-items">
<h3>Work Items</h3>
<ul class="simple">
<li>design API of modify actions</li>
<li>framework for pluggable modify actions - registering and managing available actions</li>
<li>implement out-of-box actions</li>
<li>add point to engine where congress called and returned action list is processed on given environment</li>
</ul>
</div>
</div>
<div class="section" id="dependencies">
<h2>Dependencies</h2>
<p>None</p>
</div>
<div class="section" id="testing">
<h2>Testing</h2>
<p>We need to cover by unit tests:
* framework for registering/managing modify actions
* applying modify actions on environment
* processing action list returned by congress</p>
<p>We need to create functional tests covering end-to-end scenario.</p>
</div>
<div class="section" id="documentation-impact">
<h2>Documentation Impact</h2>
<p>It is documented as part of policy guided fulfillment.</p>
</div>
<div class="section" id="references">
<h2>References</h2>
</div>
</div>
Wed, 03 Jun 2015 00:00:00 Murano API - Core Model Component Integration Improvementhttp://murano-specs.readthedocs.org/specs/liberty/murano-core-model-integration-improvements.html
<p><a class="reference external" href="https://blueprints.launchpad.net/murano/+spec/murano-core-model-integration-improvements">https://blueprints.launchpad.net/murano/+spec/murano-core-model-integration-improvements</a></p>
<p>Core Model can be seen as API, because user is using it when writing Datalog queries
in Congress, or integrating with Mistral workflows. Current Murano Core model does not
provide means to easy link them with realized OpenStack entities (for example Murano
Instance does not provide UUID of provisioned Nova Server).</p>
<div class="section" id="problem-description">
<h2>Problem description</h2>
<p>Congress datalog queries are one of core features used by Policy Guided Fulfillment.
These queries are used to express validity of Murano environment either
in pre-deployment and/or runtime. In order to evaluate environment validity it is
necessary to work with realized entities by core Murano components - for example</p>
<ul class="simple">
<li><em>I want to check if Murano Instance’s Nova server exists and is running</em><ul>
<li>In kilo I have to use IP address of the Murano Instance and do multiple joins of
neutron tables to identify Nova server.</li>
</ul>
</li>
<li><em>I want to check if owner of network used by Murano Environment is from given group of
users</em><ul>
<li>In kilo it is impossible because Murano network object contains only name
of the network (<em>a-network</em>), while realized network (via Heat) contains name
with Murano object id (<em>a-network-bed7a70ed791434c8acdd53a52a8d4ca</em>)</li>
</ul>
</li>
</ul>
</div>
<div class="section" id="proposed-change">
<h2>Proposed change</h2>
<p>Changes of core Murano model:</p>
<ul class="simple">
<li><strong>io.murano.resources.Instance</strong><ul>
<li>add property <em>openstackId</em> and fill the property with value once Heat provisioned
Instance</li>
</ul>
</li>
</ul>
<div class="highlight-python"><div class="highlight"><pre>openstackId:
Contract: $.string()
Usage: Out
</pre></div>
</div>
<ul class="simple">
<li><strong>io.murano.resources.Network</strong><ul>
<li>add property <em>openstackId</em> and fill the property with value once Heat provisioned
network (as part of Instance provisioning)</li>
</ul>
</li>
</ul>
<div class="highlight-python"><div class="highlight"><pre>openstackId:
Contract: $.string()
Usage: Out
</pre></div>
</div>
<div class="section" id="alternatives">
<h3>Alternatives</h3>
<p>Instead of adding the same property to each class aware of openstack ID we can create
mixin class ( e.g. <strong>OpenstackIdMixin</strong>) with this property and all classes aware of
openstack ID will extend that mixin.</p>
<div class="highlight-python"><div class="highlight"><pre>Name: OpenstackIdMixin
Properties:
openstackId:
Contract: $.string()
Usage: Out
</pre></div>
</div>
</div>
<div class="section" id="data-model-impact">
<h3>Data model impact</h3>
<p>None</p>
</div>
<div class="section" id="rest-api-impact">
<h3>REST API impact</h3>
<p>None</p>
</div>
<div class="section" id="versioning-impact">
<h3>Versioning impact</h3>
<p>Murano package versioning is currently analyzed and it is planned for Liberty.</p>
<p>It makes sense to introduce it (modifications of the core Murano packages) as new
versions of core Murano packages.</p>
<p>On the other hand, proposed changes are backward compatible, so they can be
done prior versioning.</p>
</div>
<div class="section" id="other-end-user-impact">
<h3>Other end user impact</h3>
<p>None</p>
</div>
<div class="section" id="deployer-impact">
<h3>Deployer impact</h3>
<p>If proposed changes will be done prior Murano package versioning, then after upgrade
the Murano objects won’t have initialized introduced properties (<em>openstackId</em>).</p>
</div>
<div class="section" id="developer-impact">
<h3>Developer impact</h3>
<p>None</p>
</div>
<div class="section" id="murano-dashboard-horizon-impact">
<h3>Murano-dashboard / Horizon impact</h3>
<p>The change will simplify implementation of Horizon UI (instance detail)</p>
</div>
</div>
<div class="section" id="implementation">
<h2>Implementation</h2>
<div class="section" id="assignee-s">
<h3>Assignee(s)</h3>
<dl class="docutils">
<dt>Primary assignee:</dt>
<dd>filip-blaha</dd>
</dl>
</div>
<div class="section" id="work-items">
<h3>Work Items</h3>
<ul class="simple">
<li>introduce <em>openstackId</em> properties to<ul>
<li><em>meta/io.murano/Classes/resources/Instance.yaml</em></li>
<li><em>meta/io.murano/Classes/resources/Network.yaml</em></li>
</ul>
</li>
<li>implemented instance and network <em>openstackId</em> property population<ul>
<li><em>meta/io.murano/Classes/resources/Instance.yaml</em> , <em>deploy</em> method</li>
<li><em>meta/io.murano/Classes/resources/NeutronNetwork.yaml</em> , <em>deploy</em> method</li>
<li><em>meta/io.murano/Classes/resources/NovaNetwork.yaml</em> won’t be modified, as nova
networking is deprecated</li>
</ul>
</li>
</ul>
</div>
</div>
<div class="section" id="dependencies">
<h2>Dependencies</h2>
<p><a class="reference external" href="https://blueprints.launchpad.net/murano/+spec/murano-versioning">https://blueprints.launchpad.net/murano/+spec/murano-versioning</a></p>
</div>
<div class="section" id="testing">
<h2>Testing</h2>
<p>Both unit and tempest tests of policy guided fulfillment will be enhanced to test properties <em>openstackId</em>.</p>
</div>
<div class="section" id="documentation-impact">
<h2>Documentation Impact</h2>
<p>None</p>
</div>
<div class="section" id="references">
<h2>References</h2>
<ul class="simple">
<li><a class="reference external" href="https://wiki.openstack.org/wiki/PolicyGuidedFulfillmentLibertyPlanning">https://wiki.openstack.org/wiki/PolicyGuidedFulfillmentLibertyPlanning</a></li>
<li><a class="reference external" href="https://wiki.openstack.org/wiki/PolicyGuidedFulfillmentLibertyPlanning_MuranoAPI">https://wiki.openstack.org/wiki/PolicyGuidedFulfillmentLibertyPlanning_MuranoAPI</a></li>
</ul>
</div>
Tue, 02 Jun 2015 00:00:00 Murano API - All Tenants Searchhttp://murano-specs.readthedocs.org/specs/liberty/murano-api-all-tenants-search.html
<p><a class="reference external" href="https://blueprints.launchpad.net/murano/+spec/murano-api-all-tenants-search">https://blueprints.launchpad.net/murano/+spec/murano-api-all-tenants-search</a></p>
<p>Congress Murano datasource driver pulls environments from one tenant only. The goal
is to pull all environments from all tenants (as nova driver does for servers).</p>
<div class="section" id="problem-description">
<h2>Problem description</h2>
<p>Murano - Congress integration is part of a part of Policy Guided Fulfillment.
It uses Congress policy framework to define and evaluate restrictions on Murano
environments. So Murano environments are pulled by Congress Murano datasource driver,
so Congress policy rules can be evaluated.</p>
<p>The problem is that Murano REST API returns environments of one tenant of authenticated user’s token only.
Thus Congress policy rules evaluation is run on data from one tenant only.</p>
<p>Other Congress datasource drivers are dealing with similar requirements also - for example
Nova datasource driver pulls data about all servers across all tenants
in its <em>nova</em> policy. It is possible because Nova REST API supports search option <em>all_tenants</em>.</p>
<p>Note that <em>Congress policy</em> is a place of both rules and data related to one <em>service</em>.
If <em>policy</em> is defined by datasource driver, then its configuration have <em>user</em>, <em>password</em> and <em>tenant</em>,
which are used to get token to access the service.</p>
</div>
<div class="section" id="proposed-change">
<h2>Proposed change</h2>
<p>Search option <em>all_tenants</em> will be added to operation <em>List Environments</em> of
Murano REST API. When set, the returned list will contain all environments accessible
by the user (specified by token) regardless of tenant.
Listing environments from all tenants can only admin user.</p>
<div class="section" id="alternatives">
<h3>Alternatives</h3>
<p>The requested behavior can be also achieved by iterating operation
<em>List Environment</em> over all tenants available to the configuration user.
This solution has following performance issues:</p>
<ul class="simple">
<li>each pull cycle executes the REST operation for every tenant where user is member,
instead of one execution in case of <em>all_tenants</em></li>
<li>user’s tenant assignment has to be periodically updated, so it leads to another
requests to keystone each such period</li>
</ul>
</div>
<div class="section" id="data-model-impact">
<h3>Data model impact</h3>
<p>None</p>
</div>
<div class="section" id="rest-api-impact">
<h3>REST API impact</h3>
<ul class="simple">
<li>List Environments<ul>
<li><em>all_tenants</em> parameter is added. When set to <em>true</em>, then search over all tenants
is executed, otherwise search on token’s tenant is done</li>
</ul>
</li>
</ul>
<p>Example (without <em>all_tenants</em>):</p>
<div class="highlight-python"><div class="highlight"><pre>GET http://<server-name>:8082/v1/environments
{
"environments": [
{
"status": "deploying",
"updated": "2015-05-06T08:14:06",
"networking": {},
"name": "test",
"created": "2015-05-06T08:08:40",
"tenant_id": "cd9e218f9b894ebdb421e9906fbec15e",
"version": 1,
"id": "8cc3187c763f4ca9bc58cdaf89f926d3"
}
]
}
</pre></div>
</div>
<p>Example (with <em>all_tenants</em> - note different <em>tenant_id</em>):</p>
<div class="highlight-python"><div class="highlight"><pre>GET http://<server-name>:8082/v1/environments?all_tenants=true
{
"environments": [
{
"status": "deploying",
"updated": "2015-05-06T08:14:06",
"networking": {},
"name": "test",
"created": "2015-05-06T08:08:40",
"tenant_id": "cd9e218f9b894ebdb421e9906fbec15e",
"version": 1,
"id": "8cc3187c763f4ca9bc58cdaf89f926d3"
},
{
"status": "deploying",
"updated": "2015-05-08T09:34:16",
"networking": {},
"name": "test 2",
"created": "2015-05-08T08:18:20",
"tenant_id": "8908989abbeec239023489023ccc1234f",
"version": 1,
"id": "abecbf88328932bbecbefe82348238b"
}
]
}
</pre></div>
</div>
</div>
<div class="section" id="versioning-impact">
<h3>Versioning impact</h3>
<p>None</p>
</div>
<div class="section" id="other-end-user-impact">
<h3>Other end user impact</h3>
<p><em>python-muranoclient</em> will be changed as follows:</p>
<ul class="simple">
<li><em>–all-tenants</em> on CLI</li>
</ul>
<p>Example:</p>
<div class="highlight-python"><div class="highlight"><pre>$ murano environment-list --all-tenants
</pre></div>
</div>
<ul class="simple">
<li><em>search options</em> will be supported on API level</li>
</ul>
<p>Example:</p>
<div class="highlight-python"><div class="highlight"><pre>class EnvironmentManager(base.ManagerWithFind):
def list(self):
...
def list(self, search_opts):
...
</pre></div>
</div>
</div>
<div class="section" id="deployer-impact">
<h3>Deployer impact</h3>
<p>None</p>
</div>
<div class="section" id="developer-impact">
<h3>Developer impact</h3>
<p>None</p>
</div>
<div class="section" id="murano-dashboard-horizon-impact">
<h3>Murano-dashboard / Horizon impact</h3>
<p>None</p>
</div>
</div>
<div class="section" id="implementation">
<h2>Implementation</h2>
<div class="section" id="assignee-s">
<h3>Assignee(s)</h3>
<dl class="docutils">
<dt>Primary assignee:</dt>
<dd>filip-blaha</dd>
</dl>
</div>
<div class="section" id="work-items">
<h3>Work Items</h3>
<ul class="simple">
<li>Introduce <em>all_tenants</em> search option in<ul>
<li>file <em>murano/api/v1/environments.py</em></li>
</ul>
</li>
<li>Modify <em>policy.json</em> file with rules<ul>
<li>file <em>etc/murano/policy.json</em></li>
</ul>
</li>
<li>Add support for search options in <em>python-muranoclient</em><ul>
<li>file <em>muranoclient/v1/environments.py</em></li>
</ul>
</li>
<li>Add support for <em>–all-tenants</em> in <em>python-muranoclient</em> CLI<ul>
<li>file <em>muranoclient/shell.py</em></li>
</ul>
</li>
</ul>
</div>
</div>
<div class="section" id="dependencies">
<h2>Dependencies</h2>
<p>None</p>
</div>
<div class="section" id="testing">
<h2>Testing</h2>
<p>Unit tests should cover server API side also client and shell should be covered.</p>
</div>
<div class="section" id="documentation-impact">
<h2>Documentation Impact</h2>
<p>REST API documentation will be modified to mention <em>all_tenants</em> search option.</p>
</div>
<div class="section" id="references">
<h2>References</h2>
<ul class="simple">
<li><a class="reference external" href="https://wiki.openstack.org/wiki/PolicyGuidedFulfillmentLibertyPlanning">https://wiki.openstack.org/wiki/PolicyGuidedFulfillmentLibertyPlanning</a></li>
<li><a class="reference external" href="https://wiki.openstack.org/wiki/PolicyGuidedFulfillmentLibertyPlanning_MuranoAPI">https://wiki.openstack.org/wiki/PolicyGuidedFulfillmentLibertyPlanning_MuranoAPI</a></li>
</ul>
</div>
Mon, 01 Jun 2015 00:00:00 Murano Repository Supporthttp://murano-specs.readthedocs.org/specs/kilo/muranoclient-marketplace-support.html
<p><a class="reference external" href="https://blueprints.launchpad.net/murano/+spec/muranoclient-marketplace-support">https://blueprints.launchpad.net/murano/+spec/muranoclient-marketplace-support</a></p>
<p>Murano applications provide a powerful and flexible way to move workloads
from other cloud environments to OpenStack. In order to accelerate
application migrating we need a way to deliver Murano
packages and Glance images to customers incrementally, independent from major
releases of OpenStack.</p>
<div class="section" id="problem-description">
<h2>Problem description</h2>
<p>Typical use cases:</p>
<ul class="simple">
<li>After the end users installed and configured Murano they would need to
install murano-enabled applications. To do so they would use <cite>murano</cite> CLI
client. Invoking a command like
<cite>murano install-package io.apps.application –version=2.0</cite> would
install the application in question alongside with all requirements
(applications and glance images)</li>
<li>A developer would want to provide murano applications to end users, by
hosting them on a web server and providing http-access to application
packages. In that case end users would be able to install the application by
invoking a CLI command <cite>murano install-package http://path/to/app</cite></li>
<li>End user would want to install bundles of applications that are often
required to work together, but not necessarily depend on each other.
In that case end user would invoke a command
<cite>murano install-bundle bundle_name</cite> and murano-client would download all
the applications mentioned in the bundle alongside with their requirements.</li>
<li>End users would want to perform same operations through
murano-dashboard instead of CLI tools.</li>
</ul>
</div>
<div class="section" id="proposed-change">
<h2>Proposed change</h2>
<p>The proposition is to implement a set of features in python-muranoclient and
murano-dashboard, that would allow end users to install applications from
http application repository.</p>
<ul class="simple">
<li>Enable <cite>package-import</cite> command to support url as a parameter for import by
modifying the way package creation of murano-client works.</li>
<li>Enable <cite>package-import</cite> command to support package name as a parameter for
import, introduce <cite>–murano-repo-url</cite> as a base path to the repository.</li>
<li>Introduce <cite>bundle-import</cite> command and allow it to support local-files, urls
and bundle names as parameters for import. The command should parse the
bundle file and import all the packages, mentioned in the file.
Bundle should be a simple json and/or yaml-structured file.</li>
<li>Introduce <cite>Require:</cite> section to <cite>manifest.yaml</cite>, that would specify which
packages are required by the appication.</li>
<li>Enable package creation suite to automatically import all the packages
mentioned in <cite>Require:</cite> section.</li>
<li>Introduce <cite>images.lst</cite> file in the package structure, that would contain a
list of images, required for the application to work.</li>
<li>Enable package creation suite to automatically import required images into
glance image service.</li>
<li>Allow <cite>bundle-import</cite> command to import bundles from local-files. In that
case first search for package files and image files in the local filesystem,
relative to the location of the bundle file. If file is not found locally
attempt to connect to the repository.</li>
<li>Enable murano-dashboard to support changes made to client and introduce a way
to upload packages via url/name to dashboard.</li>
<li>Implement importing of bundles in murano-dashboard by url or by name.
Since bundles are currently a simple json/yaml optionally we could optionally
support direct input.</li>
<li>Implement error handling both for CLI-tools and dashboard, that would inform
end users about any errors that might have happened along the way of
importing.</li>
<li>Optionally implement a progress marker and a ETA-marker for CLI <cite>import</cite>
commands.</li>
</ul>
<div class="section" id="alternatives">
<h3>Alternatives</h3>
<p>Implementing a server, that would hold versions and paths to package files
and implementing a client to that server might be a good alternative to a
simple http-server, although it seems a bit excessive at the moment.</p>
<p>Another idea would be to implement a service, that would download packages
asynchronously. This would allow client to download large package files and
image files with possibly better error handling mechanisms. This also seems a
bit excessive at the moment.</p>
</div>
<div class="section" id="data-model-impact">
<h3>Data model impact</h3>
<p>It might be a good idea to store information about required apps and required
images, although it is not strictly required for the task.</p>
</div>
<div class="section" id="rest-api-impact">
<h3>REST API impact</h3>
<p>It might be a good idea to warn the end user if the client installed a
package, that depends on other packages, not present in app catalog,
although it is not strictly required for the task.</p>
</div>
<div class="section" id="versioning-impact">
<h3>Versioning impact</h3>
<p>This proposition adds functionality both to python-muranoclient and to
murano-dashboard. It should be fully backward compatible.</p>
<p>Minor version of python-muranoclient should be increased, because we add
functionality.</p>
</div>
<div class="section" id="other-end-user-impact">
<h3>Other end user impact</h3>
<p>See <em>Proposed Change</em> section, as it describes all the ways users would
interact with the feature</p>
</div>
<div class="section" id="deployer-impact">
<h3>Deployer impact</h3>
<p>None</p>
</div>
<div class="section" id="developer-impact">
<h3>Developer impact</h3>
<p>None</p>
</div>
<div class="section" id="murano-dashboard-horizon-impact">
<h3>Murano-dashboard / Horizon impact</h3>
<p>Package import dialog should be changed to reflect different ways of
importing an application.
Additional bundle-import dialog should be implemented.</p>
</div>
</div>
<div class="section" id="implementation">
<h2>Implementation</h2>
<div class="section" id="assignee-s">
<h3>Assignee(s)</h3>
<dl class="docutils">
<dt>Primary assignee:</dt>
<dd><<a class="reference external" href="mailto:kzaitsev%40mirantis.com">kzaitsev<span>@</span>mirantis<span>.</span>com</a>></dd>
</dl>
</div>
<div class="section" id="work-items">
<h3>Work Items</h3>
<ul class="simple">
<li>Add support for importing packages by url in client</li>
<li>Add support for importing packages by name in client</li>
<li>Add support for importing bundles by name/url in client</li>
<li>Add support for recursive parsing of Require section of <cite>manifest.yaml</cite>
file in client</li>
<li>Add support for image download/upload from <cite>images.lst</cite> file in client</li>
<li>Handle <cite>package exists</cite> error in CLI client</li>
<li>Add support for different ways to import a package in murano-dashboard</li>
<li>Add support for bundle-import in murano-dashboard</li>
<li>Add support for image/package requirements while importing packages and
bundles in murano-dashboard</li>
</ul>
</div>
</div>
<div class="section" id="dependencies">
<h2>Dependencies</h2>
<p>None</p>
</div>
<div class="section" id="testing">
<h2>Testing</h2>
<p>Unit testing should be sufficient to cover most of the use cases.
However an integration test, that would setup a simple repository is very
desirable, since we add changes to both <cite>python-muranoclient</cite> and
<cite>muranodashboard</cite>.</p>
</div>
<div class="section" id="documentation-impact">
<h2>Documentation Impact</h2>
<p>Additional capabilities of the CLI client should be documented, otherwise
there should be no impact, since we do not change the API.</p>
</div>
<div class="section" id="references">
<h2>References</h2>
<p>None</p>
</div>
Sun, 05 Apr 2015 00:00:00 Environment Template Cataloguehttp://murano-specs.readthedocs.org/specs/kilo/blueprint-template.html
<p><a class="reference external" href="https://blueprints.launchpad.net/murano/+spec/blueprint-template">https://blueprints.launchpad.net/murano/+spec/blueprint-template</a></p>
<div class="section" id="problem-description">
<h2>Problem description</h2>
<p>One of powerful Murano use cases is deploying compound applications, composed by set of
different layers such as DB, web server and others, which implies the deployment of
software not just in an unique VM but in several ones. The environment template is the specification of
the set of VMs plus the applications to be installed on top of. The user can define
environment templates from scratch or reuse and customize them (e.g. including keypairs).
Environment templates not only cover instantiation, but also the specification of such templates,
store them in a catalogue and clone them from the abstract template catalog. In this way,
an abstract environment template catalogue as well as a environment template one will be stored in the
database, storing templates shared among all users and individual ones.</p>
</div>
<div class="section" id="proposed-change">
<h2>Proposed change</h2>
<p>In order to fullfill this functionality, a new entity can be introduced in the MURANO
database. It is the Murano environment-template, which contains the specification about what
is going to be deployed in terms of virtual resources and application information, and it can be deployed
on top of Openstack by translating it into environment. This environment template can be created, deleted,
modified and customized by the users. In fact, it can be instantiate as many times as the user wants.
For instance, the user wants to have different deployments from the same environment template: one for
testing and another for production.</p>
<p>The environment template is composed by a set of services/applications with the software to be installed together their
properties to work with. This software can be instantiate over an virtual service.</p>
<p>In this case the workflow for the creation and the instantiation of the environment template will imply:
1.- Creation of the environment template (including application information)
2.- Transformation of the environment template into the environment (creation of the environment, session and
adding applications to the environment
3.- Deploy the environment on top of Openstack.</p>
<p>The environment template structure and information will be similar to the environment, not including some hardware information, like
default network, or virtual server name. Mainly, the environment template information will contain:
- template name, the name for the template. In case, it is not provided, the request will not be valid.
- services, the application information. For each service it will include information about the applications to be
installed (like tomcat), including application properties like tomcat port. In addition, in case applied, the information about
the virtual server (instance) will be incorporated like keyname, flavor, image and so on. The following lines show
an environment template example.</p>
<div class="highlight-python"><div class="highlight"><pre><span class="p">{</span>
<span class="s">"name"</span><span class="p">:</span> <span class="s">"env_template_name"</span><span class="p">,</span>
<span class="s">"services"</span><span class="p">:</span> <span class="p">[</span>
<span class="p">{</span>
<span class="s">"instance"</span><span class="p">:</span> <span class="p">{</span>
<span class="s">"assignFloatingIp"</span><span class="p">:</span> <span class="s">"true"</span><span class="p">,</span>
<span class="s">"keyname"</span><span class="p">:</span> <span class="s">"mykeyname"</span><span class="p">,</span>
<span class="s">"image"</span><span class="p">:</span> <span class="s">"cloud-fedora-v3"</span><span class="p">,</span>
<span class="s">"flavor"</span><span class="p">:</span> <span class="s">"m1.medium"</span><span class="p">,</span>
<span class="s">"?"</span><span class="p">:</span> <span class="p">{</span>
<span class="s">"type"</span><span class="p">:</span> <span class="s">"io.murano.resources.LinuxMuranoInstance"</span><span class="p">,</span>
<span class="s">"id"</span><span class="p">:</span> <span class="s">"ef984a74-29a4-45c0-b1dc-2ab9f075732e"</span>
<span class="p">}</span>
<span class="p">},</span>
<span class="s">"name"</span><span class="p">:</span> <span class="s">"tomcat"</span><span class="p">,</span>
<span class="s">"port"</span><span class="p">:</span> <span class="s">"8080"</span><span class="p">,</span>
<span class="s">"?"</span><span class="p">:</span> <span class="p">{</span>
<span class="s">"type"</span><span class="p">:</span> <span class="s">"io.murano.apps.apache.Tomcat"</span><span class="p">,</span>
<span class="s">"id"</span><span class="p">:</span> <span class="s">"54cea43d-5970-4c73-b9ac-fea656f3c722"</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">]</span>
<span class="p">}</span>
</pre></div>
</div>
<div class="section" id="alternatives">
<h3>Alternatives</h3>
<p>None</p>
</div>
<div class="section" id="data-model-impact">
<h3>Data model impact</h3>
<p>A environment template entity will be introduced in the MURANO object model. This implies its existence
in the database, the inclusion of Template services and the extension of the API. The template entity
can consist on:</p>
<blockquote>
<div><dl class="docutils">
<dt>template :-</dt>
<dd>murano:property(temp_id, “created”, datetime)
murano:property(temp_id, “updated”, datetime)
murano:property(temp_id, “id”, ID)
murano:property(temp_id, “name”, varchar)
murano:property(temp_id, “tenant-id”, varchar)
murano:property(temp_id, “version”, bigint)
murano:property(temp_id, “description”, text)
murano:property(temp_id, “networking”, text)</dd>
</dl>
</div></blockquote>
</div>
<div class="section" id="rest-api-impact">
<h3>REST API impact</h3>
<p>The inclusion of the environment-template entity will imply the extension of the API for the environment-template
creation, deletion, updating and translate into the environment.</p>
<p><strong>POST /templates</strong></p>
<p><em>Request</em></p>
<table border="1" class="docutils">
<colgroup>
<col width="13%"/>
<col width="40%"/>
<col width="48%"/>
</colgroup>
<thead valign="bottom">
<tr class="row-odd"><th class="head">Method</th>
<th class="head">URI</th>
<th class="head">Description</th>
</tr>
</thead>
<tbody valign="top">
<tr class="row-even"><td>POST</td>
<td>/templates</td>
<td>Create a new environment template</td>
</tr>
</tbody>
</table>
<dl class="docutils">
<dt><em>Content-Type</em></dt>
<dd>application/json</dd>
</dl>
<p><em>Example Payload</em>
This template description can be composed just by the environment template name, or it can
include the description of all services/applications to be deployed.
1.- Just the template</p>
<div class="highlight-python"><div class="highlight"><pre><span class="p">{</span>
<span class="s">'name'</span><span class="p">:</span> <span class="s">'env_template_name'</span>
<span class="p">}</span>
</pre></div>
</div>
<p>2.- Specification of all the services</p>
<div class="highlight-python"><div class="highlight"><pre>{
"name": "env_template_name",
"services": [
{
"instance": {
"assignFloatingIp": "true",
"keyname": "mykeyname",
"image": "cloud-fedora-v3",
"flavor": "m1.medium",
"?": {
"type": "io.murano.resources.LinuxMuranoInstance",
"id": "ef984a74-29a4-45c0-b1dc-2ab9f075732e"
},
"name": "orion",
"port": "8080",
"?": {
"type": "io.murano.apps.apache.Tomcat",
"id": "54cea43d-5970-4c73-b9ac-fea656f3c722"
}
}
]
}
</pre></div>
</div>
<p><em>Response</em></p>
<div class="highlight-python"><div class="highlight"><pre><span class="p">{</span>
<span class="s">"updated"</span><span class="p">:</span> <span class="s">"2015-01-26T09:12:51"</span><span class="p">,</span>
<span class="s">"networking"</span><span class="p">:</span>
<span class="p">{</span>
<span class="p">},</span>
<span class="s">"name"</span><span class="p">:</span> <span class="s">"template_name"</span><span class="p">,</span>
<span class="s">"created"</span><span class="p">:</span> <span class="s">"2015-01-26T09:12:51"</span><span class="p">,</span>
<span class="s">"tenant_id"</span><span class="p">:</span> <span class="s">"00000000000000000000000000000001"</span><span class="p">,</span>
<span class="s">"version"</span><span class="p">:</span> <span class="mi">0</span><span class="p">,</span>
<span class="s">"id"</span><span class="p">:</span> <span class="s">"aa9033ca7ce245fca10e38e1c8c4bbf7"</span><span class="p">,</span>
<span class="p">}</span>
</pre></div>
</div>
<p>+————————–+———————————————————–+
| Code | Description |
+================+===========================================================+
| 200 | OK. Environment Template created successfully |
+—————-+———————————————————–+
| 401 | User is not authorized to access this session |
+—————-+———————————————————–+
| 409 | The environment template already exists |
+—————-+———————————————————–+</p>
<p><strong>GET /templates/{env-temp-id}</strong></p>
<p><em>Request</em></p>
<table border="1" class="docutils">
<colgroup>
<col width="11%"/>
<col width="35%"/>
<col width="54%"/>
</colgroup>
<thead valign="bottom">
<tr class="row-odd"><th class="head">Method</th>
<th class="head">URI</th>
<th class="head">Description</th>
</tr>
</thead>
<tbody valign="top">
<tr class="row-even"><td>GET</td>
<td>/templates/{env-temp-id}</td>
<td>Obtains the environment template information</td>
</tr>
</tbody>
</table>
<p><em>Parameters:</em></p>
<ul class="simple">
<li><cite>env-temp-id</cite> - environment template ID, required</li>
</ul>
<dl class="docutils">
<dt><em>Content-Type</em></dt>
<dd>application/json</dd>
</dl>
<p><em>Response</em></p>
<div class="highlight-python"><div class="highlight"><pre><span class="p">{</span>
<span class="s">"updated"</span><span class="p">:</span> <span class="s">"2015-01-26T09:12:51"</span><span class="p">,</span>
<span class="s">"networking"</span><span class="p">:</span>
<span class="p">{</span>
<span class="p">},</span>
<span class="s">"name"</span><span class="p">:</span> <span class="s">"template_name"</span><span class="p">,</span>
<span class="s">"created"</span><span class="p">:</span> <span class="s">"2015-01-26T09:12:51"</span><span class="p">,</span>
<span class="s">"tenant_id"</span><span class="p">:</span> <span class="s">"00000000000000000000000000000001"</span><span class="p">,</span>
<span class="s">"version"</span><span class="p">:</span> <span class="mi">0</span><span class="p">,</span>
<span class="s">"id"</span><span class="p">:</span> <span class="s">"aa9033ca7ce245fca10e38e1c8c4bbf7"</span><span class="p">,</span>
<span class="p">}</span>
</pre></div>
</div>
<p>+————————–+———————————————————–+
| Code | Description |
+================+===========================================================+
| 200 | OK. Environment Template created successfully |
+—————-+———————————————————–+
| 401 | User is not authorized to access this session |
+—————-+———————————————————–+
| 404 | The environment template does not exit |
+—————-+———————————————————–+</p>
<p><strong>DELETE /templates/{env-temp-id}</strong></p>
<p><em>Request</em></p>
<table border="1" class="docutils">
<colgroup>
<col width="13%"/>
<col width="44%"/>
<col width="44%"/>
</colgroup>
<thead valign="bottom">
<tr class="row-odd"><th class="head">Method</th>
<th class="head">URI</th>
<th class="head">Description</th>
</tr>
</thead>
<tbody valign="top">
<tr class="row-even"><td>DELETE</td>
<td>/templates/<env-temp-id></td>
<td>Delete the template id</td>
</tr>
</tbody>
</table>
<p><em>Parameters:</em></p>
<ul class="simple">
<li><cite>env-temp_id</cite> - environment template ID, required</li>
</ul>
<p><em>Response</em></p>
<table border="1" class="docutils">
<colgroup>
<col width="21%"/>
<col width="79%"/>
</colgroup>
<thead valign="bottom">
<tr class="row-odd"><th class="head">Code</th>
<th class="head">Description</th>
</tr>
</thead>
<tbody valign="top">
<tr class="row-even"><td>200</td>
<td>OK. Environment Template deleted successfully</td>
</tr>
<tr class="row-odd"><td>401</td>
<td>User is not authorized to access this session</td>
</tr>
<tr class="row-even"><td>404</td>
<td>Not found. Specified environment template doesn`t exist</td>
</tr>
</tbody>
</table>
<p><strong>POST /templates/{template-id}/services</strong></p>
<p><em>Request</em></p>
<table border="1" class="docutils">
<colgroup>
<col width="13%"/>
<col width="45%"/>
<col width="43%"/>
</colgroup>
<thead valign="bottom">
<tr class="row-odd"><th class="head">Method</th>
<th class="head">URI</th>
<th class="head">Description</th>
</tr>
</thead>
<tbody valign="top">
<tr class="row-even"><td>POST</td>
<td>/templates/{env-temp-id}/services</td>
<td>Create a new application</td>
</tr>
</tbody>
</table>
<p><em>Parameters:</em></p>
<ul class="simple">
<li><cite>env-temp-id</cite> - The environment-template id, required</li>
<li>payload - the service description</li>
</ul>
<dl class="docutils">
<dt><em>Content-Type</em></dt>
<dd>application/json</dd>
</dl>
<p><em>Example</em></p>
<div class="highlight-python"><div class="highlight"><pre><span class="p">{</span>
<span class="s">"instance"</span><span class="p">:</span> <span class="p">{</span>
<span class="s">"assignFloatingIp"</span><span class="p">:</span> <span class="s">"true"</span><span class="p">,</span>
<span class="s">"keyname"</span><span class="p">:</span> <span class="s">"mykeyname"</span><span class="p">,</span>
<span class="s">"image"</span><span class="p">:</span> <span class="s">"cloud-fedora-v3"</span><span class="p">,</span>
<span class="s">"flavor"</span><span class="p">:</span> <span class="s">"m1.medium"</span><span class="p">,</span>
<span class="s">"?"</span><span class="p">:</span> <span class="p">{</span>
<span class="s">"type"</span><span class="p">:</span> <span class="s">"io.murano.resources.LinuxMuranoInstance"</span><span class="p">,</span>
<span class="s">"id"</span><span class="p">:</span> <span class="s">"ef984a74-29a4-45c0-b1dc-2ab9f075732e"</span>
<span class="p">}</span>
<span class="p">},</span>
<span class="s">"name"</span><span class="p">:</span> <span class="s">"orion"</span><span class="p">,</span>
<span class="s">"port"</span><span class="p">:</span> <span class="s">"8080"</span><span class="p">,</span>
<span class="s">"?"</span><span class="p">:</span> <span class="p">{</span>
<span class="s">"type"</span><span class="p">:</span> <span class="s">"io.murano.apps.apache.Tomcat"</span><span class="p">,</span>
<span class="s">"id"</span><span class="p">:</span> <span class="s">"54cea43d-5970-4c73-b9ac-fea656f3c722"</span>
<span class="p">}</span>
<span class="p">}</span>
</pre></div>
</div>
<p><em>Response</em></p>
<div class="highlight-python"><div class="highlight"><pre><span class="p">{</span>
<span class="s">"instance"</span><span class="p">:</span>
<span class="p">{</span>
<span class="s">"assignFloatingIp"</span><span class="p">:</span> <span class="s">"true"</span><span class="p">,</span>
<span class="s">"keyname"</span><span class="p">:</span> <span class="s">"mykeyname"</span><span class="p">,</span>
<span class="s">"image"</span><span class="p">:</span> <span class="s">"cloud-fedora-v3"</span><span class="p">,</span>
<span class="s">"flavor"</span><span class="p">:</span> <span class="s">"m1.medium"</span><span class="p">,</span>
<span class="s">"?"</span><span class="p">:</span>
<span class="p">{</span>
<span class="s">"type"</span><span class="p">:</span> <span class="s">"io.murano.resources.LinuxMuranoInstance"</span><span class="p">,</span>
<span class="s">"id"</span><span class="p">:</span> <span class="s">"ef984a74-29a4-45c0-b1dc-2ab9f075732e"</span>
<span class="p">}</span>
<span class="p">},</span>
<span class="s">"name"</span><span class="p">:</span> <span class="s">"orion"</span><span class="p">,</span>
<span class="s">"?"</span><span class="p">:</span>
<span class="p">{</span>
<span class="s">"type"</span><span class="p">:</span> <span class="s">"io.murano.apps.apache.Tomcat"</span><span class="p">,</span>
<span class="s">"id"</span><span class="p">:</span> <span class="s">"54cea43d-5970-4c73-b9ac-fea656f3c722"</span>
<span class="p">},</span>
<span class="s">"port"</span><span class="p">:</span> <span class="s">"8080"</span>
<span class="p">}</span>
</pre></div>
</div>
<table border="1" class="docutils">
<colgroup>
<col width="21%"/>
<col width="79%"/>
</colgroup>
<thead valign="bottom">
<tr class="row-odd"><th class="head">Code</th>
<th class="head">Description</th>
</tr>
</thead>
<tbody valign="top">
<tr class="row-even"><td>200</td>
<td>OK. Application added successfully</td>
</tr>
<tr class="row-odd"><td>401</td>
<td>User is not authorized to access this session</td>
</tr>
<tr class="row-even"><td>404</td>
<td>The environment template does not exit</td>
</tr>
</tbody>
</table>
<p><strong>GET /templates/{env-temp-id}/services*</strong>
Request*</p>
<table border="1" class="docutils">
<colgroup>
<col width="12%"/>
<col width="44%"/>
<col width="0%"/>
<col width="43%"/>
</colgroup>
<thead valign="bottom">
<tr class="row-odd"><th class="head">Method</th>
<th class="head" colspan="3">URI | Description</th>
</tr>
</thead>
<tbody valign="top">
<tr class="row-even"><td>GET</td>
<td colspan="3">/templates/{env-temp-id}/services | It obtains the service description</td>
</tr>
</tbody>
</table>
<p><em>Parameters:</em></p>
<ul class="simple">
<li><cite>env-temp-id</cite> - The environment template ID, required</li>
</ul>
<dl class="docutils">
<dt><em>Content-Type</em></dt>
<dd>application/json</dd>
</dl>
<p><em>Response</em></p>
<div class="highlight-python"><div class="highlight"><pre><span class="p">[</span>
<span class="p">{</span>
<span class="s">"instance"</span><span class="p">:</span>
<span class="p">{</span>
<span class="s">"assignFloatingIp"</span><span class="p">:</span> <span class="s">"true"</span><span class="p">,</span>
<span class="s">"keyname"</span><span class="p">:</span> <span class="s">"mykeyname"</span><span class="p">,</span>
<span class="s">"image"</span><span class="p">:</span> <span class="s">"cloud-fedora-v3"</span><span class="p">,</span>
<span class="s">"flavor"</span><span class="p">:</span> <span class="s">"m1.medium"</span><span class="p">,</span>
<span class="s">"?"</span><span class="p">:</span>
<span class="p">{</span>
<span class="s">"type"</span><span class="p">:</span> <span class="s">"io.murano.resources.LinuxMuranoInstance"</span><span class="p">,</span>
<span class="s">"id"</span><span class="p">:</span> <span class="s">"ef984a74-29a4-45c0-b1dc-2ab9f075732e"</span>
<span class="p">}</span>
<span class="p">},</span>
<span class="s">"name"</span><span class="p">:</span> <span class="s">"tomcat"</span><span class="p">,</span>
<span class="s">"?"</span><span class="p">:</span>
<span class="p">{</span>
<span class="s">"type"</span><span class="p">:</span> <span class="s">"io.murano.apps.apache.Tomcat"</span><span class="p">,</span>
<span class="s">"id"</span><span class="p">:</span> <span class="s">"54cea43d-5970-4c73-b9ac-fea656f3c722"</span>
<span class="p">},</span>
<span class="s">"port"</span><span class="p">:</span> <span class="s">"8080"</span>
<span class="p">},</span>
<span class="p">{</span>
<span class="s">"instance"</span><span class="p">:</span> <span class="s">"ef984a74-29a4-45c0-b1dc-2ab9f075732e"</span><span class="p">,</span>
<span class="s">"password"</span><span class="p">:</span> <span class="s">"XXX"</span><span class="p">,</span>
<span class="s">"name"</span><span class="p">:</span> <span class="s">"mysql"</span><span class="p">,</span>
<span class="s">"?"</span><span class="p">:</span>
<span class="p">{</span>
<span class="s">"type"</span><span class="p">:</span> <span class="s">"io.murano.apps.database.MySQL"</span><span class="p">,</span>
<span class="s">"id"</span><span class="p">:</span> <span class="s">"54cea43d-5970-4c73-b9ac-fea656f3c722"</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">]</span>
</pre></div>
</div>
<table border="1" class="docutils">
<colgroup>
<col width="21%"/>
<col width="79%"/>
</colgroup>
<thead valign="bottom">
<tr class="row-odd"><th class="head">Code</th>
<th class="head">Description</th>
</tr>
</thead>
<tbody valign="top">
<tr class="row-even"><td>200</td>
<td>OK. Tier created successfully</td>
</tr>
<tr class="row-odd"><td>401</td>
<td>User is not authorized to access this session</td>
</tr>
<tr class="row-even"><td>404</td>
<td>The environment template does not exit</td>
</tr>
</tbody>
</table>
<p><strong>POST /templates/{env-temp-id}/create-environment</strong></p>
<p><em>Request</em></p>
<table border="1" class="docutils">
<colgroup>
<col width="11%"/>
<col width="35%"/>
<col width="12%"/>
<col width="42%"/>
</colgroup>
<thead valign="bottom">
<tr class="row-odd"><th class="head">Method</th>
<th class="head" colspan="3">URI | Description</th>
</tr>
</thead>
<tbody valign="top">
<tr class="row-even"><td>POST</td>
<td colspan="3">/templates/{env-temp-id}/create-environment| Create an environment</td>
</tr>
</tbody>
</table>
<p><em>Parameters:</em></p>
<ul class="simple">
<li><cite>env-temp-id</cite> - The environment template ID, required</li>
</ul>
<p><em>Payload:</em></p>
<ul class="simple">
<li>‘environment name’: The environment name to be created.</li>
</ul>
<dl class="docutils">
<dt><em>Content-Type</em></dt>
<dd>application/json</dd>
</dl>
<p><em>Example</em></p>
<div class="highlight-python"><div class="highlight"><pre><span class="p">{</span>
<span class="s">'name'</span><span class="p">:</span> <span class="s">'environment_name'</span>
<span class="p">}</span>
</pre></div>
</div>
<p><em>Response</em></p>
<div class="highlight-python"><div class="highlight"><pre><span class="p">{</span>
<span class="s">"environment_id"</span><span class="p">:</span> <span class="s">"aa90fadfafca10e38e1c8c4bbf7"</span><span class="p">,</span>
<span class="s">"name"</span><span class="p">:</span> <span class="s">"environment_name"</span><span class="p">,</span>
<span class="s">"created"</span><span class="p">:</span> <span class="s">"2015-01-26T09:12:51"</span><span class="p">,</span>
<span class="s">"tenant_id"</span><span class="p">:</span> <span class="s">"00000000000000000000000000000001"</span><span class="p">,</span>
<span class="s">"version"</span><span class="p">:</span> <span class="mi">0</span><span class="p">,</span>
<span class="s">"session_id"</span><span class="p">:</span> <span class="s">"adf4dadfaa9033ca7ce245fca10e38e1c8c4bbf7"</span><span class="p">,</span>
<span class="p">}</span>
</pre></div>
</div>
<p>+————————–+———————————————————–+
| Code | Description |
+================+===========================================================+
| 200 | OK. Environment template created successfully |
+—————-+———————————————————–+
| 401 | User is not authorized to access this session |
+—————-+———————————————————–+
| 404 | The environment template does not exit |
+—————-+———————————————————–+
| 409 | The environment already exists |
+—————-+———————————————————–+</p>
</div>
<div class="section" id="versioning-impact">
<h3>Versioning impact</h3>
<p>Murano client will change to include this new functionality.</p>
</div>
<div class="section" id="other-end-user-impact">
<h3>Other end user impact</h3>
<p>As well as a change in the API to include this new entity, the python-muranoclient will
be changed for including the environment template operations.
* env-template-create Create an environment template.
* env-template-delete Delete an environment template.
* env-template-list List the environment templates.
* env-template-rename Rename an environment template.
* env-template-show Show the information of the environment template
* env-template-add-app Add an application to the environment template
* env-template-create-environment It creates an environment from the environment template description</p>
</div>
<div class="section" id="deployer-impact">
<h3>Deployer impact</h3>
<p>None</p>
</div>
<div class="section" id="developer-impact">
<h3>Developer impact</h3>
<p>None</p>
</div>
<div class="section" id="murano-dashboard-horizon-impact">
<h3>Murano-dashboard / Horizon impact</h3>
<p>New views will be required for including the environment template functionality</p>
</div>
</div>
<div class="section" id="implementation">
<h2>Implementation</h2>
<div class="section" id="assignee-s">
<h3>Assignee(s)</h3>
<dl class="docutils">
<dt>Primary assignee:</dt>
<dd>hmunfru</dd>
<dt>Other contributors:</dt>
<dd>jesuspg
TBC</dd>
</dl>
</div>
<div class="section" id="work-items">
<h3>Work Items</h3>
<p>1.- Including the environment template entity in database
2.- Extension of the API for environment template catalogue
3.- Generation of environment from template operation
4.- Implement the changes in murano CLI</p>
</div>
</div>
<div class="section" id="dependencies">
<h2>Dependencies</h2>
</div>
<div class="section" id="testing">
<h2>Testing</h2>
<p>TBD</p>
</div>
<div class="section" id="documentation-impact">
<h2>Documentation Impact</h2>
<p>Environment template documentation should be included.</p>
</div>
<div class="section" id="references">
<h2>References</h2>
<p><a class="reference external" href="https://etherpad.openstack.org/p/GLLAQ0m1H7">https://etherpad.openstack.org/p/GLLAQ0m1H7</a></p>
</div>
Sat, 21 Mar 2015 00:00:00 Add timeouts to murano-agent callshttp://murano-specs.readthedocs.org/specs/kilo/murano-agent-timeouts.html
<p><a class="reference external" href="https://blueprints.launchpad.net/murano/+spec/murano-agent-timeouts">https://blueprints.launchpad.net/murano/+spec/murano-agent-timeouts</a></p>
<p>Now there is no way to be sure that the agent successfully started execution
on a VM. Also there is no control of the execution time of scripts on agent.
This process should be more controllable. It can be done by adding timeouts
in Murano engine.</p>
<div class="section" id="problem-description">
<h2>Problem description</h2>
<ul class="simple">
<li>During the agent`s work could be some problems with execution of scripts and
VM may hang. In this case user will wait indefinitely without knowing
what’s happend.</li>
<li>Currently there is no feedback from agent so, it`s impossible to determine
whether agent is ready to accept execution plans or not.</li>
</ul>
<p>It is proposed to provide mechanism of timeouts which solve these problems.</p>
</div>
<div class="section" id="proposed-change">
<h2>Proposed change</h2>
<ol class="arabic simple">
<li>First of all add timeout to method <em>call</em> of agent on engine-side.</li>
</ol>
<p>Optional parameter <em>timeout</em> will be added to method <em>call</em> of class <em>Agent</em>
in agent.py. This parameter is the time in seconds with default value <em>600</em>.
Developer can set up custom value during developing apps for example in this
way:</p>
<div class="highlight-python"><div class="highlight"><pre>- $.instance.agent.call($template, $resources, 300)
</pre></div>
</div>
<p>If the agent plan execution time exceeds the limit, it will be terminated.</p>
<ol class="arabic simple" start="2">
<li>Add method <em>waitReady</em> in Agent class.</li>
</ol>
<p>Method will be added to <em>Agent</em> class in agent.py. It has optional parameter
<em>timeout</em> with default value <em>100</em>. <em>waitReady</em> creates test plan with trivial
body:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="n">template</span> <span class="o">=</span> <span class="p">{</span><span class="s">'Body'</span><span class="p">:</span> <span class="s">'return'</span><span class="p">,</span> <span class="s">'FormatVersion'</span><span class="p">:</span> <span class="s">'2.0.0'</span><span class="p">,</span> <span class="s">'Scripts'</span><span class="p">:</span> <span class="p">{}}</span>
</pre></div>
</div>
<p>and sends this plan once to agent by method <em>call</em>. It can be uses by developer
to stop deployment before sending template of app if agent is inaccessible as
follows:</p>
<div class="highlight-python"><div class="highlight"><pre>- $.instance.agent.waitReady()
- $.instance.agent.call($template, $resources)
</pre></div>
</div>
<p>If the agent test plan execution time exceeds the time limit,
<em>TimeoutException</em> will be raised and deployment terminates. <em>TimeoutException</em>
will be created in murano/common/exceptions.py.</p>
<ol class="arabic simple" start="3">
<li>Add new method <em>isReady</em> in Agent class.</li>
</ol>
<p>This method will be simply call the <em>waitReady</em>. Method <em>isReady</em> returns:</p>
<blockquote>
<div><ul class="simple">
<li><em>True</em>, if test plan is executed on time;</li>
<li><em>False</em>, if the agent plan execution time exceeds the
limit.</li>
<li>and raise <em>PolicyViolationException</em>, which will be created in
murano/coommon/exceptions,py, if the agent disabled by the server.</li>
</ul>
</div></blockquote>
<p>The method can be used during development Murano-applications. For example,
developer can check if the agent is running and ready to execute templates
before sending the execution plan of application:</p>
<div class="highlight-python"><div class="highlight"><pre>- If: $.instance.agent.isReady()
Then:
- $._environment.reporter.report($this, 'Murano Agent is ready')
</pre></div>
</div>
<p>The message in above example will be reported to Murano Dashboard.</p>
<div class="section" id="alternatives">
<h3>Alternatives</h3>
<p>None</p>
</div>
<div class="section" id="data-model-impact">
<h3>Data model impact</h3>
<p>None</p>
</div>
<div class="section" id="rest-api-impact">
<h3>REST API impact</h3>
<p>None</p>
</div>
<div class="section" id="versioning-impact">
<h3>Versioning impact</h3>
<p>None</p>
</div>
<div class="section" id="other-end-user-impact">
<h3>Other end user impact</h3>
<p>None</p>
</div>
<div class="section" id="deployer-impact">
<h3>Deployer impact</h3>
<p>None</p>
</div>
<div class="section" id="developer-impact">
<h3>Developer impact</h3>
<p>None</p>
</div>
<div class="section" id="murano-dashboard-horizon-impact">
<h3>Murano-dashboard / Horizon impact</h3>
<p>None</p>
</div>
</div>
<div class="section" id="implementation">
<h2>Implementation</h2>
<div class="section" id="assignee-s">
<h3>Assignee(s)</h3>
<dl class="docutils">
<dt>Primary assignee:lk</dt>
<dd>ddovbii</dd>
</dl>
</div>
<div class="section" id="work-items">
<h3>Work Items</h3>
<p>The change is simple and can be done in one Gerrit patch. Implementation is
acutally completed.</p>
</div>
</div>
<div class="section" id="dependencies">
<h2>Dependencies</h2>
<p>None</p>
</div>
<div class="section" id="testing">
<h2>Testing</h2>
<p>Unit and integration tests must be done.</p>
</div>
<div class="section" id="documentation-impact">
<h2>Documentation Impact</h2>
<p>MuranoPL specification should be updated.</p>
</div>
<div class="section" id="references">
<h2>References</h2>
<p>None</p>
</div>
Wed, 18 Mar 2015 00:00:00 Example Spec - The title of your blueprinthttp://murano-specs.readthedocs.org/specs/kilo/placeholder.html
<p>Include the URL of your launchpad blueprint:</p>
<p><a class="reference external" href="https://blueprints.launchpad.net/murano/+spec/example">https://blueprints.launchpad.net/murano/+spec/example</a></p>
<p>Introduction paragraph – why are we doing anything? A single paragraph of
prose that operators can understand. The title and this first paragraph
should be used as the subject line and body of the commit message
respectively.</p>
<p>Some notes about using this template:</p>
<ul>
<li><p class="first">Your spec should be in ReSTructured text, like this template.</p>
</li>
<li><p class="first">Please wrap text at 79 columns.</p>
</li>
<li><p class="first">The filename in the git repository should match the launchpad URL, for
example a URL of: <a class="reference external" href="https://blueprints.launchpad.net/murano/+spec/awesome-thing">https://blueprints.launchpad.net/murano/+spec/awesome-thing</a>
should be named awesome-thing.rst</p>
</li>
<li><p class="first">Please do not delete any of the sections in this template. If you have
nothing to say for a whole section, just write: None</p>
</li>
<li><p class="first">For help with syntax, see <a class="reference external" href="http://sphinx-doc.org/rest.html">http://sphinx-doc.org/rest.html</a></p>
</li>
<li><p class="first">To test out your formatting, build the docs using tox, or see:
<a class="reference external" href="http://rst.ninjs.org">http://rst.ninjs.org</a></p>
</li>
<li><p class="first">If you would like to provide a diagram with your spec, ascii diagrams are
required. <a class="reference external" href="http://asciiflow.com/">http://asciiflow.com/</a> is a very nice tool to assist with making
ascii diagrams. The reason for this is that the tool used to review specs is
based purely on plain text. Plain text will allow review to proceed without
having to look at additional files which can not be viewed in gerrit. It
will also allow inline feedback on the diagram itself.</p>
</li>
<li><p class="first">If your specification proposes any changes to the Murano REST API such
as changing parameters which can be returned or accepted, or even
the semantics of what happens when a client calls into the API, then
you should add the APIImpact flag to the commit message. Specifications with
the APIImpact flag can be found with the following query:</p>
<p><a class="reference external" href="https://review.openstack.org/#/q/status:open+project:stackforge/murano-specs+message:apiimpact,n,z">https://review.openstack.org/#/q/status:open+project:stackforge/murano-specs+message:apiimpact,n,z</a></p>
</li>
</ul>
<div class="section" id="problem-description">
<h2>Problem description</h2>
<p>A detailed description of the problem:</p>
<ul class="simple">
<li>For a new feature this might be use cases. Ensure you are clear about the
actors in each use case: End User vs Deployer</li>
<li>For a major reworking of something existing it would describe the
problems in that feature that are being addressed.</li>
</ul>
</div>
<div class="section" id="proposed-change">
<h2>Proposed change</h2>
<p>Here is where you cover the change you propose to make in detail. How do you
propose to solve this problem?</p>
<p>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?</p>
<div class="section" id="alternatives">
<h3>Alternatives</h3>
<p>What other ways could we do this thing? Why aren’t we using those? This doesn’t
have to be a full literature review, but it should demonstrate that thought has
been put into why the proposed solution is an appropriate one.</p>
</div>
<div class="section" id="data-model-impact">
<h3>Data model impact</h3>
<p>Changes which require modifications to the data model often have a wider impact
on the system. The community often has strong opinions on how the data model
should be evolved, from both a functional and performance perspective. It is
therefore important to capture and gain agreement as early as possible on any
proposed changes to the data model.</p>
<p>Questions which need to be addressed by this section include:</p>
<ul class="simple">
<li>What new data objects and/or database schema changes is this going to
require?</li>
<li>What database migrations will accompany this change.</li>
<li>How will the initial set of new data objects be generated, for example if you
need to take into account existing instances, or modify other existing data
describe how that will work.</li>
</ul>
</div>
<div class="section" id="rest-api-impact">
<h3>REST API impact</h3>
<p>Each API method which is either added or changed should have the following</p>
<ul class="simple">
<li>Specification for the method<ul>
<li>A description of what the method does suitable for use in
user documentation</li>
<li>Method type (POST/PUT/GET/DELETE)</li>
<li>Normal http response code(s)</li>
<li>Expected error http response code(s)<ul>
<li>A description for each possible error code should be included
describing semantic errors which can cause it such as
inconsistent parameters supplied to the method, or when an
instance is not in an appropriate state for the request to
succeed. Errors caused by syntactic problems covered by the JSON
schema definition do not need to be included.</li>
</ul>
</li>
<li>URL for the resource</li>
<li>Parameters which can be passed via the url</li>
</ul>
</li>
<li>Example use case including typical API samples for both data supplied
by the caller and the response</li>
<li>Discuss any policy changes, and discuss what things a deployer needs to
think about when defining their policy.</li>
</ul>
</div>
<div class="section" id="versioning-impact">
<h3>Versioning impact</h3>
<p>Discuss how your change affects versioning and backward compatibility:</p>
<ul class="simple">
<li>Can it break any existing DSL code even in theory?</li>
<li>Can it break API consumers that are using older python-muranoclient versions
or non-python clients?</li>
<li>If you make changes to Murano package please state how the version number
should be incremented?</li>
<li>Does your change require newer version of external or internal component?</li>
<li>How to keep backward compatibility with code and consumers that were
available prior to your change?</li>
</ul>
</div>
<div class="section" id="other-end-user-impact">
<h3>Other end user impact</h3>
<p>Aside from the API, are there other ways a user will interact with this
feature?</p>
<ul class="simple">
<li>Does this change have an impact on python-muranoclient? What does the user
interface there look like?</li>
</ul>
</div>
<div class="section" id="deployer-impact">
<h3>Deployer impact</h3>
<p>Discuss things that will affect how you deploy and configure OpenStack
that have not already been mentioned, such as:</p>
<ul class="simple">
<li>What config options are being added? Should they be more generic than
proposed (for example a flag that other hypervisor drivers might want to
implement as well)? Are the default values ones which will work well in
real deployments?</li>
<li>Is this a change that takes immediate effect after its merged, or is it
something that has to be explicitly enabled?</li>
<li>If this change is a new binary, how would it be deployed?</li>
<li>Please state anything that those doing continuous deployment, or those
upgrading from the previous release, need to be aware of. Also describe
any plans to deprecate configuration values or features. For example, if we
change the directory name that instances are stored in, how do we handle
instance directories created before the change landed? Do we move them? Do
we have a special case in the code? Do we assume that the operator will
recreate all the instances in their cloud?</li>
</ul>
</div>
<div class="section" id="developer-impact">
<h3>Developer impact</h3>
<p>Discuss things that will affect other developers working on OpenStack,
such as:</p>
<ul class="simple">
<li>If the blueprint proposes a change to the driver API, discussion of how
other hypervisors would implement the feature is required.</li>
</ul>
</div>
<div class="section" id="murano-dashboard-horizon-impact">
<h3>Murano-dashboard / Horizon impact</h3>
<p>Does it require changes to the murano-dashboard / horizon? If so, changes
should be described well. If it’s about complex changes than probably a
separate blueprint / spec should be created for it.</p>
</div>
</div>
<div class="section" id="implementation">
<h2>Implementation</h2>
<div class="section" id="assignee-s">
<h3>Assignee(s)</h3>
<p>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?</p>
<p>If more than one person is working on the implementation, please designate the
primary author and contact.</p>
<dl class="docutils">
<dt>Primary assignee:</dt>
<dd><launchpad-id or None></dd>
<dt>Other contributors:</dt>
<dd><launchpad-id or None></dd>
</dl>
</div>
<div class="section" id="work-items">
<h3>Work Items</h3>
<p>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.</p>
</div>
</div>
<div class="section" id="dependencies">
<h2>Dependencies</h2>
<ul class="simple">
<li>Include specific references to specs and/or blueprints in murano, or in other
projects, that this one either depends on or is related to.</li>
<li>If this requires functionality of another project that is not currently used
by Murano, document that fact.</li>
<li>Does this feature require any new library dependencies or code otherwise not
included in OpenStack? Or does it depend on a specific version of library?</li>
</ul>
</div>
<div class="section" id="testing">
<h2>Testing</h2>
<p>Please discuss how the change will be tested. We especially want to know what
tempest tests will be added. It is assumed that unit test coverage will be
added so that doesn’t need to be mentioned explicitly, but discussion of why
you think unit tests are sufficient and we don’t need to add more tempest
tests would need to be included.</p>
<p>Is this untestable in gate given current limitations (specific hardware /
software configurations available)? Is this untestable in murano-ci? If so,
are there mitigation plans (3rd party testing, gate enhancements, etc).</p>
</div>
<div class="section" id="documentation-impact">
<h2>Documentation Impact</h2>
<p>What is the impact on the docs team of this change? Some changes might require
donating resources to the docs team to have the documentation updated. Don’t
repeat details discussed above, but please reference them here.</p>
</div>
<div class="section" id="references">
<h2>References</h2>
<p>Please add any useful references here. You are not required to have any
reference. Moreover, this specification should still make sense when your
references are unavailable. Examples of what you could include are:</p>
<ul class="simple">
<li>Links to mailing list or IRC discussions</li>
<li>Links to notes from a summit session</li>
<li>Links to relevant research, if appropriate</li>
<li>Related specifications as appropriate (e.g. if it’s an EC2 thing, link the
EC2 docs)</li>
<li>Anything else you feel it is worthwhile to refer to</li>
</ul>
</div>
Wed, 18 Mar 2015 00:00:00 Policy Guided Fulfillment - Policy Enforcement Pointhttp://murano-specs.readthedocs.org/specs/kilo/policy-enforcement-point.html
<p>URL of launchpad blueprint:</p>
<p><a class="reference external" href="https://blueprints.launchpad.net/murano/+spec/policy-enforcement-point">https://blueprints.launchpad.net/murano/+spec/policy-enforcement-point</a></p>
<div class="section" id="problem-description">
<h2>Problem description</h2>
<p>As a part of policy guided fulfillment we need to implement <em>predeploy</em> policy enforcement point - i.e., Murano calls Congress to evaluate <em>predeploy</em> policy rules on data representing Murano environment being deployed. If evaluation returns <em>predeploy error</em> data (i.e., enforcement failed), then deployment of Murano environment fails.</p>
<p><em>Predeploy</em> policy rules are represented by <em>predeploy_error(env_id, obj_id, message)</em> congress table.
It means</p>
<ul class="simple">
<li>Congress administrator is responsible for creating predeploy rules, which has this table on the left side (see examples).</li>
<li>Murano is not involved in policy rule evaluation, except that Murano provides data about Murano environments. Thus user can use any data (e.g., datasource tables, policy rules) available in Congress to define when environment can be deployed.</li>
</ul>
<p>Table <em>predeploy_error(env_id, obj_id, message)</em> reports list of found errors:</p>
<ul class="simple">
<li><em>env_id</em> environment id where error was detected</li>
<li><em>obj_id</em> object id (in environment id) on which error was detected</li>
<li><em>message</em> text message of error</li>
</ul>
<p>Murano environment serialization/decomposition is described in <a class="reference external" href="https://blueprints.launchpad.net/murano/+spec/congress-support-in-murano">Congress Support in Murano</a> and <a class="reference external" href="https://blueprints.launchpad.net/congress/+spec/murano-driver">Murano Congress Driver</a></p>
<p>Example (generic):</p>
<div class="highlight-python"><div class="highlight"><pre>predeploy_error(env_id, obj_id, message) :-
murano:state(env_id,"PENDING"),
my-rule-table1(env_id, obj_id),
concat("", "some error message 1", message)
predeploy_error(env_id, obj_id, message) :-
murano:state(env_id,"PENDING"),
my-rule-table2(env_id, obj_id),
concat("", "some error message 2", message)
my-rule-table1(env_id, obj_id) :- ....
my-rule-table2(env_id, obj_id) :- ....
</pre></div>
</div>
<p>Example (allow only environments where all VM instances has flavor with max 2048MB RAM):</p>
<div class="highlight-python"><div class="highlight"><pre>predeploy_error(eid, oid, msg) :-
murano:object(oid, eid, type),
checkIfError(oid),
concat("", "Instance flavor has RAM size over 2048MB", msg)
checkIfError(oid) :-
murano:parent_type(oid, "io.murano.resources.Instance"),
murano:property(oid, "flavor", fname),
nova:flavors(i,fname,v,r,d,e,rx),
gt(r,2048)
</pre></div>
</div>
<p>Enforcement point will use Congress simulation api to evaluate rules on passed mapped environment into Congress schema.</p>
</div>
<div class="section" id="proposed-change">
<h2>Proposed change</h2>
<p>When user executes <em>deploy</em> action on an environment following steps will be done</p>
<ul class="simple">
<li>environment will be mapped into <em>update sequence</em></li>
<li>Congress simulation API will be executed:</li>
</ul>
<div class="highlight-python"><div class="highlight"><pre>openstack congress policy simulate murano_system 'predeploy-error(envId, objId, message)' 'env+(1000,"myEnv") obj+(1,1000,"VM") prop+(100,1,"name", "vm1") prop+(101,1,"image", "ubuntulinuximg") obj+(2,1000,"Tomcat") prop+(110,2,"name", "tomcat") prop+(111,2,"port", 8080) rel+(200,2,1, "instance") ' action
</pre></div>
</div>
<ul class="simple">
<li>if response will contain non empty result, then deployment will fails</li>
</ul>
<div class="section" id="alternatives">
<h3>Alternatives</h3>
<p>None</p>
</div>
<div class="section" id="data-model-impact">
<h3>Data model impact</h3>
<p>None</p>
</div>
<div class="section" id="rest-api-impact">
<h3>REST API impact</h3>
<p>None</p>
</div>
<div class="section" id="versioning-impact">
<h3>Versioning impact</h3>
<p>None</p>
</div>
<div class="section" id="other-end-user-impact">
<h3>Other end user impact</h3>
<p>Environment deployment may fail due to policy validation failure.</p>
</div>
<div class="section" id="deployer-impact">
<h3>Deployer impact</h3>
<p>Policy enforcement will be used only if</p>
<ul class="simple">
<li>Enforcement is enabled in <em>murano.conf</em></li>
<li>Congress is available in Keystone catalog (i.e., it is deployed in OpenStack)</li>
</ul>
</div>
<div class="section" id="developer-impact">
<h3>Developer impact</h3>
<p>None</p>
</div>
<div class="section" id="murano-dashboard-horizon-impact">
<h3>Murano-dashboard / Horizon impact</h3>
<p>None</p>
</div>
</div>
<div class="section" id="implementation">
<h2>Implementation</h2>
<div class="section" id="assignee-s">
<h3>Assignee(s)</h3>
<dl class="docutils">
<dt>Primary assignee:</dt>
<dd>ondrej-vojta</dd>
<dt>Other contributors:</dt>
<dd>filip-blaha, radek-pospisil</dd>
</dl>
</div>
<div class="section" id="work-items">
<h3>Work Items</h3>
<ol class="arabic simple">
<li>Use implementation of <em>Congress Support in Murano</em> in order to implement policy enforcement point as advised by Stan (see below). The Congress support must correctly deal with following setups</li>
</ol>
<ul class="simple">
<li>Openstack with Congress installed</li>
<li>Openstack without Congress</li>
</ul>
<div class="highlight-python"><div class="highlight"><pre>Stan: such approach makes PolicyEnforces (and thus dependency on Congress) be mandatory for Murano. Better approach for now could be just insert
at https://github.com/stackforge/murano/blob/master/murano/common/engine.py#L112
something like
if config.CONF.enable_policy_enforcer:
policyenforcer.validate(self.model)
</pre></div>
</div>
<ol class="arabic simple" start="2">
<li>Provide Developer and User Documentation (see Documentation section).</li>
</ol>
</div>
</div>
<div class="section" id="dependencies">
<h2>Dependencies</h2>
<ul class="simple">
<li><em>Congress Support in Murano</em> <a class="reference external" href="https://blueprints.launchpad.net/congress/+spec/murano-driver">https://blueprints.launchpad.net/congress/+spec/murano-driver</a></li>
<li><em>Murano datasource driver</em> in Congress <a class="reference external" href="https://blueprints.launchpad.net/congress/+spec/murano-driver">https://blueprints.launchpad.net/congress/+spec/murano-driver</a></li>
<li><em>Policy enforcement specification</em> <a class="reference external" href="https://etherpad.openstack.org/p/policy-congress-murano-spec">https://etherpad.openstack.org/p/policy-congress-murano-spec</a></li>
</ul>
</div>
<div class="section" id="testing">
<h2>Testing</h2>
<p>Unit and integration tests must be done.</p>
<p>Integration tests must cover following setups</p>
<ul>
<li><dl class="first docutils">
<dt>Openstack has Congress installed</dt>
<dd><ul class="first last simple">
<li>situations when Congress is running (i.e., responding) and not running (i.e., not responding) must be tested</li>
</ul>
</dd>
</dl>
</li>
<li><p class="first">Openstack has not Congress installed</p>
</li>
</ul>
</div>
<div class="section" id="documentation-impact">
<h2>Documentation Impact</h2>
<p>Policy enforcement must be documented from following perspectives</p>
<ul class="simple">
<li>Setup configuration (e.g., with and without congress)</li>
<li>Murano rules (i.e., Murano environment data decompositiion) in Murano policy</li>
<li>How Murano policy affects environment deployment</li>
</ul>
<p>Following Murano documentation will be affected</p>
<ul>
<li><dl class="first docutils">
<dt>Murano Installation Guide</dt>
<dd><p class="first last">Add section on Congress requirement and section on enabling policy enforcement</p>
</dd>
</dl>
</li>
<li><dl class="first docutils">
<dt>Murano Workflow</dt>
<dd><p class="first last">Add section on Murano policy enforcement</p>
</dd>
</dl>
</li>
<li><dl class="first docutils">
<dt>Murano Article (new)</dt>
<dd><p class="first last">Article on Murano policy rules (e.g., Murano environment decomposition to Congress)</p>
</dd>
</dl>
</li>
</ul>
</div>
<div class="section" id="references">
<h2>References</h2>
<ul class="simple">
<li><em>Congress Support in Murano</em> <a class="reference external" href="https://blueprints.launchpad.net/congress/+spec/murano-driver">https://blueprints.launchpad.net/congress/+spec/murano-driver</a></li>
<li><em>Murano datasource driver</em> in Congress <a class="reference external" href="https://blueprints.launchpad.net/congress/+spec/murano-driver">https://blueprints.launchpad.net/congress/+spec/murano-driver</a></li>
<li><em>Policy enforcement specification</em> <a class="reference external" href="https://etherpad.openstack.org/p/policy-congress-murano-spec">https://etherpad.openstack.org/p/policy-congress-murano-spec</a></li>
</ul>
</div>
Tue, 17 Mar 2015 00:00:00 Policy Guided Fulfillment - Congress Support in Muranohttp://murano-specs.readthedocs.org/specs/kilo/congress-support.html
<p>URL of launchpad blueprint:</p>
<p><a class="reference external" href="https://blueprints.launchpad.net/murano/+spec/congress-support-in-murano">https://blueprints.launchpad.net/murano/+spec/congress-support-in-murano</a></p>
<div class="section" id="problem-description">
<h2>Problem description</h2>
<p>As a part of policy guided fulfillment we need to call Congress from Murano,
to enforce the policy on Murano environment. For current release
the enforcement will be done by Congress simulation API, where Murano will
query table <em>predeploy_error</em> in <em>murano_system</em> policy for passed update
sequence created by mapping of environment into congress schema.</p>
</div>
<div class="section" id="proposed-change">
<h2>Proposed change</h2>
<p>We need to provide</p>
<ul>
<li><p class="first">python congress client in Murano</p>
<blockquote>
<div><p>We will use simulation feature of <a class="reference external" href="https://docs.google.com/document/d/14hM7-GSm3CcyohPT2Q7GalyrQRohVcx77hxEx4AO4Bk/edit#heading=h.ll03wo2z9pcb">congress API</a>.
Using this API Murano will send decomposed Murano environment to Congress
tables, so simulation can evaluate <em>predeploy_error</em> rule without changing
existing data in Congress.</p>
</div></blockquote>
</li>
<li><p class="first">mapping of Murano Environment into <em>update sequence</em> used in simulation API</p>
</li>
</ul>
<div class="section" id="murano-to-congress-mapping-details">
<h3>Murano To Congress Mapping Details</h3>
<p>This section provides congress schema created for Murano environment mapping.
It will be created by Congress datasource drivers - see <a class="reference external" href="https://blueprints.launchpad.net/congress/+spec/murano-driver">murano driver spec</a> .</p>
<ul>
<li><p class="first"><strong>Policies</strong></p>
<blockquote>
<div><ul>
<li><p class="first"><strong>murano</strong></p>
<blockquote>
<div><p>Dedicated policy for Murano data.</p>
</div></blockquote>
</li>
<li><dl class="first docutils">
<dt><strong>murano_system</strong></dt>
<dd><p class="first last">Dedicated policy for rules</p>
</dd>
</dl>
</li>
</ul>
</div></blockquote>
</li>
<li><p class="first"><strong>Schema</strong></p>
<blockquote>
<div><ul>
<li><p class="first"><em>murano:objects(obj_id, owner_id, type)</em></p>
<p>This table holds every MuranoPL object instance in an environment.</p>
<blockquote>
<div><ul class="simple">
<li><em>obj_id</em> - uuid of the object as used in Murano</li>
<li><em>owner_id</em> - uuid of the owner object as used in Murano</li>
<li><em>type</em> - string with full type indentifier as used in Murano
(e.g., io.murano.Environment,...)</li>
</ul>
</div></blockquote>
</li>
<li><p class="first"><em>murano:parent_types(obj_id, parent_type)</em></p>
<p>This table holds parent types of <em>obj_id</em> object. Note that Murano
supports multiple inheritance, so there can be several parent types for
one object</p>
</li>
<li><p class="first"><em>murano:properties(obj_id, name, value)</em></p>
<blockquote>
<div><p>This table stores object’s properties. For multiple cardinality
properties, there can be number of records here. MuranoPL properties
referencing class type (i.e., another object) are stored in
<em>murano:relatinoship</em>. Properties with structured content will be
stored component by component.</p>
</div></blockquote>
</li>
<li><p class="first"><em>murano:relationships(src_id, trg_id, name)</em></p>
<blockquote>
<div><p>This table stores relationship between objects (i.e., MuranoPL property
to <em>class</em>). For multiple cardinality relationships several records
should be stored.</p>
</div></blockquote>
</li>
<li><p class="first"><em>murano:connected(src_id, trg_id)</em></p>
<blockquote>
<div><p>This table stores tuples of objects connected directly and indirectly
via relationship. It is necessary since Congress does not support
recursive rules yet.</p>
</div></blockquote>
</li>
<li><p class="first"><em>murano:states(end_id, state)</em></p>
<blockquote>
<div><p>This table stores <em>EnvironmentStatus</em> of Murano environment ( one of
‘ready’, ‘pending’, ‘deploying’, ‘deploy failure’, ‘deleting’,
‘delete failure’ ).</p>
</div></blockquote>
</li>
</ul>
</div></blockquote>
</li>
</ul>
</div>
<div class="section" id="alternatives">
<h3>Alternatives</h3>
<p>None</p>
</div>
<div class="section" id="data-model-impact">
<h3>Data model impact</h3>
<p>None</p>
</div>
<div class="section" id="rest-api-impact">
<h3>REST API impact</h3>
<p>None</p>
</div>
<div class="section" id="versioning-impact">
<h3>Versioning impact</h3>
<p>None</p>
</div>
<div class="section" id="other-end-user-impact">
<h3>Other end user impact</h3>
<p>None</p>
</div>
<div class="section" id="deployer-impact">
<h3>Deployer impact</h3>
<p>None</p>
</div>
<div class="section" id="developer-impact">
<h3>Developer impact</h3>
<p>None</p>
</div>
<div class="section" id="murano-dashboard-horizon-impact">
<h3>Murano-dashboard / Horizon impact</h3>
<p>None</p>
</div>
</div>
<div class="section" id="implementation">
<h2>Implementation</h2>
<div class="section" id="assignee-s">
<h3>Assignee(s)</h3>
<dl class="docutils">
<dt>Primary assignee:</dt>
<dd>filip-blaha</dd>
<dt>Other contributors:</dt>
<dd>ondrej-vojta, radek-pospisil</dd>
</dl>
</div>
<div class="section" id="work-items">
<h3>Work Items</h3>
<ol class="arabic simple">
<li>Introduce Congress python client into Murano</li>
<li>Implement mapping of Murano Environment into Congress simulation API
update-sequence.</li>
<li>Provide tests</li>
</ol>
</div>
</div>
<div class="section" id="dependencies">
<h2>Dependencies</h2>
<ul class="simple">
<li>Congress python client ( <a class="reference external" href="https://git.openstack.org/stackforge/python-congressclient">GIT</a> ) will be added into Murano.</li>
<li><em>Murano datasource driver</em> in Congress <a class="reference external" href="https://blueprints.launchpad.net/congress/+spec/murano-driver">murano driver spec</a></li>
</ul>
</div>
<div class="section" id="testing">
<h2>Testing</h2>
<p>Testing will use predefined Congress policy rules in order to test client and
mapping. See <a class="reference external" href="https://etherpad.openstack.org/p/policy-congress-murano-spec">https://etherpad.openstack.org/p/policy-congress-murano-spec</a> for
an example mapping and test.</p>
</div>
<div class="section" id="documentation-impact">
<h2>Documentation Impact</h2>
<p>Documentation impact is specified in <a class="reference external" href="https://blueprints.launchpad.net/murano/+spec/policy-enforcement-point">Policy Enforcement Point</a> blueprint.</p>
</div>
<div class="section" id="references">
<h2>References</h2>
<ul class="simple">
<li><em>Murano datasource driver</em> in Congress
<a class="reference external" href="https://blueprints.launchpad.net/congress/+spec/murano-driver">https://blueprints.launchpad.net/congress/+spec/murano-driver</a></li>
<li><a class="reference external" href="https://blueprints.launchpad.net/murano/+spec/policy-enforcement-point">https://blueprints.launchpad.net/murano/+spec/policy-enforcement-point</a></li>
<li><a class="reference external" href="https://etherpad.openstack.org/p/policy-congress-murano-spec">https://etherpad.openstack.org/p/policy-congress-murano-spec</a></li>
</ul>
</div>
Tue, 17 Mar 2015 00:00:00 Plugable pythonic classes for Muranohttp://murano-specs.readthedocs.org/specs/kilo/plugable-classes.html
<p><a class="reference external" href="https://blueprints.launchpad.net/murano/+spec/plugable-classes">https://blueprints.launchpad.net/murano/+spec/plugable-classes</a></p>
<p>One of the key features of Murano is extensibility, and we need to push this
feature even further and give our customers a way to extend Murano with new
functions (e.g. support for F5 BigIP API) in a drag-n-drop manner. This spec
proposes a solution which will add this extensibility option.</p>
<div class="section" id="problem-description">
<h2>Problem description</h2>
<p>Currently all the functionality which is available to user is limited to the
features of MuranoPL language which just provides data transformation
capabilities and flow control primitives. The language itself does not contain
any functions for I/O operations, hardware access or interaction with host
operating system, other OpenStack or third-party services. This is an
intentional design feature: MuranoPL code is provided by users and cannot be
always trusted. All the external communications and low-level interactions are
done via python code which is bundled with Murano Engine and is accessible to
MuranoPL code via MuranoPL wrappers. Any interactions which are not supported
by that Python classes are impossible.</p>
<p>Some deployment scenarios may need to extend this set of allowed low-level
interactions. They may include some customer-specific logic, custom software
bindings etc, so trying to bundle all of them into the standard Murano Engine
classes is not a good idea. Instead, there should be a way to dynamically
add extra interactions to any existing deployment of Murano without modifying
its core components but rather with installing some plugin-like components.</p>
<p>Installing these plugins is supposed to be a maintainer-only operation,
requiring administrative access to nodes running Murano services. It is
supposed that the maintainer is always aware about the contents of the plugins
and is able to verify them from security, performance and other sensible points
of view.</p>
</div>
<div class="section" id="proposed-change">
<h2>Proposed change</h2>
<p>It is proposed to implement each extension as independent Python Package built
using setuptools library. Each package should define one or more entry-point in
a specific namespace (<tt class="docutils literal"><span class="pre">io.murano.extensions</span></tt> is suggested). Each of this
entry- points should export a class, which may be registered as MuranoPL class
when the engine loads.</p>
<p>Each package should be installed on Murano nodes into the same Python
environment with Murano engine service.</p>
<p>Murano will get a PluginLoader class which will utilize stevedore library [1]
to discover classes registered as entry-points in <tt class="docutils literal"><span class="pre">io.murano.extensions</span></tt>
namespace.</p>
<p>Murano Engine will use PluginLoader to register all the loaded plugins in its
class loader (i.e. will call <tt class="docutils literal"><span class="pre">import_class</span></tt> with a class imported from the
plugin as a parameter). As the result, the classes will become available for
the MuranoPL code being executed in the Engine.</p>
<p>To prevent potential name collisions, MuranoPL names for the loaded classes
will be assigned automatically: the name will consist of the namespace
(<tt class="docutils literal"><span class="pre">io.murano.extensions</span></tt> as suggested above) and the name of entry-point.
To guarantee this naming rule the imported classes should not define their
MuranoPL names on their own (i.e they should not have
<tt class="docutils literal"><span class="pre">@murano_class.classname</span></tt> decorators or other code which modifies their
<tt class="docutils literal"><span class="pre">_murano_class_name</span></tt> field). If they do, the PluginLoader will discard
that information and will log a warning message.</p>
<p>As the entry-point name will eventually become a name of MuranoPL class, the
PluginLoader will validate it accordingly.</p>
<p>As neither stevedore nor setuptools enforce any uniqueness constraints on the
entry-point names (i.e. several packages may define entry-points with the same
name within a same namespace, and all of them will be correctly loaded by
stevedore), then this enforcement should also be done by the Murano’s Plugin
Loader. If two or more plugin packages attempt to register classes with the
same endpoint name, then a warning will be logged and no classes from all the
conflicting packages will be loaded.</p>
<p>PluginLoader will also ensure that objects being exported in these entry-points
are indeed classes, and will check if they define a classmethod called
<tt class="docutils literal"><span class="pre">init_plugin</span></tt>. If such method exists, the PluginLoader will execute it before
loading it.</p>
<p>The plugins which are already installed in the environment may be prevented
from being loaded by a configuration option. This new option called
<tt class="docutils literal"><span class="pre">enabled_plugins</span></tt> will be added to <tt class="docutils literal"><span class="pre">murano.conf</span></tt>. If it has its default
value <tt class="docutils literal"><span class="pre">None</span></tt> or is omitted from the config, there will be no restriction on
the plugins which are being loaded (any plugin registered within the
environment will be loaded). If it exists and is not None, then it is expected
to contain a list of names of the packages from which the plugins will be
loaded. If the package is not mentioned there, all its endpoints will be
ignored and no classes from it will be imported. Empty value of
<tt class="docutils literal"><span class="pre">enabled_plugins</span></tt> will mean that no plugins may be loaded and only bundled
system classes are accessible from the MuranoPL code.</p>
<p>The <tt class="docutils literal"><span class="pre">enabled_plugins</span></tt> setting will be implemented using
<tt class="docutils literal"><span class="pre">EnabledExtensionManager</span></tt> class of the stevedore library [2], so the disabled
plugins will be excluded from entry-point name analysis. Thus if there are
plugins which define conflicting entry-point names, then the conflict may be
resolved with this setting instead of uninstalling the plugin from the
environment.</p>
<p>Currently stevedore is unable to load packages which were installed after the
start of the current process. So, in current proposal it is required to restart
Murano services after plugin package is installed, removed or upgraded and
after the changing of <tt class="docutils literal"><span class="pre">enabled_plugins</span></tt> value in configuration file.
As the restart of the services is not a good thing for production solutions, it
may be a good idea to design a “graceful restart” solution which will make the
service to stop listening for incoming requests, finish its current tasks and
then exit and restart, loading the updated configuration and plugins. However
such solution is out of scope of the current spec and is left for future
blueprints.</p>
<div class="section" id="alternatives">
<h3>Alternatives</h3>
<p>Instead of using stevedore to discover and load the plugins, some home-made
solution may be invented to load Python modules from some directory. This
solution may have its benefits (e.g. it does not require restarts to load new
plugins), however stevedore is currently a de-facto standard for building
plugable solutions in Openstack, so it is suggested to use it.</p>
</div>
<div class="section" id="data-model-impact">
<h3>Data model impact</h3>
<p>This proposal does not affect data model.</p>
</div>
<div class="section" id="rest-api-impact">
<h3>REST API impact</h3>
<p>N/A</p>
</div>
<div class="section" id="versioning-impact">
<h3>Versioning impact</h3>
<p>N/A</p>
</div>
<div class="section" id="other-end-user-impact">
<h3>Other end user impact</h3>
<p>N/A</p>
</div>
<div class="section" id="deployer-impact">
<h3>Deployer impact</h3>
<p>The change itself does not have any immediate impact on deployer: a new
configuration option is optional and has meaningful default. However
registering new plugins will require to restart the Services, which may bring
up some concerns in production environments.</p>
</div>
<div class="section" id="developer-impact">
<h3>Developer impact</h3>
<p>Developers who build their own plugins should be aware about setuptools entry-
points and should inherit their exported classes from
<cite>murano.dsl.murano_object.MuranoObject</cite>.</p>
</div>
<div class="section" id="murano-dashboard-horizon-impact">
<h3>Murano-dashboard / Horizon impact</h3>
<p>No immediate changes required.</p>
</div>
</div>
<div class="section" id="implementation">
<h2>Implementation</h2>
<div class="section" id="assignee-s">
<h3>Assignee(s)</h3>
<dl class="docutils">
<dt>Primary assignee:</dt>
<dd>ativelkov</dd>
</dl>
</div>
<div class="section" id="work-items">
<h3>Work Items</h3>
<ul class="simple">
<li>Implement the PluginLoader class</li>
<li>Modify MuranoEngine to register plugin-imported classes in class loader.</li>
</ul>
</div>
</div>
<div class="section" id="dependencies">
<h2>Dependencies</h2>
<p>This requires stevedore library as a dependency. It is already part of
OpenStack Global Requirements, so no problems are expected.</p>
</div>
<div class="section" id="testing">
<h2>Testing</h2>
<p>The unit-tests have to cover PluginLoader class using the make_test_instance
method of stevedore.</p>
<p>Separated tests should cover API method call.</p>
<p>Tempest tests are out of the scope of this spec.</p>
</div>
<div class="section" id="documentation-impact">
<h2>Documentation Impact</h2>
<p>There should be created a “Plugin developer’s Manual” which will describe the
process of plugin package creation.</p>
</div>
<div class="section" id="references">
<h2>References</h2>
<p>[1] <a class="reference external" href="http://docs.openstack.org/developer/stevedore/">http://docs.openstack.org/developer/stevedore/</a>
[2] <a class="reference external" href="http://docs.openstack.org/developer/stevedore/managers.html#enabledextensionmanager">http://docs.openstack.org/developer/stevedore/managers.html#enabledextensionmanager</a></p>
</div>
Wed, 04 Mar 2015 00:00:00 Configuration Language Supporthttp://murano-specs.readthedocs.org/specs/kilo/conf-language-support.html
<p><a class="reference external" href="https://blueprints.launchpad.net/murano/+spec/conf-language-support">https://blueprints.launchpad.net/murano/+spec/conf-language-support</a></p>
<div class="section" id="problem-description">
<h2>Problem description</h2>
<p>There is a huge community of applications (opscode, puppet-labs) where
deployment installation instructions are specified in configuration
languages such as Puppet or Chef. In order to reuse these applications,
adaptors like Chef or Puppet are required on the VM side. Both chef and
puppet recipes will not be managed by centralized server (chef-server,
puppet-master), but they will use the standalone version, specifically
the usage of chef-solo and puppet apply.</p>
</div>
<div class="section" id="proposed-change">
<h2>Proposed change</h2>
<p>Inclusion of new executors in the murano-agent project. These executors
will be objects to be used by murano-agent. Specifically, two executors
will be implemented: Puppet and Chef. Both executors will be in charge of:</p>
<ul class="simple">
<li>Obtaining the required modules or cookbooks in the virtual machine.</li>
</ul>
<p>This task can be done by passing the information from murano-engine to
murano-agent, obtaining the information from the package itself. It requires
the user to upload the package information plus the cookbooks to be used.
The second option implies the cookbooks are downloaded in the virtual
machine, so that they only need the URL to be accessible.</p>
<ul class="simple">
<li>Generating the required files for the configuration language.</li>
</ul>
<p>For instance, manifests and hiera data for puppet, and, node
specifications for chef from the information stored in the
execution plan.</p>
<ul class="simple">
<li>Executing the chef-solo or puppet-apply process.</li>
</ul>
<p>Previously, some work has to be done to install Chef or Puppet inside the VM.
This task can be done by using cloud-init from the murano engine. The
following is an example on how these executors work:</p>
<div class="highlight-python"><div class="highlight"><pre>## YAML Template.
---
FormatVersion: 2.0.0
Version: 1.0.0
Name: Deploy Tomcat
Parameters:
port: $port
Body: |
return deployTomcat(port=args.port).stdout
Scripts:
deployTomcat:
Type: Chef
Version: 1.0.0
EntryPoint: mycoockbook::myrecipe
Files:
tomcat:
Name: tomcat
URL: git://github.com/opscode-cookbooks/tomcat.git
Type: Downloadable
java:
Name: java
URL: git://github.com/opscode-cookbooks/java.git
Type: Downloadable
ssl:
Name: openssl
URL: https://github.com/opscode-cookbooks/ssl.git
Type: Downloadable
Options:
captureStdout: true
captureStderr: true
</pre></div>
</div>
<p>In this case, a new script Type appears (instead of Application). It is
Chef type, which will execute the Chef executor. The same happens with
the Puppet Type. In addition, the EntryPoint contains the information
about the cookbook and the recipe to be installed. The Files section
is used for the cookbooks and its dependence information. The cookbooks
properties are in the Parameter section.</p>
<p>All the required steps to be part of the executor can be summarized as follows.</p>
<p>For Chef,</p>
<ol class="arabic">
<li><p class="first">Creating the node.json with the recipes and the configuration parameters:</p>
<div class="highlight-python"><div class="highlight"><pre>{
orion::ports: 1026
orion::dbname: oriondb
"run_list": [
"recipe[orion::0.13.0_install]"
]
}
</pre></div>
</div>
</li>
<li><dl class="first docutils">
<dt>Executing chef-solo:</dt>
<dd><p class="first last">chef-solo -j node.json</p>
</dd>
</dl>
</li>
</ol>
<p>For puppet,</p>
<ol class="arabic">
<li><p class="first">Generating the manifest (site.pp):</p>
<div class="highlight-python"><div class="highlight"><pre>node 'default'
{
class{
'orion::install':
}
}
</pre></div>
</div>
</li>
<li><p class="first">Creating the hiera data information: hiera.yaml:</p>
<div class="highlight-python"><div class="highlight"><pre>## YAML Template.
---
orion::port: 1026
orion::dbname: oriondb
</pre></div>
</div>
</li>
<li><dl class="first docutils">
<dt>Executing:</dt>
<dd><p class="first last">puppet apply –hiera_config=hiera.yaml –modulepath=/opt/puppet/modules/orion site.pp</p>
</dd>
</dl>
</li>
</ol>
<div class="section" id="alternatives">
<h3>Alternatives</h3>
<p>None</p>
</div>
<div class="section" id="data-model-impact">
<h3>Data model impact</h3>
<p>None</p>
</div>
<div class="section" id="rest-api-impact">
<h3>REST API impact</h3>
<p>None</p>
</div>
<div class="section" id="versioning-impact">
<h3>Versioning impact</h3>
<p>None</p>
</div>
<div class="section" id="other-end-user-impact">
<h3>Other end user impact</h3>
<p>None</p>
</div>
<div class="section" id="deployer-impact">
<h3>Deployer impact</h3>
<p>The solution proposed is valid for any VM which contains the configuration
language implementation already installed. There are event chef-solo and
puppet agents for Windows.</p>
</div>
<div class="section" id="developer-impact">
<h3>Developer impact</h3>
<p>None</p>
</div>
<div class="section" id="murano-dashboard-horizon-impact">
<h3>Murano-dashboard / Horizon impact</h3>
<p>None</p>
</div>
</div>
<div class="section" id="implementation">
<h2>Implementation</h2>
<div class="section" id="assignee-s">
<h3>Assignee(s)</h3>
<dl class="docutils">
<dt>Primary assignee:</dt>
<dd>hmunfru</dd>
<dt>Other contributors:</dt>
<dd>jesuspg</dd>
</dl>
</div>
<div class="section" id="work-items">
<h3>Work Items</h3>
<ol class="arabic simple">
<li>Generate Chef executor</li>
<li>Generate Puppet executor</li>
<li>Work on configuration</li>
</ol>
</div>
</div>
<div class="section" id="dependencies">
<h2>Dependencies</h2>
<p>None</p>
</div>
<div class="section" id="testing">
<h2>Testing</h2>
<p>Integration tests will be done</p>
</div>
<div class="section" id="documentation-impact">
<h2>Documentation Impact</h2>
<p>Information about how to defines application for Puppet and Chef will have
to be documented, explaining the different fields.</p>
</div>
<div class="section" id="references">
<h2>References</h2>
<ul class="simple">
<li><a class="reference external" href="http://es.slideshare.net/hmunfru/fiware-and-murano-support-for-configuration-languages">http://es.slideshare.net/hmunfru/fiware-and-murano-support-for-configuration-languages</a></li>
<li><a class="reference external" href="https://etherpad.openstack.org/p/conf-language-support-spec">https://etherpad.openstack.org/p/conf-language-support-spec</a></li>
</ul>
</div>
Tue, 13 Jan 2015 00:00:00 Provide opportunity to manage application categorieshttp://murano-specs.readthedocs.org/specs/kilo/enable-category-management.html
<p><a class="reference external" href="https://blueprints.launchpad.net/murano/+spec/enable-category-management">https://blueprints.launchpad.net/murano/+spec/enable-category-management</a></p>
<p>Murano is an application catalog, where new applications can be easily added.
Those applications may belong to a category, that is not on predefined list.</p>
<p>Also, some categories may not be needed, and user can delete such kind
of categories.
All operations should be available only for admin users.</p>
<div class="section" id="problem-description">
<h2>Problem description</h2>
<p>Category management should be provided during:</p>
<blockquote>
<div><ul class="simple">
<li>Packages uploading in dashboard;</li>
<li>Packages modifying in dashboard;</li>
<li>Packages uploading or modifying via command line;</li>
</ul>
</div></blockquote>
<p>Adding new category:</p>
<blockquote>
<div><ul class="simple">
<li>Category name may contain spaces and other special characters;</li>
<li>Category name limit is equal to 80 characters;</li>
<li>Only admin users can add new category;</li>
</ul>
</div></blockquote>
<p>Deleting category:</p>
<blockquote>
<div><ul class="simple">
<li>Category may be deleted only if no packages belong to this category;</li>
<li>Only admin users can delete category;</li>
</ul>
</div></blockquote>
</div>
<div class="section" id="proposed-change">
<h2>Proposed change</h2>
<p>Changes required to support this feature:</p>
<blockquote>
<div><ul class="simple">
<li>Add new panel named ‘Categories’ under ‘Manage’ section;
It should be available only for admin users.
This panel should represent table with categories.
The table will contain ‘name’ column and ‘assigned packages’ column.
“Add category” will be a table action and “Delete Category” will be
row action.
Delete button should be hidden for those categories connected to
the packages.</li>
<li>Provide corresponding methods in the python-muranoclient;
Category manager will be added to v1 module;</li>
</ul>
</div></blockquote>
<div class="section" id="alternatives">
<h3>Alternatives</h3>
<p>Admin can edit a database to add or delete categories.</p>
</div>
<div class="section" id="data-model-impact">
<h3>Data model impact</h3>
<p>None</p>
</div>
<div class="section" id="rest-api-impact">
<h3>REST API impact</h3>
<p><strong>GET /catalog/categories</strong></p>
<p>The previous call /catalog/packages/categories is will still be valid to
support backward compatibility.</p>
<p><em>Request</em></p>
<table border="1" class="docutils">
<colgroup>
<col width="13%"/>
<col width="44%"/>
<col width="44%"/>
</colgroup>
<thead valign="bottom">
<tr class="row-odd"><th class="head">Method</th>
<th class="head">URI</th>
<th class="head">Description</th>
</tr>
</thead>
<tbody valign="top">
<tr class="row-even"><td>Get</td>
<td>/catalog/categories</td>
<td>Get list of existing categories</td>
</tr>
</tbody>
</table>
<p><em>Response</em></p>
<div class="highlight-python"><div class="highlight"><pre>{"categories": [
"id": "3dd486b1e26f40ac8f35416b63f52042",
"updated": "2014-12-26T13:57:04",
"name": "Web",
"created": "2014-12-26T13:57:04",
"package_count": 0
},
{
"id": "k67gf67654f095gf89hjj87y56g98965v",
"updated": "2014-12-26T13:57:04",
"name": "Databases",
"created": "2014-12-26T13:57:04",
"package_count": 0
}]
}
</pre></div>
</div>
<p><strong>GET /catalog/categories/<category_id></strong></p>
<p><em>Request</em></p>
<table border="1" class="docutils">
<colgroup>
<col width="13%"/>
<col width="44%"/>
<col width="43%"/>
</colgroup>
<thead valign="bottom">
<tr class="row-odd"><th class="head">Method</th>
<th class="head">URI</th>
<th class="head">Description</th>
</tr>
</thead>
<tbody valign="top">
<tr class="row-even"><td>Get</td>
<td>/catalog/categories/<category_id></td>
<td>Get category detail</td>
</tr>
</tbody>
</table>
<p><em>Parameters</em></p>
<ul class="simple">
<li><cite>category_id</cite> - category ID, required</li>
</ul>
<p><em>Response</em></p>
<div class="highlight-python"><div class="highlight"><pre><span class="p">{</span>
<span class="s">"id"</span><span class="p">:</span> <span class="s">"0420045dce7445fabae7e5e61fff9e2f"</span><span class="p">,</span>
<span class="s">"updated"</span><span class="p">:</span> <span class="s">"2014-12-26T13:57:04"</span><span class="p">,</span>
<span class="s">"packages"</span><span class="p">:</span> <span class="p">[</span>
<span class="s">"Apache HTTP Server"</span><span class="p">,</span>
<span class="s">"Apache Tomcat"</span><span class="p">,</span>
<span class="s">"PostgreSQL"</span>
<span class="p">],</span>
<span class="s">"name"</span><span class="p">:</span> <span class="s">"Web"</span><span class="p">,</span>
<span class="s">"created"</span><span class="p">:</span> <span class="s">"2014-12-26T13:57:04"</span>
<span class="p">}</span>
</pre></div>
</div>
<table border="1" class="docutils">
<colgroup>
<col width="21%"/>
<col width="79%"/>
</colgroup>
<thead valign="bottom">
<tr class="row-odd"><th class="head">Code</th>
<th class="head">Description</th>
</tr>
</thead>
<tbody valign="top">
<tr class="row-even"><td>200</td>
<td>OK. Category retrieved successfully</td>
</tr>
<tr class="row-odd"><td>401</td>
<td>User is not authorized to access this session</td>
</tr>
<tr class="row-even"><td>404</td>
<td>Not found. Specified category doesn`t exist</td>
</tr>
</tbody>
</table>
<p><strong>POST /catalog/categories</strong></p>
<table border="1" class="docutils">
<colgroup>
<col width="24%"/>
<col width="13%"/>
<col width="62%"/>
</colgroup>
<thead valign="bottom">
<tr class="row-odd"><th class="head">Attribute</th>
<th class="head">Type</th>
<th class="head">Description</th>
</tr>
</thead>
<tbody valign="top">
<tr class="row-even"><td>name</td>
<td>string</td>
<td>Category name</td>
</tr>
</tbody>
</table>
<p><em>Request</em></p>
<table border="1" class="docutils">
<colgroup>
<col width="13%"/>
<col width="44%"/>
<col width="44%"/>
</colgroup>
<thead valign="bottom">
<tr class="row-odd"><th class="head">Method</th>
<th class="head">URI</th>
<th class="head">Description</th>
</tr>
</thead>
<tbody valign="top">
<tr class="row-even"><td>POST</td>
<td>/catalog/categories</td>
<td>Create new category</td>
</tr>
</tbody>
</table>
<dl class="docutils">
<dt><em>Content-Type</em></dt>
<dd>application/json</dd>
<dt><em>Example</em></dt>
<dd>{“name”: “category_name”}</dd>
</dl>
<p><em>Response</em></p>
<div class="highlight-python"><div class="highlight"><pre><span class="p">{</span>
<span class="s">"id"</span><span class="p">:</span> <span class="s">"ce373a477f211e187a55404a662f968"</span><span class="p">,</span>
<span class="s">"name"</span><span class="p">:</span> <span class="s">"category_name"</span><span class="p">,</span>
<span class="s">"created"</span><span class="p">:</span> <span class="s">"2013-11-30T03:23:42Z"</span><span class="p">,</span>
<span class="s">"updated"</span><span class="p">:</span> <span class="s">"2013-11-30T03:23:44Z"</span><span class="p">,</span>
<span class="p">}</span>
</pre></div>
</div>
<table border="1" class="docutils">
<colgroup>
<col width="21%"/>
<col width="79%"/>
</colgroup>
<thead valign="bottom">
<tr class="row-odd"><th class="head">Code</th>
<th class="head">Description</th>
</tr>
</thead>
<tbody valign="top">
<tr class="row-even"><td>200</td>
<td>OK. Category created successfully</td>
</tr>
<tr class="row-odd"><td>401</td>
<td>User is not authorized to access this session</td>
</tr>
<tr class="row-even"><td>403</td>
<td>Forbidden. Category with specified name already exist</td>
</tr>
</tbody>
</table>
<p><strong>DELETE /catalog/categories</strong></p>
<p><em>Request</em></p>
<table border="1" class="docutils">
<colgroup>
<col width="13%"/>
<col width="44%"/>
<col width="44%"/>
</colgroup>
<thead valign="bottom">
<tr class="row-odd"><th class="head">Method</th>
<th class="head">URI</th>
<th class="head">Description</th>
</tr>
</thead>
<tbody valign="top">
<tr class="row-even"><td>DELETE</td>
<td>/catalog/categories/<category_id></td>
<td>Delete category with specified id</td>
</tr>
</tbody>
</table>
<p><em>Parameters:</em></p>
<ul class="simple">
<li><cite>category_id</cite> - category ID, required</li>
</ul>
<p><em>Response</em></p>
<table border="1" class="docutils">
<colgroup>
<col width="21%"/>
<col width="79%"/>
</colgroup>
<thead valign="bottom">
<tr class="row-odd"><th class="head">Code</th>
<th class="head">Description</th>
</tr>
</thead>
<tbody valign="top">
<tr class="row-even"><td>200</td>
<td>OK. Category deleted successfully</td>
</tr>
<tr class="row-odd"><td>401</td>
<td>User is not authorized to access this session</td>
</tr>
<tr class="row-even"><td>404</td>
<td>Not found. Specified category doesn`t exist</td>
</tr>
<tr class="row-odd"><td>403</td>
<td>Forbidden. Category with specified name is assigned to
the package, presented in the catalog. Only empty
categories can be removed</td>
</tr>
</tbody>
</table>
</div>
<div class="section" id="versioning-impact">
<h3>Versioning impact</h3>
<p>Murano dashboard will support only the version of the client, that includes
corresponding changes in the client. ‘Categories’ panel will not work
with the old murano version, but application catalog and package management
will work fine.</p>
</div>
<div class="section" id="other-end-user-impact">
<h3>Other end user impact</h3>
<p>None</p>
</div>
<div class="section" id="murano-dashboard-horizon-impact">
<h3>Murano-dashboard / Horizon impact</h3>
<p>Category management will be available in dashboard.
Areas to be changed: (described in sections above)</p>
<ul class="simple">
<li>Manage section will have new panel;</li>
</ul>
</div>
<div class="section" id="deployer-impact">
<h3>Deployer impact</h3>
<p>None</p>
</div>
<div class="section" id="developer-impact">
<h3>Developer impact</h3>
<p>None</p>
</div>
</div>
<div class="section" id="implementation">
<h2>Implementation</h2>
<div class="section" id="assignee-s">
<h3>Assignee(s)</h3>
<p>Ekaterina Chernova</p>
<dl class="docutils">
<dt>Primary assignee:</dt>
<dd><<a class="reference external" href="mailto:efedorova%40mirantis.com">efedorova<span>@</span>mirantis<span>.</span>com</a>></dd>
</dl>
</div>
<div class="section" id="work-items">
<h3>Work Items</h3>
<ul class="simple">
<li>Introduce 2 additional calls in API</li>
<li>Update API specification</li>
<li>Provide these calls in python-muranoclient</li>
<li>Implement changes in dashboard</li>
<li>Enable CLI to manage categories</li>
</ul>
</div>
</div>
<div class="section" id="dependencies">
<h2>Dependencies</h2>
<p>None</p>
</div>
<div class="section" id="testing">
<h2>Testing</h2>
<p>New tests should be added in dashboard integration tests</p>
</div>
<div class="section" id="documentation-impact">
<h2>Documentation Impact</h2>
<p>API specification should be updated.
All changes are already represented here, just need to copy.</p>
</div>
<div class="section" id="references">
<h2>References</h2>
<p>None</p>
</div>
Fri, 05 Dec 2014 00:00:00 murano-mistral-integrationhttp://murano-specs.readthedocs.org/specs/kilo/murano-mistral-integration-1.html
<p><a class="reference external" href="https://blueprints.launchpad.net/murano/+spec/murano-mistral-integration-1">https://blueprints.launchpad.net/murano/+spec/murano-mistral-integration-1</a></p>
<p>The purpose is to add integration between Murano and Mistral.
We would like to allow invocation of a Mistral workflow from Murano.
No prerequisite for uploaded Mistral workflow.</p>
<div class="section" id="problem-description">
<h2>Problem description</h2>
<p>A new capability in Murano modeling process should be added in order to answer
several use cases, including:</p>
<ol class="arabic">
<li><p class="first">The application modeler wishes to leverage existing workflow that deploys
a specific component as part of a new application model creation process.</p>
</li>
<li><p class="first">The application modeler wishes to add post-deployment logic to an
application model.</p>
<p>For example:</p>
<ol class="loweralpha simple">
<li>Check that the application has been successfully deployed.</li>
<li>Inject initial data to the deployed application.</li>
</ol>
</li>
</ol>
</div>
<div class="section" id="proposed-change">
<h2>Proposed change</h2>
<p>Adding a new system class for Mistral Client that allows to call Mistral
APIs from the Murano application model.</p>
<p>The system class will allow you to:</p>
<ol class="arabic simple">
<li>Upload a Mistral workflow to Mistral.</li>
<li>Trigger the already-deployed Mistral workflow, wait for completion and
return the execution output.</li>
</ol>
<div class="section" id="alternatives">
<h3>Alternatives</h3>
<p>None</p>
</div>
<div class="section" id="data-model-impact">
<h3>Data model impact</h3>
<p>None</p>
</div>
<div class="section" id="rest-api-impact">
<h3>REST API impact</h3>
<p>None</p>
</div>
<div class="section" id="versioning-impact">
<h3>Versioning impact</h3>
<p>None</p>
</div>
<div class="section" id="other-end-user-impact">
<h3>Other end user impact</h3>
<p>None</p>
</div>
<div class="section" id="deployer-impact">
<h3>Deployer impact</h3>
<p>None</p>
</div>
<div class="section" id="developer-impact">
<h3>Developer impact</h3>
<p>None</p>
</div>
<div class="section" id="murano-dashboard-horizon-impact">
<h3>Murano-dashboard / Horizon impact</h3>
<p>None</p>
</div>
</div>
<div class="section" id="implementation">
<h2>Implementation</h2>
<div class="section" id="assignee-s">
<h3>Assignee(s)</h3>
<p>Primary assignee:
Natasha Beck</p>
</div>
<div class="section" id="work-items">
<h3>Work Items</h3>
<ol class="arabic simple">
<li>Add mistral client system class that can trigger pre-deployed Mistral
workflow.</li>
<li>Add ability to the client to upload the Mistral workflow.</li>
<li>Add test that deploys application which uploads the Mistral workflow from
Resources, triggers it and gets output as a result.</li>
</ol>
</div>
</div>
<div class="section" id="dependencies">
<h2>Dependencies</h2>
<p>Openstack Mistral component.</p>
</div>
<div class="section" id="testing">
<h2>Testing</h2>
<p>Functional test will be added to Murano.
The test deploys application which uploads the Mistral workflow from
Resources, triggers it and gets output as a result.</p>
</div>
<div class="section" id="documentation-impact">
<h2>Documentation Impact</h2>
<p>Murano-Mistral integration must be documented from the following perspectives:</p>
<ul class="simple">
<li>Setup configuration (for example with and without mistral)</li>
<li>Include usage of Mistral workflow as a part of an application model</li>
</ul>
<p>The following Murano documentation will be affected:</p>
<ul>
<li><dl class="first docutils">
<dt>Murano Installation Guide</dt>
<dd><p class="first last">Add section on Mistral requirement</p>
</dd>
</dl>
</li>
<li><dl class="first docutils">
<dt>Murano Workflow</dt>
<dd><p class="first last">Add section on Murano-Mistral integration</p>
</dd>
</dl>
</li>
<li><dl class="first docutils">
<dt>Murano Article (new)</dt>
<dd><p class="first last">Article on Murano-Mistral integration</p>
</dd>
</dl>
</li>
</ul>
</div>
<div class="section" id="references">
<h2>References</h2>
<p>None</p>
</div>
Fri, 05 Dec 2014 00:00:00 Remove name field from fields and object model in dynamic UIhttp://murano-specs.readthedocs.org/specs/liberty/dynamic-ui-specify-no-explicit-name-field.html
<p><a class="reference external" href="https://blueprints.launchpad.net/murano/+spec/dynamic-ui-specify-no-explicit-name-field">https://blueprints.launchpad.net/murano/+spec/dynamic-ui-specify-no-explicit-name-field</a></p>
<p>Now name is a required parameter in every single form definition.
But murano-engine doesn’t know anything about this parameter. It mostly used
for dymanic UI purposes. So we can insert this field automatically in every
form.</p>
<div class="section" id="problem-description">
<h2>Problem description</h2>
<ul>
<li><p class="first">‘name’ property has no built-in predefined meaning for MuranoPL classes
or applications.</p>
<p>Now all unknown parameters are ignored, but the error will be spawned and
all applications will be invalid in the near future.
To prevent global failure this change is suggested.</p>
</li>
</ul>
</div>
<div class="section" id="proposed-change">
<h2>Proposed change</h2>
<p>Add automatic field inserting into the first form and store ‘name’ field value
in object header:</p>
<ul class="simple">
<li>Dynamic UI version will be increased to 2.1;</li>
<li>‘name’ property is not required in MuranoPL class definition anymore.
If user still have ‘name’ property in class definition, he should supply
corresponding field in UI definition. It will have no special meaning for
murano dashboard.</li>
<li>New field will be inserted to the first form if Dymanic UI version is higher
or equal to 2.1;</li>
<li>If Dymanic UI version is higher or equal to 2.1 ‘name’ field value will be
placed to the object header (‘?’), in “done” method of application creation
wizard;</li>
<li>In get-mode, application ‘name’ parameter will be checked in:<ul>
<li>Primary under ‘?’ parameter;</li>
<li>Secondary in the object model root;</li>
</ul>
</li>
<li>Add new YAQL function to dashboard’s YAQL to be used by dynamic UI.
The function will be called ‘name’ and will allow to use
automatically-inserted name field in object model description.</li>
</ul>
<div class="section" id="alternatives">
<h3>Alternatives</h3>
<p>None</p>
</div>
<div class="section" id="data-model-impact">
<h3>Data model impact</h3>
<p>None</p>
</div>
<div class="section" id="rest-api-impact">
<h3>REST API impact</h3>
<p>None</p>
</div>
<div class="section" id="versioning-impact">
<h3>Versioning impact</h3>
<p>This change introduces new version of dynamic UI form definition.
Only backward compatibility will be supported: new dashboard can work with old engine.</p>
</div>
<div class="section" id="other-end-user-impact">
<h3>Other end user impact</h3>
<p>None</p>
</div>
<div class="section" id="deployer-impact">
<h3>Deployer impact</h3>
<p>None</p>
</div>
<div class="section" id="developer-impact">
<h3>Developer impact</h3>
<p>None</p>
</div>
<div class="section" id="murano-dashboard-horizon-impact">
<h3>Murano-dashboard / Horizon impact</h3>
<p>This spec is supposed to be implemented in murano-dashboard only.
User will see new field for adding app name.</p>
</div>
</div>
<div class="section" id="implementation">
<h2>Implementation</h2>
<div class="section" id="assignee-s">
<h3>Assignee(s)</h3>
<dl class="docutils">
<dt>Primary assignee:</dt>
<dd><<a class="reference external" href="mailto:efedorova%40mirantis.com">efedorova<span>@</span>mirantis<span>.</span>com</a>></dd>
</dl>
</div>
<div class="section" id="work-items">
<h3>Work Items</h3>
<ul class="simple">
<li>Implement automatic ‘name’ field insertion if version satisfies the requirements;</li>
<li>Put ‘name’ field value to the object header area;</li>
<li>Use ‘name’ attribute from object header or inside object modal root
in environments table;</li>
<li>Implement new YAQL function, which returns applications name.</li>
</ul>
</div>
</div>
<div class="section" id="dependencies">
<h2>Dependencies</h2>
<p>This change is a dependency for a future changes in engine</p>
</div>
<div class="section" id="testing">
<h2>Testing</h2>
<p>CI tests should be updated and catch all errors.</p>
</div>
<div class="section" id="documentation-impact">
<h2>Documentation Impact</h2>
<p>Dynamic UI form definition examples should be updated</p>
</div>
<div class="section" id="references">
<h2>References</h2>
<p>None</p>
</div>
Tue, 25 Nov 2014 00:00:00 PK G| murano-specs-latest/objects.inv# Sphinx inventory version 2
# Project: Murano Specs
# Version:
# The remainder of this file is compressed using zlib.
xOKIP(.IILJQ5T(ͅJe(+槔*xShBu@&%g*AC$r 1PK GW^ ^ murano-specs-latest/index.html
One of powerful Murano use cases is deploying compound applications, composed by set of
different layers such as DB, web server and others, which implies the deployment of
software not just in an unique VM but in several ones. The environment template is the specification of
the set of VMs plus the applications to be installed on top of. The user can define
environment templates from scratch or reuse and customize them (e.g. including keypairs).
Environment templates not only cover instantiation, but also the specification of such templates,
store them in a catalogue and clone them from the abstract template catalog. In this way,
an abstract environment template catalogue as well as a environment template one will be stored in the
database, storing templates shared among all users and individual ones.
In order to fullfill this functionality, a new entity can be introduced in the MURANO
database. It is the Murano environment-template, which contains the specification about what
is going to be deployed in terms of virtual resources and application information, and it can be deployed
on top of Openstack by translating it into environment. This environment template can be created, deleted,
modified and customized by the users. In fact, it can be instantiate as many times as the user wants.
For instance, the user wants to have different deployments from the same environment template: one for
testing and another for production.
The environment template is composed by a set of services/applications with the software to be installed together their
properties to work with. This software can be instantiate over an virtual service.
In this case the workflow for the creation and the instantiation of the environment template will imply:
1.- Creation of the environment template (including application information)
2.- Transformation of the environment template into the environment (creation of the environment, session and
adding applications to the environment
3.- Deploy the environment on top of Openstack.
The environment template structure and information will be similar to the environment, not including some hardware information, like
default network, or virtual server name. Mainly, the environment template information will contain:
- template name, the name for the template. In case, it is not provided, the request will not be valid.
- services, the application information. For each service it will include information about the applications to be
installed (like tomcat), including application properties like tomcat port. In addition, in case applied, the information about
the virtual server (instance) will be incorporated like keyname, flavor, image and so on. The following lines show
an environment template example.
A environment template entity will be introduced in the MURANO object model. This implies its existence
in the database, the inclusion of Template services and the extension of the API. The template entity
can consist on:
The inclusion of the environment-template entity will imply the extension of the API for the environment-template
creation, deletion, updating and translate into the environment.
POST /templates
Request
Method
URI
Description
POST
/templates
Create a new environment template
Content-Type
application/json
Example Payload
This template description can be composed just by the environment template name, or it can
include the description of all services/applications to be deployed.
1.- Just the template
+————————–+———————————————————–+
| Code | Description |
+================+===========================================================+
| 200 | OK. Environment Template created successfully |
+—————-+———————————————————–+
| 401 | User is not authorized to access this session |
+—————-+———————————————————–+
| 409 | The environment template already exists |
+—————-+———————————————————–+
+————————–+———————————————————–+
| Code | Description |
+================+===========================================================+
| 200 | OK. Environment Template created successfully |
+—————-+———————————————————–+
| 401 | User is not authorized to access this session |
+—————-+———————————————————–+
| 404 | The environment template does not exit |
+—————-+———————————————————–+
DELETE /templates/{env-temp-id}
Request
Method
URI
Description
DELETE
/templates/<env-temp-id>
Delete the template id
Parameters:
env-temp_id - environment template ID, required
Response
Code
Description
200
OK. Environment Template deleted successfully
401
User is not authorized to access this session
404
Not found. Specified environment template doesn`t exist
POST /templates/{template-id}/services
Request
Method
URI
Description
POST
/templates/{env-temp-id}/services
Create a new application
Parameters:
env-temp-id - The environment-template id, required
+————————–+———————————————————–+
| Code | Description |
+================+===========================================================+
| 200 | OK. Environment template created successfully |
+—————-+———————————————————–+
| 401 | User is not authorized to access this session |
+—————-+———————————————————–+
| 404 | The environment template does not exit |
+—————-+———————————————————–+
| 409 | The environment already exists |
+—————-+———————————————————–+
As well as a change in the API to include this new entity, the python-muranoclient will
be changed for including the environment template operations.
* env-template-create Create an environment template.
* env-template-delete Delete an environment template.
* env-template-list List the environment templates.
* env-template-rename Rename an environment template.
* env-template-show Show the information of the environment template
* env-template-add-app Add an application to the environment template
* env-template-create-environment It creates an environment from the environment template description
1.- Including the environment template entity in database
2.- Extension of the API for environment template catalogue
3.- Generation of environment from template operation
4.- Implement the changes in murano CLI
There is a huge community of applications (opscode, puppet-labs) where
deployment installation instructions are specified in configuration
languages such as Puppet or Chef. In order to reuse these applications,
adaptors like Chef or Puppet are required on the VM side. Both chef and
puppet recipes will not be managed by centralized server (chef-server,
puppet-master), but they will use the standalone version, specifically
the usage of chef-solo and puppet apply.
Inclusion of new executors in the murano-agent project. These executors
will be objects to be used by murano-agent. Specifically, two executors
will be implemented: Puppet and Chef. Both executors will be in charge of:
Obtaining the required modules or cookbooks in the virtual machine.
This task can be done by passing the information from murano-engine to
murano-agent, obtaining the information from the package itself. It requires
the user to upload the package information plus the cookbooks to be used.
The second option implies the cookbooks are downloaded in the virtual
machine, so that they only need the URL to be accessible.
Generating the required files for the configuration language.
For instance, manifests and hiera data for puppet, and, node
specifications for chef from the information stored in the
execution plan.
Executing the chef-solo or puppet-apply process.
Previously, some work has to be done to install Chef or Puppet inside the VM.
This task can be done by using cloud-init from the murano engine. The
following is an example on how these executors work:
In this case, a new script Type appears (instead of Application). It is
Chef type, which will execute the Chef executor. The same happens with
the Puppet Type. In addition, the EntryPoint contains the information
about the cookbook and the recipe to be installed. The Files section
is used for the cookbooks and its dependence information. The cookbooks
properties are in the Parameter section.
All the required steps to be part of the executor can be summarized as follows.
For Chef,
Creating the node.json with the recipes and the configuration parameters:
The solution proposed is valid for any VM which contains the configuration
language implementation already installed. There are event chef-solo and
puppet agents for Windows.
As a part of policy guided fulfillment we need to call Congress from Murano,
to enforce the policy on Murano environment. For current release
the enforcement will be done by Congress simulation API, where Murano will
query table predeploy_error in murano_system policy for passed update
sequence created by mapping of environment into congress schema.
We will use simulation feature of congress API.
Using this API Murano will send decomposed Murano environment to Congress
tables, so simulation can evaluate predeploy_error rule without changing
existing data in Congress.
mapping of Murano Environment into update sequence used in simulation API
This section provides congress schema created for Murano environment mapping.
It will be created by Congress datasource drivers - see murano driver spec .
Policies
murano
Dedicated policy for Murano data.
murano_system
Dedicated policy for rules
Schema
murano:objects(obj_id, owner_id, type)
This table holds every MuranoPL object instance in an environment.
obj_id - uuid of the object as used in Murano
owner_id - uuid of the owner object as used in Murano
type - string with full type indentifier as used in Murano
(e.g., io.murano.Environment,...)
murano:parent_types(obj_id, parent_type)
This table holds parent types of obj_id object. Note that Murano
supports multiple inheritance, so there can be several parent types for
one object
murano:properties(obj_id, name, value)
This table stores object’s properties. For multiple cardinality
properties, there can be number of records here. MuranoPL properties
referencing class type (i.e., another object) are stored in
murano:relatinoship. Properties with structured content will be
stored component by component.
murano:relationships(src_id, trg_id, name)
This table stores relationship between objects (i.e., MuranoPL property
to class). For multiple cardinality relationships several records
should be stored.
murano:connected(src_id, trg_id)
This table stores tuples of objects connected directly and indirectly
via relationship. It is necessary since Congress does not support
recursive rules yet.
murano:states(end_id, state)
This table stores EnvironmentStatus of Murano environment ( one of
‘ready’, ‘pending’, ‘deploying’, ‘deploy failure’, ‘deleting’,
‘delete failure’ ).
Murano is an application catalog, where new applications can be easily added.
Those applications may belong to a category, that is not on predefined list.
Also, some categories may not be needed, and user can delete such kind
of categories.
All operations should be available only for admin users.
Add new panel named ‘Categories’ under ‘Manage’ section;
It should be available only for admin users.
This panel should represent table with categories.
The table will contain ‘name’ column and ‘assigned packages’ column.
“Add category” will be a table action and “Delete Category” will be
row action.
Delete button should be hidden for those categories connected to
the packages.
Provide corresponding methods in the python-muranoclient;
Category manager will be added to v1 module;
Murano dashboard will support only the version of the client, that includes
corresponding changes in the client. ‘Categories’ panel will not work
with the old murano version, but application catalog and package management
will work fine.
Now there is no way to be sure that the agent successfully started execution
on a VM. Also there is no control of the execution time of scripts on agent.
This process should be more controllable. It can be done by adding timeouts
in Murano engine.
During the agent`s work could be some problems with execution of scripts and
VM may hang. In this case user will wait indefinitely without knowing
what’s happend.
Currently there is no feedback from agent so, it`s impossible to determine
whether agent is ready to accept execution plans or not.
It is proposed to provide mechanism of timeouts which solve these problems.
First of all add timeout to method call of agent on engine-side.
Optional parameter timeout will be added to method call of class Agent
in agent.py. This parameter is the time in seconds with default value 600.
Developer can set up custom value during developing apps for example in this
way:
If the agent plan execution time exceeds the limit, it will be terminated.
Add method waitReady in Agent class.
Method will be added to Agent class in agent.py. It has optional parameter
timeout with default value 100. waitReady creates test plan with trivial
body:
and sends this plan once to agent by method call. It can be uses by developer
to stop deployment before sending template of app if agent is inaccessible as
follows:
If the agent test plan execution time exceeds the time limit,
TimeoutException will be raised and deployment terminates. TimeoutException
will be created in murano/common/exceptions.py.
Add new method isReady in Agent class.
This method will be simply call the waitReady. Method isReady returns:
True, if test plan is executed on time;
False, if the agent plan execution time exceeds the
limit.
and raise PolicyViolationException, which will be created in
murano/coommon/exceptions,py, if the agent disabled by the server.
The method can be used during development Murano-applications. For example,
developer can check if the agent is running and ready to execute templates
before sending the execution plan of application:
- If: $.instance.agent.isReady()
Then:
- $._environment.reporter.report($this, 'Murano Agent is ready')
The message in above example will be reported to Murano Dashboard.
The purpose is to add integration between Murano and Mistral.
We would like to allow invocation of a Mistral workflow from Murano.
No prerequisite for uploaded Mistral workflow.
Functional test will be added to Murano.
The test deploys application which uploads the Mistral workflow from
Resources, triggers it and gets output as a result.
Murano applications provide a powerful and flexible way to move workloads
from other cloud environments to OpenStack. In order to accelerate
application migrating we need a way to deliver Murano
packages and Glance images to customers incrementally, independent from major
releases of OpenStack.
After the end users installed and configured Murano they would need to
install murano-enabled applications. To do so they would use murano CLI
client. Invoking a command like
murano install-package io.apps.application –version=2.0 would
install the application in question alongside with all requirements
(applications and glance images)
A developer would want to provide murano applications to end users, by
hosting them on a web server and providing http-access to application
packages. In that case end users would be able to install the application by
invoking a CLI command murano install-package http://path/to/app
End user would want to install bundles of applications that are often
required to work together, but not necessarily depend on each other.
In that case end user would invoke a command
murano install-bundle bundle_name and murano-client would download all
the applications mentioned in the bundle alongside with their requirements.
End users would want to perform same operations through
murano-dashboard instead of CLI tools.
The proposition is to implement a set of features in python-muranoclient and
murano-dashboard, that would allow end users to install applications from
http application repository.
Enable package-import command to support url as a parameter for import by
modifying the way package creation of murano-client works.
Enable package-import command to support package name as a parameter for
import, introduce –murano-repo-url as a base path to the repository.
Introduce bundle-import command and allow it to support local-files, urls
and bundle names as parameters for import. The command should parse the
bundle file and import all the packages, mentioned in the file.
Bundle should be a simple json and/or yaml-structured file.
Introduce Require: section to manifest.yaml, that would specify which
packages are required by the appication.
Enable package creation suite to automatically import all the packages
mentioned in Require: section.
Introduce images.lst file in the package structure, that would contain a
list of images, required for the application to work.
Enable package creation suite to automatically import required images into
glance image service.
Allow bundle-import command to import bundles from local-files. In that
case first search for package files and image files in the local filesystem,
relative to the location of the bundle file. If file is not found locally
attempt to connect to the repository.
Enable murano-dashboard to support changes made to client and introduce a way
to upload packages via url/name to dashboard.
Implement importing of bundles in murano-dashboard by url or by name.
Since bundles are currently a simple json/yaml optionally we could optionally
support direct input.
Implement error handling both for CLI-tools and dashboard, that would inform
end users about any errors that might have happened along the way of
importing.
Optionally implement a progress marker and a ETA-marker for CLI import
commands.
Implementing a server, that would hold versions and paths to package files
and implementing a client to that server might be a good alternative to a
simple http-server, although it seems a bit excessive at the moment.
Another idea would be to implement a service, that would download packages
asynchronously. This would allow client to download large package files and
image files with possibly better error handling mechanisms. This also seems a
bit excessive at the moment.
It might be a good idea to warn the end user if the client installed a
package, that depends on other packages, not present in app catalog,
although it is not strictly required for the task.
Unit testing should be sufficient to cover most of the use cases.
However an integration test, that would setup a simple repository is very
desirable, since we add changes to both python-muranoclient and
muranodashboard.
Introduction paragraph – why are we doing anything? A single paragraph of
prose that operators can understand. The title and this first paragraph
should be used as the subject line and body of the commit message
respectively.
Some notes about using this template:
Your spec should be in ReSTructured text, like this template.
To test out your formatting, build the docs using tox, or see:
http://rst.ninjs.org
If you would like to provide a diagram with your spec, ascii diagrams are
required. http://asciiflow.com/ is a very nice tool to assist with making
ascii diagrams. The reason for this is that the tool used to review specs is
based purely on plain text. Plain text will allow review to proceed without
having to look at additional files which can not be viewed in gerrit. It
will also allow inline feedback on the diagram itself.
If your specification proposes any changes to the Murano REST API such
as changing parameters which can be returned or accepted, or even
the semantics of what happens when a client calls into the API, then
you should add the APIImpact flag to the commit message. Specifications with
the APIImpact flag can be found with the following query:
What other ways could we do this thing? Why aren’t we using those? This doesn’t
have to be a full literature review, but it should demonstrate that thought has
been put into why the proposed solution is an appropriate one.
Changes which require modifications to the data model often have a wider impact
on the system. The community often has strong opinions on how the data model
should be evolved, from both a functional and performance perspective. It is
therefore important to capture and gain agreement as early as possible on any
proposed changes to the data model.
Questions which need to be addressed by this section include:
What new data objects and/or database schema changes is this going to
require?
What database migrations will accompany this change.
How will the initial set of new data objects be generated, for example if you
need to take into account existing instances, or modify other existing data
describe how that will work.
Each API method which is either added or changed should have the following
Specification for the method
A description of what the method does suitable for use in
user documentation
Method type (POST/PUT/GET/DELETE)
Normal http response code(s)
Expected error http response code(s)
A description for each possible error code should be included
describing semantic errors which can cause it such as
inconsistent parameters supplied to the method, or when an
instance is not in an appropriate state for the request to
succeed. Errors caused by syntactic problems covered by the JSON
schema definition do not need to be included.
URL for the resource
Parameters which can be passed via the url
Example use case including typical API samples for both data supplied
by the caller and the response
Discuss any policy changes, and discuss what things a deployer needs to
think about when defining their policy.
Discuss things that will affect how you deploy and configure OpenStack
that have not already been mentioned, such as:
What config options are being added? Should they be more generic than
proposed (for example a flag that other hypervisor drivers might want to
implement as well)? Are the default values ones which will work well in
real deployments?
Is this a change that takes immediate effect after its merged, or is it
something that has to be explicitly enabled?
If this change is a new binary, how would it be deployed?
Please state anything that those doing continuous deployment, or those
upgrading from the previous release, need to be aware of. Also describe
any plans to deprecate configuration values or features. For example, if we
change the directory name that instances are stored in, how do we handle
instance directories created before the change landed? Do we move them? Do
we have a special case in the code? Do we assume that the operator will
recreate all the instances in their cloud?
Does it require changes to the murano-dashboard / horizon? If so, changes
should be described well. If it’s about complex changes than probably a
separate blueprint / spec should be created for it.
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.
Include specific references to specs and/or blueprints in murano, or in other
projects, that this one either depends on or is related to.
If this requires functionality of another project that is not currently used
by Murano, document that fact.
Does this feature require any new library dependencies or code otherwise not
included in OpenStack? Or does it depend on a specific version of library?
Please discuss how the change will be tested. We especially want to know what
tempest tests will be added. It is assumed that unit test coverage will be
added so that doesn’t need to be mentioned explicitly, but discussion of why
you think unit tests are sufficient and we don’t need to add more tempest
tests would need to be included.
Is this untestable in gate given current limitations (specific hardware /
software configurations available)? Is this untestable in murano-ci? If so,
are there mitigation plans (3rd party testing, gate enhancements, etc).
What is the impact on the docs team of this change? Some changes might require
donating resources to the docs team to have the documentation updated. Don’t
repeat details discussed above, but please reference them here.
Please add any useful references here. You are not required to have any
reference. Moreover, this specification should still make sense when your
references are unavailable. Examples of what you could include are:
Links to mailing list or IRC discussions
Links to notes from a summit session
Links to relevant research, if appropriate
Related specifications as appropriate (e.g. if it’s an EC2 thing, link the
EC2 docs)
Anything else you feel it is worthwhile to refer to
One of the key features of Murano is extensibility, and we need to push this
feature even further and give our customers a way to extend Murano with new
functions (e.g. support for F5 BigIP API) in a drag-n-drop manner. This spec
proposes a solution which will add this extensibility option.
Currently all the functionality which is available to user is limited to the
features of MuranoPL language which just provides data transformation
capabilities and flow control primitives. The language itself does not contain
any functions for I/O operations, hardware access or interaction with host
operating system, other OpenStack or third-party services. This is an
intentional design feature: MuranoPL code is provided by users and cannot be
always trusted. All the external communications and low-level interactions are
done via python code which is bundled with Murano Engine and is accessible to
MuranoPL code via MuranoPL wrappers. Any interactions which are not supported
by that Python classes are impossible.
Some deployment scenarios may need to extend this set of allowed low-level
interactions. They may include some customer-specific logic, custom software
bindings etc, so trying to bundle all of them into the standard Murano Engine
classes is not a good idea. Instead, there should be a way to dynamically
add extra interactions to any existing deployment of Murano without modifying
its core components but rather with installing some plugin-like components.
Installing these plugins is supposed to be a maintainer-only operation,
requiring administrative access to nodes running Murano services. It is
supposed that the maintainer is always aware about the contents of the plugins
and is able to verify them from security, performance and other sensible points
of view.
It is proposed to implement each extension as independent Python Package built
using setuptools library. Each package should define one or more entry-point in
a specific namespace (io.murano.extensions is suggested). Each of this
entry- points should export a class, which may be registered as MuranoPL class
when the engine loads.
Each package should be installed on Murano nodes into the same Python
environment with Murano engine service.
Murano will get a PluginLoader class which will utilize stevedore library [1]
to discover classes registered as entry-points in io.murano.extensions
namespace.
Murano Engine will use PluginLoader to register all the loaded plugins in its
class loader (i.e. will call import_class with a class imported from the
plugin as a parameter). As the result, the classes will become available for
the MuranoPL code being executed in the Engine.
To prevent potential name collisions, MuranoPL names for the loaded classes
will be assigned automatically: the name will consist of the namespace
(io.murano.extensions as suggested above) and the name of entry-point.
To guarantee this naming rule the imported classes should not define their
MuranoPL names on their own (i.e they should not have
@murano_class.classname decorators or other code which modifies their
_murano_class_name field). If they do, the PluginLoader will discard
that information and will log a warning message.
As the entry-point name will eventually become a name of MuranoPL class, the
PluginLoader will validate it accordingly.
As neither stevedore nor setuptools enforce any uniqueness constraints on the
entry-point names (i.e. several packages may define entry-points with the same
name within a same namespace, and all of them will be correctly loaded by
stevedore), then this enforcement should also be done by the Murano’s Plugin
Loader. If two or more plugin packages attempt to register classes with the
same endpoint name, then a warning will be logged and no classes from all the
conflicting packages will be loaded.
PluginLoader will also ensure that objects being exported in these entry-points
are indeed classes, and will check if they define a classmethod called
init_plugin. If such method exists, the PluginLoader will execute it before
loading it.
The plugins which are already installed in the environment may be prevented
from being loaded by a configuration option. This new option called
enabled_plugins will be added to murano.conf. If it has its default
value None or is omitted from the config, there will be no restriction on
the plugins which are being loaded (any plugin registered within the
environment will be loaded). If it exists and is not None, then it is expected
to contain a list of names of the packages from which the plugins will be
loaded. If the package is not mentioned there, all its endpoints will be
ignored and no classes from it will be imported. Empty value of
enabled_plugins will mean that no plugins may be loaded and only bundled
system classes are accessible from the MuranoPL code.
The enabled_plugins setting will be implemented using
EnabledExtensionManager class of the stevedore library [2], so the disabled
plugins will be excluded from entry-point name analysis. Thus if there are
plugins which define conflicting entry-point names, then the conflict may be
resolved with this setting instead of uninstalling the plugin from the
environment.
Currently stevedore is unable to load packages which were installed after the
start of the current process. So, in current proposal it is required to restart
Murano services after plugin package is installed, removed or upgraded and
after the changing of enabled_plugins value in configuration file.
As the restart of the services is not a good thing for production solutions, it
may be a good idea to design a “graceful restart” solution which will make the
service to stop listening for incoming requests, finish its current tasks and
then exit and restart, loading the updated configuration and plugins. However
such solution is out of scope of the current spec and is left for future
blueprints.
Instead of using stevedore to discover and load the plugins, some home-made
solution may be invented to load Python modules from some directory. This
solution may have its benefits (e.g. it does not require restarts to load new
plugins), however stevedore is currently a de-facto standard for building
plugable solutions in Openstack, so it is suggested to use it.
The change itself does not have any immediate impact on deployer: a new
configuration option is optional and has meaningful default. However
registering new plugins will require to restart the Services, which may bring
up some concerns in production environments.
Developers who build their own plugins should be aware about setuptools entry-
points and should inherit their exported classes from
murano.dsl.murano_object.MuranoObject.
As a part of policy guided fulfillment we need to implement predeploy policy enforcement point - i.e., Murano calls Congress to evaluate predeploy policy rules on data representing Murano environment being deployed. If evaluation returns predeploy error data (i.e., enforcement failed), then deployment of Murano environment fails.
Predeploy policy rules are represented by predeploy_error(env_id, obj_id, message) congress table.
It means
Congress administrator is responsible for creating predeploy rules, which has this table on the left side (see examples).
Murano is not involved in policy rule evaluation, except that Murano provides data about Murano environments. Thus user can use any data (e.g., datasource tables, policy rules) available in Congress to define when environment can be deployed.
Table predeploy_error(env_id, obj_id, message) reports list of found errors:
env_id environment id where error was detected
obj_id object id (in environment id) on which error was detected
Use implementation of Congress Support in Murano in order to implement policy enforcement point as advised by Stan (see below). The Congress support must correctly deal with following setups
Openstack with Congress installed
Openstack without Congress
Stan: such approach makes PolicyEnforces (and thus dependency on Congress) be mandatory for Murano. Better approach for now could be just insert
at https://github.com/stackforge/murano/blob/master/murano/common/engine.py#L112
something like
if config.CONF.enable_policy_enforcer:
policyenforcer.validate(self.model)
Provide Developer and User Documentation (see Documentation section).
Murano Project introduces an application catalog, which allows application
developers and cloud administrators to publish various cloud-ready
applications in a browsable categorized catalog. Cloud users
– including inexperienced ones – can then use the catalog to
compose reliable application environments with the push of a button.
The change described here will focus on supporting Heat environments. Another
spec was submitted for Heat files.
In this spec no UI changes are included. A UI part that can be added in future
specs, and in any case is out of the scope of this spec.
Allowing Heat environments to be saved and deployed as part of a Murano Heat
package. Adding environments to a package should be optional. Heat environment
files should be placed in the package under ‘/Resources/HotEnvironments’ When a
user request to add a Heat-generated package to a Murano environment, he should
have an option to specify one of the hot-environment-files located at
‘/Resources/HotEnvironments’ in the package, and this heat environment file
should be sent to Heat with the template during Murano environment deployment.
If no heat environment file was specified, the template will be deployed
without a Heat environment.
The stage where the Heat environment for the deployment should be specified
is when adding a package to a Murano environment as part of a configuration
session.
The heat environment should be referenced by name.
In the future, there can be an API to list the hot environments of a package.
This might be done by using the existing API of getting the UI of a package.
Words that can replace the word environments to reference heat environments:
configurations, profiles, settings. The problem is that in Heat they use the
word environments.
Specifying the heat environment to be deployed with the Heat template as
part of a Murano environment when deploying the environment (instead of
specifying it when adding a package to an environment). If we will wait to
this point, we will have to give a map of packages and the environments to be
deployed with them. this alternative requires more validations.
hotEnvironment - This parameter will be passed as part of the
/environments/{env-id}/services POST API request body. The value of this
parameter will be an environment file name.
templateParameters - All heat parameters that were passed in the root of the
/environments/{env-id}/services POST API request body, will be moved under
this property.
User will now have the option to add heat environments and additional files to
the package, and have them deployed with the package as part of the Murano
environment. The Heat environment will be deployed when it is requested in the
relevant API, while the additional files will always be deployed.
At this point there will be no change in the python-muranoclient. If the user
will wish to add environments or additional files to a heat generated package.
He can edit the package and continue via API. If the user only added additional
files, he can continue via python-muranoclient/UI as well.
New features must not break UI. So since it was proposed to move the user
defined parameters from the root of the request body to the property
“templateParameters”, the UI must change the way it build the request to add a
package to a Murano environment.
The new feature for sending a hot environment with the template will be exposed
in the UI the following way:
The user will be able to choose an environment file from a drop-down list
during the same wizard actions he uses to enter heat template parameters.
envs will be generated when parsing the package, so if there is nothing in the
package, the new data objects will be empty. If an API to list the environments
will be implemented an empty list will return, same as in other Murano APIs.
A new object called envs of type dictionary will be added in HeatStack class
in the init method. It can be referenced from inside HeatStack by using
self._envs before/when sending the create request to Heat. This object will be
initialized to be empty.
A new method called setEnvs will be added in HeatStack class. It will allow to
enter a value into _envs just like setParameters allows to enter values into
_parameters.
env_name will take the value passed by the user in the parameter
heatEnvironment. It will be initialized and passed to class HeatStack the same
way parameters are passed today.
When sending the create stack request to heat the selected environment content
should be passed. If all is configured and passed correctly the environment
file content can be accessed from class HeatStack by using the next command:
self._envs[self._env_name]
A new method called _translate_envs will be add to HotPackage class. it will
get a path to the envs directory and will return a dictionary of environments
locations and files values. It will be in the next format:
environmentRelativePathStartingHeatEnvironmentsDirectory -> stringFileContent
For example if there is an environment with a full path of
/Resources/HeatEnvironments/my_heat_env.yaml and content of:
“heat_template_version: 2013-05-23nnparameters:n” and it
is the only file in the folder, than this will be the dictionary returned:
{“my_heat_env.yaml”: “heat_template_version: 2013-05-23nnparameters:n”}
A very similar function was proposed for the Heat files feature. There will be
a reuse of the code there, if it will be implemented first.
Add support for adding a package to a Murano environment with a Heat
environment specified in the request.
Add support for Heat environments when deploying a Murano environment. If
a Heat environment is saved in the session for the package, it should be
parsed and send with the template, when deploying a Murano environment.
make sure that when ui generate a POST request for API:
/environments/{env-id}/services the user defined parameters are located under
templateParameters in the request body.
The change described here will focus on supporting additional files. Another
spec will be submitted for Heat environments.
Allowing Heat additional files to be saved and deployed as part of a Murano
Heat applications. Adding additional files to a package should be optional.
Such files should be placed in the package under ‘/Resources/HeatFiles’. When a
Heat generated package is being deployed, if the package contains Heat files,
they should be sent to Heat together with the template and params. If there are
any Heat additional files located in the package under ‘/Resources/HeatFiles’,
they should all be sent with the template during stack creation in Heat.
There can be more nested directories under ‘/Resources/HeatFiles’, and if they
have files in them, those should be send to heat as well together with their
relative path.
This part does not require any UI nor API changes.
User will have the option to add Heat files to the package, and have them
deployed with the package as part of the Murano environment.
At this point there will be no change in the python-muranoclient. If the user
will wish to add files to a heat generated package, he can edit the package and
continue normally from there.
This new data object will be generated when parsing the package, so if there
is nothing in the package, the new data objects will be empty.
A new object called files of type dictionary will be added in HeatStack class
in the init method. It can be referenced from inside HeatStack by using
self._files when sending the create request to Heat. This object will be
initialized to be empty.
A new method called setFiles will be added in HeatStack class. It will allow to
enter a value into _files just like setParameters allows to enter values into
_parameters.
A new method called _translate_files will be add to HotPackage class. it will
get a path to the files directory and will return a dictionary of files
locations and files values. It will be in the next format:
fileRelativePathStartingHeatFilesDirectory -> stringFileContent
For example if there is a file with a full path of
/Resources/HeatFiles/my_heat_file.yaml and content of “echo hello world” and it
is the only file in the folder, than this will be the dictionary returned:
{“my_heat_file.yaml”: “echo hello world”}
A new parameter of called files will be added to _generate_workflow method that
can be found inside HotPackage class. It will be included in the deploy
variable in the same way the template_parameters is included.
Add support for Heat additional-files. If such files exist in the package,
they should be parsed and send with the template, when deploying a Murano
environment.
There are cases when there is no Internet access cloud with murano installed.
Then if user wants to add some bundle of packages into murano, he has to
download all of them one-by-one from application catalog using local computer
with access to the Internet. After that he saves them somewhere on data storage
device and moves all files to cloud.
It is necessary to simplify process of saving packages to avoid manual
downloading.
It’s proposed to add new CLI command bundle-save to murano-client.
Method do_bundle_save will corresponds with new command. It will take three
arguments:
filename is a bundle name, bundle url or path to the bundle file;
–path (optional) is a path to directory in which user wants save packages.
If it is not specified, current directory will be used;
–no-images (optional) is flag. If it is set, downloading of all required
images will be skipped.
Method will build whole list of packages and its dependencies. This ability is
already implemented and used in ‘bundle-import’. Then method will save bundle
file and each package to specified path. For this, method ‘save’ will be added
to FileWrapperMixin – the parent class for Bundle and Package classes.
This method will take one argument dst – destination for file. It will copy
already downloaded file to the specified path.
Method do_bundle_save will also save images which packages require.
save_image_local method will be used for that. All images will be downloaded
if –no-images is not set.
After bundle saving directory with packages can be moved to lab with murano
where all of them can be imported to murano application catalog in one
command.
CLI command package-save also must be implemented. It will give to user the
opportunity to download specific package or several packages he need.
The implementation of command will be based on the methods described above.
Class loader should be able to load packages not only from the external
repository, but from a local directory. It’s needed not only for testing new
packages, but for accepting packages on-the-fly.
During the development phase the package gets frequently updated, and the need
to upload it to the repository on each update complicates the development.
Ability to load it from the local filesystem will streamline the process
Another case, when there is no connection to the external repository.
Need to create one more class, responsible for loading packages.
It will look up at the provided directory for a package, that name was requested.
It worth noting, that packages should not be zipped.
Class loader from repository (RCL) and new class loader from local dir (LCL)
will provide the following logic:
If local dir is not provided, LCL is not operating.
Logic stays same as it’s now. RCL do all the work.
If directory path or several paths to load local packages from are provided,
LCL will check all packages in dir and compare with requested name.
If the desired class is found, package gets loaded. If not - next dir in the
provided list will be scaned.
If is not found in all the provided directories - RCL sends API call to find
it in the repository as usual.
We do have both class loader implemented, we need an ability to combine two
(or more) package loaders in one, with the ability to prioritize the queries.
For example, a CombinedPackageLoader may be created with an instances of
DirectoryPackageLoader and ApiPackageLoader underneath. When a
request for a package or class comes in, it is first executed against loader
with the highest priority (say, DirectoryPackageLoader), and if it is not
found there, then goes to the next one.
Use separate class loader in test framework.
But support two different class loaders is not good.
Also as an alternative we can also mention
this
approach.
That is: introduce package_loaders config parameter. It can be a list of
python-dot-notation class names, that murano would import and try to import pkg
from each loader. This could further be modified to a list of lists, to allow params
like this:
package_loaders: [pkg_loader1, [pkg_loader2, param1, param2]]
This would allow to easily add custom loaders without changing murano code itself.
Cloud Foundry is PaaS which supports full lifecycle from initial development,
through all testing stages, to deployment. As far as Cloud Foundry comes in
three flavours such as Cloud Foundry OSS, Pivotal Cloud Foundry and Pivotal
Web Services.
If we implement Cloud Foundry Service Broker API in murano, murano apps will
get an ability to be deployed through CloudFoundry itself. This will improve
PaaS user experience as it will have an ability to integrate his app with
existing apps in murano and deploy really complex configurations on top of
OpenStack.
We need to write Cloud Foundry Service Broker implementation for murano. One of
the parts of this implementation should be some mapping function between Cloud
Foundry and OpenStack resources. Now it’s planned to map Cloud Foundry
Organizations to Openstack tenants and Cloud Foundry spaces to murano
environments. So, all tenant users will be granted with the privileges based on
their existing roles in OpenStack tenant. And now it looks like we need to have
to run a murano environment for every single service provisioned in Cloud Foundry.
The parameters which is needed to murano for successful application deployment
will store in service object section parameters. The Service Broker itself will
parse them as soon as Cloud Foundry can’t do it. It will be parsed during Provision
request. The request body will look like that:
.. code-block:: javascript
It’s planned to setup a Service Broker as a separate service which will be deployed
on the same nodes as murano. Additional options should be added to the configs.
Also we want to use Cloud Foundry experimental asynchronous operations[3].
No existing API of murano service is going to be changed. New service will be
created implementing the standard Cloud Foundry Service Broker API. Its API
methods are as follows:
GET /v2/catalog
Request
Method
URI
Description
GET
/v2/catalog
List all available apps
Parameters:
None
Response
Code
Description
200
OK. The expected resource body as below
{"services":[{"id":"service-guid-here","name":"mysql","description":"A MySQL-compatible relational database","bindable":true,"plans":[{"id":"plan1-guid-here","name":"small","description":"A small shared database with 100mb storage quota and 10 connections"},{"id":"plan2-guid-here","name":"large","description":"A large dedicated database with 10GB storage quota, 512MB of RAM, and 100 connections","free":false}],"dashboard_client":{"id":"client-id-1","secret":"secret-1","redirect_uri":"https://dashboard.service.com"}}]}
PUT /v2/service_instances/:instance_id?accepts_incomplete=true
Binding has been created. The expected response body is below.
200
May be returned if the binding already exists and the requested
parameters are identical to the existing binding. The expected
response body is below.
409
Should be returned if the requested binding already exists. The
expected response. body is {}, though the description field can
be used to return a user-factorin error message.
Now name is a required parameter in every single form definition.
But murano-engine doesn’t know anything about this parameter. It mostly used
for dymanic UI purposes. So we can insert this field automatically in every
form.
‘name’ property has no built-in predefined meaning for MuranoPL classes
or applications.
Now all unknown parameters are ignored, but the error will be spawned and
all applications will be invalid in the near future.
To prevent global failure this change is suggested.
Add automatic field inserting into the first form and store ‘name’ field value
in object header:
Dynamic UI version will be increased to 2.1;
‘name’ property is not required in MuranoPL class definition anymore.
If user still have ‘name’ property in class definition, he should supply
corresponding field in UI definition. It will have no special meaning for
murano dashboard.
New field will be inserted to the first form if Dymanic UI version is higher
or equal to 2.1;
If Dymanic UI version is higher or equal to 2.1 ‘name’ field value will be
placed to the object header (‘?’), in “done” method of application creation
wizard;
In get-mode, application ‘name’ parameter will be checked in:
Primary under ‘?’ parameter;
Secondary in the object model root;
Add new YAQL function to dashboard’s YAQL to be used by dynamic UI.
The function will be called ‘name’ and will allow to use
automatically-inserted name field in object model description.
This change introduces new version of dynamic UI form definition.
Only backward compatibility will be supported: new dashboard can work with old engine.
Currently there is no way to configure and/or deploy a murano environment from
the command line. This specification describes how this issue can be addressed
and what steps have to be taken in order to implement this abilities.
Currently the only possible way to deploy a murano environment is through
interaction with horizon. CLI client currently lacks commands to add apps to
environment or deploy an environment. This makes murano useless without horizon
and murano-dashboard.
It also means, that scripting and/or automating deployment of murano
apps/environments is currently problematic to say the least.
This spec proposes to add several new CLI commands and modify existing to
allow user to add apps to the env, configure it and send it to deploy.
Command environment-create currently only supports adding the name of the
environment, while the api call supports setting aditional params, such as
defaultNetworks. environment-create should be updated to allow setting
custom keys to environment model.
environment-edit command should perform all the editing (adding, deleting,
modifying of existing apps)
This command should be non-interctive, adding an interactive mode is a
good idea as of itself, but is out of scope of this spec.
environment-edit would use jsonpatch format for input (as described by
RFC 6902). This is a well known and powerfull instrument to manipulate json,
and object model is currently stored in json.
This would allow easy addition, modification and deletion of apps.
Editing of environment attributes is not allowed by API, so it’s beyond the
scope of this spec.
During command execution, env configuration parameters should be read from
stdin or a file.
Supporting stdin as input source means it should be possible to issue a
command like muranoenvironment-editenv_id<app_patch.json
All operations would only apply to services field, so the /services/ part of
the path can be ommited.
note::
This means, that a user has to generate unique ids. This can be a difficult
task and may hinder scripting capabilities. We might think of a way to
mitigate this issue, by introducing a way to generate ids. This can be done
by introducing an optional parameter --id-format. It would accept a
template for strings to be replaced with generated ids. For example:
--id-format=##id## would replace all occurrences of ##id##-1 with fist
generated id, all occurrences of ##id##-2 with second generated id and all
occurrences of ##id## with a unique id. uuids should be used for id
generation.
Command should perform validation of its input. This can be done using
MuranoPL classes and property contracts.
If an error happens during non-interactive mode (for example validation fails
for some field) murano should return a non-zero status, to facilitate
scipting and error-detecting.
Command environment-edit should support optional --session parameter,
that allows user to specify a session for editing an environment.
It should also
warn user in case more than one session is open. If the session parameter is
omitted: last open session for given environment is used.
If there are no open sessions — a new session would be opened.
note::
This means that to deploy a simple application one has to know jsonpatch
syntax. We might think about optional syntax sugar commands, that would
allow adding a single app to the environment. These would use predefined
jsonpatch patch documents and would accept only value to be added to
/Objects/services/- path.
We should implement session controlling commands during
implementation of this spec, for example:
session-list Show list of open sessions for a given environment.
session-show Show details of currently configured session..
session-delete Discard an open session for a given environment.
In case an error occurs during environment deployment this would allow to
rollback the changes to the previous version of environment.
This should also allow to handle cases, when a single environment is edited
simultaneously by different users.
environment-action command should be implemented to allow performing
actions against an environment. One example of actions is a deploy action, so
muranoenvironment-actiondeploy should deploy the environment.
Alternatively we can implement an interactive mode, that would mimic current
dashboard behaviour. This would not allow scripting, but would allow us to
build a more user-friendly CLI interface. The dowside is that current UI
definitions are scheduled to be changed and would most likely be replaced in
the forseable future. This means, that most of the work would go to waste.
It is possible that implementation of this spec would require setting and
reading intermediate environment variables to work correctly with sessions,
during app addition, env deployment.
Overall deployment of murano would not be affected.
We shall need Unit tests for new commands introduced.
Also, since this change introduces a way to deploy an env from CLI. This means
that integration tests for murano client should be implemented. A typical test
should upload and app, configure a simple environment with 1-2 apps and set
some custom parameters, like access port and optionally deploy the env in
question. This tests should probably take place in murano-ci.
New python-muranoclient commands would have to get a proper documentation. It’s
also possible, that we would want to document the whole process of deploying an
app or scripting of such a deployment as a separate article in murano
documentattion.
The purpose is to add an ability to abandon the environment, which hangs during
deployment or deleting in order to hide it from the list of other environments.
There are cases when the process of deleting or deploying environment may hang.
Then the user has to release all used resources and manually clean the database
in order to get rid of the list of failed environments.
Manual cleaning of the database is unsafe and inconvenient operation. That’s
why abandon feature has to be provided. It should improve usability and
allows to user to avoid direct database editing. But it is necessary to notify
the user that all resources used by abandoned environment must be also released
manually as previously.
The implementation of this feature consists of three stages:
Modify environment-delete API endopoint to have abandon feature
The method delete must be changed. Depending on the parameter “abandon”,
obtained from request data, the method should work differently. This parameter
has a boolean type. If it equals True enviroment will be directly removed
from the database without object model cleanup.
Provide corresponding changes in the python-muranoclient
Method delete of environment manager should be modified. New boolean
parameter abandon with default value False should be added. The value of
parameter affects the building of url, which is sent to murano-api.
Add new button Abandon to murano-dashboard
This button should be available with any environment state.
Proposed change doesn’t solve problem of deployment process hanging.
Murano-engine may continue to deploy abandoned environment. It is
necessary to find a way how to stop murano-engine in this case.
abandon - boolean, indicates how to delete environment. False is used if
all resources used by environment must be destroyed; True is used when just
database must be cleaned
Functional tests for murano-dashboard must be updated.
Unit tests should cover API call and CLI client
Tempest tests are out of the scope of this spec.
Others logging methods are Logger.debug, Logger.info, Logger.warning,
Logger.error, Logger.critical. Each method corresponds to the oslo.log
logging level.
There is also separate method for exception stack trace output described
below.
Exceptions logging
Method Logger.exception intended to log a stack trace:
$.log.exception(exc, 'Something bad happened: {0}', 'Oops!')
exception method uses the same log level as Logger.error.
New global MuranoPL function logger()
Call of the function logger(‘logger_name’) returns new instance of the
io.murano.system.Logger. If function with the same logger_name was
called previously then the same logger instance should be returned instead of
building new one.
Logging configuration
Logging should use standard Murano Engine logging subsystem.
Application itself cannot set logging settings at runtime.
All of appenders, formatters an etc. may be configured via standard way
as others loggers in Murano Engine.
Prefix applications should be added to each logger name which created by
application. As example, logger named active_directory in the MuranoPL
should be identified as applications.active_directory at the python side
and in the system config. This is for separation loggers used by
applications and engine system loggers. Also it will allow us to specify
settings for the application loggers separately from others loggers.
Default configuration
All logs written in the one file by default. Log rotation should be used,
so maximum size of logs is limited.
Logging naming conventions
A note about the logging naming conventions should be added to the MuranoPL
tutorial.
Congress Murano datasource driver pulls environments from one tenant only. The goal
is to pull all environments from all tenants (as nova driver does for servers).
Murano - Congress integration is part of a part of Policy Guided Fulfillment.
It uses Congress policy framework to define and evaluate restrictions on Murano
environments. So Murano environments are pulled by Congress Murano datasource driver,
so Congress policy rules can be evaluated.
The problem is that Murano REST API returns environments of one tenant of authenticated user’s token only.
Thus Congress policy rules evaluation is run on data from one tenant only.
Other Congress datasource drivers are dealing with similar requirements also - for example
Nova datasource driver pulls data about all servers across all tenants
in its nova policy. It is possible because Nova REST API supports search option all_tenants.
Note that Congress policy is a place of both rules and data related to one service.
If policy is defined by datasource driver, then its configuration have user, password and tenant,
which are used to get token to access the service.
Search option all_tenants will be added to operation List Environments of
Murano REST API. When set, the returned list will contain all environments accessible
by the user (specified by token) regardless of tenant.
Listing environments from all tenants can only admin user.
The requested behavior can be also achieved by iterating operation
List Environment over all tenants available to the configuration user.
This solution has following performance issues:
each pull cycle executes the REST operation for every tenant where user is member,
instead of one execution in case of all_tenants
user’s tenant assignment has to be periodically updated, so it leads to another
requests to keystone each such period
Core Model can be seen as API, because user is using it when writing Datalog queries
in Congress, or integrating with Mistral workflows. Current Murano Core model does not
provide means to easy link them with realized OpenStack entities (for example Murano
Instance does not provide UUID of provisioned Nova Server).
Congress datalog queries are one of core features used by Policy Guided Fulfillment.
These queries are used to express validity of Murano environment either
in pre-deployment and/or runtime. In order to evaluate environment validity it is
necessary to work with realized entities by core Murano components - for example
I want to check if Murano Instance’s Nova server exists and is running
In kilo I have to use IP address of the Murano Instance and do multiple joins of
neutron tables to identify Nova server.
I want to check if owner of network used by Murano Environment is from given group of
users
In kilo it is impossible because Murano network object contains only name
of the network (a-network), while realized network (via Heat) contains name
with Murano object id (a-network-bed7a70ed791434c8acdd53a52a8d4ca)
Instead of adding the same property to each class aware of openstack ID we can create
mixin class ( e.g. OpenstackIdMixin) with this property and all classes aware of
openstack ID will extend that mixin.
Name: OpenstackIdMixin
Properties:
openstackId:
Contract: $.string()
Usage: Out
If proposed changes will be done prior Murano package versioning, then after upgrade
the Murano objects won’t have initialized introduced properties (openstackId).
The good way to unify our log system would be to follow the major guidelines.
Here is a brief description of log levels:
Debug: Shows everything and is likely not suitable for normal production
operation due to the sheer size of logs generated (e.g. scripts executions,
process execution, etc.).
Info: Usually indicates successful service start/stop, versions and such
non-error related data. This should include largely positive units of work
that are accomplished (e.g. service setup, environment create, successful
application deployment).
Warning: Indicates that there might be a systemic issue;
potential predictive failure notice (e.g. package execution problems,
problems with categories listing).
Error: An error has occurred and an administrator should research the event
(e.g. deployment failed, app add failed).
Critical: An error has occurred and the system might be unstable, anything
that eliminates part of murano’s intended functionality; immediately get
administrator assistance (e.g. failed to access keystone/database, plugin
load failed).
As far as murano-dashboard has it own notification system all notifications
should be duplicated at log messages and should follow this spec in the selection
of log level.
Here are examples of log levels depending on environment execution:
LOG.warning(_LW("Class is defined in multiple packages!"))
Environment is not found
LOG.error(_LE('Environment {id} is not found').format(id=environment_id))
Additional step for our logging system should be usage of pep3101 as unified
format for all our logging messages. As soon as we try to make our code more
readable please use {<smthg>} instead of {0} in log messages.
We need to follow OpenStack guidelines, but if needed we can move plugin logs
to DEBUG level instead of INFO. It should be discussed separately in each case.
Goal is to be able to define modification of an environment by Congress policies prior
deployment. This allows to add components (for example monitoring), change/set properties
(for example to enforce given zone, flavors, ...) and relationships into environment,
so modified environment is after that deployed.
Currently it is possible to reject deployment of an environment if it does not follows
set of so called pre-deployment policies set by admin. Administrator wants to also modify
environment prior it is deployed:
add/set/remove component properties
add/remove relationships
add/remove objects
Example Use Case: Policy Based Monitoring
Admin wants to monitor an environment, so he wants to
install monitoring agent on each Instance
it is done by adding component with the agent and creating relationship between
agent and Instance. It is done at pre-deploy time
register monitoring agent on Monitoring server
it is done by calling monitoring server API during deployment of monitoring agent.
We need to cover by unit tests:
* framework for registering/managing modify actions
* applying modify actions on environment
* processing action list returned by congress
We need to create functional tests covering end-to-end scenario.
As an Application Developer I’d like to execute my workflows without actual
deployment and interaction with murano-dashboard in order to verify my workflow
before actual deployment by those increasing my application development
speed.
Verifying application packages should be simple and fast.
User doesn’t have to re-upload package and add app to the environment on every
change.
Allow application author to validate his application using unit-tests
Those tests will be put to the application package to allow anyone to test
this app at any time
Tests will look like regular unit tests. Testing framework, witch will
run unit-tests will support commands, that will allow to load test package
from directory, to call class methods and configure deployments parameters.
That will make deployment test run easier. Also, test writer may run
deployment several times, examine and compare results with different
parameters
Tests should be able to produce complete object model with some parameters
of deployment:
environment attributes (such as tokens) (or overwriting values, defined in
config);
mock the methods of system classes which include various kinds of external
communications. Dependent applications, system resources and various API
clients and also be mocked. It should be allowed to specify a returned
value. There would be separate specification for mocking, where the
details will be described.
Provide one CLI command, that will mock creation of VMs and other things and
returns the deployment result.
Cons:
Impossible to verify deployments, where execution plan returns a value, which
is used in future app workflow. Compare results of several deployments would be
inconvenient Real VM’s can’t be
Tests will be placed to a package, so manifest version need to be updated.
This functionality should be described in a separate spec.
For now, there will be no impact on project itself.
#. Add ‘simulation’ mode (new entry-point) to Murano Engine, where
packages would be uploaded from the provided path there would be no
interconnection with RabbitMQ
Implement testing framework, written in MuranoPL that will include the
classes, described below. The structure would be taken from python unittest
module. Framework will include test-runner
Implement mock support.
Define what is needed to change in MuranoPL itself
Testing framework may contain the following classes and methods.
This are base classes for simple testing framework.
TestCase class
Method
Description
setUp()
Method called immediately before calling the test method.
tearDown()
Method called immediately after the test method has been
called and the result recorded.
run(result=None)
Run the test, collecting the result into the test result
object passed as result.
assert...
Different asserts (assertEqual, assertNotEqual, assertTrue,
assertFalse).
TestResult class: This class is used to compile information about which tests have succeeded and which have failed.
Attribute
Description
errors
A list containing 2-tuples of TestCase instances and strings
holding formatted tracebacks. Each tuple represents a test
which raised an unexpected exception.
failures
A list containing 2-tuples of TestCase instances and strings
holding formatted tracebacks. Each tuple represents a test
where a failure was explicitly signalled using the
TestCase.assert*() methods.
testsRun
The total number of tests run so far.
TestRunner(stream=sys.stderr,descriptions=True,verbosity=1) A basic test runner
implementation which prints results on standard error.
Has run method, witch executes the given test case. Also stores the execution result.
For the fist time test may be run only one by one. Later we can add TestSuite class and
TestLoader class:
* TestLoader class is responsible for loading tests according to various criteria
and returning them wrapped in a TestSuite (or TestSuite if will add this class).
Methods
Description
loadTestsFromTestCase(testCaseClass)
Return a suite of all tests cases contained in the
TestCase-derived testCaseClass.
Implement simple mocking machinery
All mockes are separated into NonCallable and Callable mocks
Mock class
Public methods
Methods
Description
start()
Activate a patch, returning any created mock.
stop()
Stop an active patch.
patch(target)
The target is patched with a new object. target should be
a string in the form package.module.ClassName.
attach_mock(mock, attribute)
Attach a mock as an attribute of this one, replacing its name
and parent
configure_mock(kwargs)
Set attributes on the mock through keyword arguments
Sometime a VM should be placed to existing network rather then to a new network
created during deployment. While our workflows support this, there is no way
for the end user to select this network in the easy way in the UI. It will be
great if there is a special form element which will pre-populate a list of
available networks and provide an easy option to select desired network for the
application.
Currently murano supports only so called “Default Scenario” when it comes to
networking: it creates a single network per environment, picks a router,
allocates an IP range and creates a subnet with this range within a created
network. This behavior is fine for most of the cases, however it may be
insufficient in complicated scenarios and topologies.
For example, an application may require some pre-configured networks to exist
so it may manipulate with the resources associated to them, allocate floating
IPs from the specific net etc. In this case, the existing net becomes a valid
input property for the application, so its developer may ask the users to
specify it before the deployment.
Another scenario is the need to have all the VMs of the environment to join
some pre-configured network - regardless of their configuration and the
applications they run for. This may be caused by some specific networking
requirements of a particular cloud (a frequent example is a custom proxy to
access the internet which is reachable only from a specific network segment).
When the Network Management scenarios were initially introduced in murano
[1]
we planed to have a so-called “Advanced scenario”, i.e to provide the users
with an ability to use existing networks, subnets, routers etc, or configure
some sophisticated combination of them.
This scenario was properly supported at engine and at the level of the Core
Library: the io.murano.resources.Instance class has a networks field which
allows to specify customNetworks as a collection of objects inheriting from
io.murano.resources.Network, which may include the existing networks or
new networks with non-default configuration.
However, there is no support of this functionality at the UI level: the object
model being generated by the Dynamic UI contains the default networking
definitions only: i.e. the directive to join Environment’s default network,
which is - in its turn - is hardcoded to be a newly created network and a
subnet in it.
A new field will be added to the Dynamic UI framework which will allow to pick
the network and a subnet from the ones available to the current user. This will
be a drop-down list populated when the form is rendered.
The value selected by the user in this field will be a tuple, consisting of
the network id and a subnet id. This ids may be passed to the application
either as plain strings or as part of a more complicated Object Model, for
example as the properties of io.murano.resources.ExistingNeutronNetwork
objects. It is up to application developer to properly interpret and use these
values. The existing applications will not be affected by this change, as their
“configure instance” step of the UI dialog will not include any networking
settings. In future some of our standard apps may be updated to utilize this
new field, but those updates are out of the scope of this spec.
A similar field (but a static one rather then defined as part of Dynamic UI
framework) should be added to the New Environment dialog form, so the user
may choose an existing network to be the default network of a given
environment. The default value in that choice should lead to the creation of a
new environment’s network (i.e. to replicate the existing behavior), while any
other choice should lead to a generation of a new object of type
io.murano.resources.ExistingNeutronNetwork which will be passed to murano-api
as part of defaultNetworks dictionary as the default environment’s network.
Both these fields should share the same logic for value population.
Additionally, the dynamic UI field should have the following options, defined
as constructor arguments and exposed to dynamic ui as yaml attributes:
include_subnets - True by default. If True, the dropdown includes all
the possible combinations of network and subnet. E.g. if there are two
available networks X and Y, and X has two subnets A and B, while Y has a
single subnet C, then the dropdown will include 3 item: (X, A), (X, B),
(Y, C). If set to False the subnet info will not be retrieved, and None
values will be returned as second items in output tuples, so only network ids
are available.
filter - None by default. If set to a regexp string, will be used to
display only the networks with names matching the given regexp.
murano_networks - None by default. May have values None, exclude or
translate. Defines the handling of networks which are created by murano.
Such networks usually have very long randomly generated names, and thus look
ugly when displayed in dropdown. If this value is set to exclude then these
networks are not shown in the dropdown at all. If set to translate the
names of such networks are replaced by a string Network of %env_name%.
Note that this functionality is based on the simple string matching of the
network name prefix and the names of all the accessible murano environments.
If the environment is renamed after the initial deployment this feature will
not be able to properly translate or exclude its network name.
allow_auto - True by default. Defines if the default value of the
dropdown (labeled “Auto”) should be present in the list. The default value is
a tuple consisting of two None values. The logic on how to treat this value
is up to application developer. It is suggested to use this field to indicate
that the instance should join default environment network. For use-cases
where such behavior is not desired, this parameter should be set to False.
The string representation of the dropdown items should look like
%NetworkName%: %cidr% (%SubnetName%), where %SubnetName% part is optional
and may be not present if the subnet’s name is not set.
If neutron is not available (so murano falls back to nova-network support) the
dropdown (both the static and dynamic ones) are not populated and appropriate
hints are available in the New Environment dialog.
Currently the only way to change the default networking behavior is the usage
of networking.yaml file which allows to override the networking setting at
the environment level, for all the murano environments of all the tenants. This
is not flexible enough and does not provide the desired user experience.
However this method will remain, as it allows to override the network setting
globally.
As this feature adds a new type of Dynamic UI fields this will bump the minor
version of Dynamic UI format version. The version will change from 2.0 to 2.1
The user will see the new field in the “Create Environment” dialog. It will
also be shown when the environment is created inline in the environments grid.
The default value of this new field will follow the old behavior.
The user experience with the existing applications will not be changed.
The dropdown in Dashboard will be calling public neutron APIs. If they are not
accessible due to some reason, the UI will guess that neutron is not installed
at all so nova network usage will be assumed.
However, the actual decision on the fallback to nova-network is done at the
murano-api. So, if the dashboard is unable to connect to neutron while the api
is then the behavior is inconsistent: the UI tells user that nova-network is
used, while this is not true. No error occur in this case though.
The application developers may need to modify their apps to use the new
feature. Patch [2] may be used as an example.
Existing apps will not be affected, they will just have the old default
behavior.
Include specific references to specs and/or blueprints in murano, or in other
projects, that this one either depends on or is related to.
If this requires functionality of another project that is not currently used
by Murano, document that fact.
Does this feature require any new library dependencies or code otherwise not
included in OpenStack? Or does it depend on a specific version of library?
There should be an acceptance testing implemented on this feature:
We should test deploying the apps with existing network selected and with the
default option.
Modified application (for example [2]) should be deployed both with “Auto” as
instance network or with some existing network selected.
The test cases above should verify the ability to assign floating IPs to the
VMs
The networks being used as an options for the manual selection should be
connected to a router uplinked to the external network (otherwise app
deployment will fail). Also the DNS nameservers has to be manually assigned
on those networks.
PK Gm$! murano-specs-latest/.buildinfo# Sphinx build info version 1
# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done.
config:
tags:
PK GH ' murano-specs-latest/_static/doctools.js/*
* doctools.js
* ~~~~~~~~~~~
*
* Sphinx JavaScript utilities for all documentation.
*
* :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
* :license: BSD, see LICENSE for details.
*
*/
/**
* select a different prefix for underscore
*/
$u = _.noConflict();
/**
* make the code below compatible with browsers without
* an installed firebug like debugger
if (!window.console || !console.firebug) {
var names = ["log", "debug", "info", "warn", "error", "assert", "dir",
"dirxml", "group", "groupEnd", "time", "timeEnd", "count", "trace",
"profile", "profileEnd"];
window.console = {};
for (var i = 0; i < names.length; ++i)
window.console[names[i]] = function() {};
}
*/
/**
* small helper function to urldecode strings
*/
jQuery.urldecode = function(x) {
return decodeURIComponent(x).replace(/\+/g, ' ');
};
/**
* small helper function to urlencode strings
*/
jQuery.urlencode = encodeURIComponent;
/**
* This function returns the parsed url parameters of the
* current request. Multiple values per key are supported,
* it will always return arrays of strings for the value parts.
*/
jQuery.getQueryParameters = function(s) {
if (typeof s == 'undefined')
s = document.location.search;
var parts = s.substr(s.indexOf('?') + 1).split('&');
var result = {};
for (var i = 0; i < parts.length; i++) {
var tmp = parts[i].split('=', 2);
var key = jQuery.urldecode(tmp[0]);
var value = jQuery.urldecode(tmp[1]);
if (key in result)
result[key].push(value);
else
result[key] = [value];
}
return result;
};
/**
* highlight a given string on a jquery object by wrapping it in
* span elements with the given class name.
*/
jQuery.fn.highlightText = function(text, className) {
function highlight(node) {
if (node.nodeType == 3) {
var val = node.nodeValue;
var pos = val.toLowerCase().indexOf(text);
if (pos >= 0 && !jQuery(node.parentNode).hasClass(className)) {
var span = document.createElement("span");
span.className = className;
span.appendChild(document.createTextNode(val.substr(pos, text.length)));
node.parentNode.insertBefore(span, node.parentNode.insertBefore(
document.createTextNode(val.substr(pos + text.length)),
node.nextSibling));
node.nodeValue = val.substr(0, pos);
}
}
else if (!jQuery(node).is("button, select, textarea")) {
jQuery.each(node.childNodes, function() {
highlight(this);
});
}
}
return this.each(function() {
highlight(this);
});
};
/**
* Small JavaScript module for the documentation.
*/
var Documentation = {
init : function() {
this.fixFirefoxAnchorBug();
this.highlightSearchWords();
this.initIndexTable();
},
/**
* i18n support
*/
TRANSLATIONS : {},
PLURAL_EXPR : function(n) { return n == 1 ? 0 : 1; },
LOCALE : 'unknown',
// gettext and ngettext don't access this so that the functions
// can safely bound to a different name (_ = Documentation.gettext)
gettext : function(string) {
var translated = Documentation.TRANSLATIONS[string];
if (typeof translated == 'undefined')
return string;
return (typeof translated == 'string') ? translated : translated[0];
},
ngettext : function(singular, plural, n) {
var translated = Documentation.TRANSLATIONS[singular];
if (typeof translated == 'undefined')
return (n == 1) ? singular : plural;
return translated[Documentation.PLURALEXPR(n)];
},
addTranslations : function(catalog) {
for (var key in catalog.messages)
this.TRANSLATIONS[key] = catalog.messages[key];
this.PLURAL_EXPR = new Function('n', 'return +(' + catalog.plural_expr + ')');
this.LOCALE = catalog.locale;
},
/**
* add context elements like header anchor links
*/
addContextElements : function() {
$('div[id] > :header:first').each(function() {
$('\u00B6').
attr('href', '#' + this.id).
attr('title', _('Permalink to this headline')).
appendTo(this);
});
$('dt[id]').each(function() {
$('\u00B6').
attr('href', '#' + this.id).
attr('title', _('Permalink to this definition')).
appendTo(this);
});
},
/**
* workaround a firefox stupidity
*/
fixFirefoxAnchorBug : function() {
if (document.location.hash && $.browser.mozilla)
window.setTimeout(function() {
document.location.href += '';
}, 10);
},
/**
* highlight the search words provided in the url in the text
*/
highlightSearchWords : function() {
var params = $.getQueryParameters();
var terms = (params.highlight) ? params.highlight[0].split(/\s+/) : [];
if (terms.length) {
var body = $('div.body');
if (!body.length) {
body = $('body');
}
window.setTimeout(function() {
$.each(terms, function() {
body.highlightText(this.toLowerCase(), 'highlighted');
});
}, 10);
$('