Retire Murano: remove repo content

Murano project is retiring
- https://review.opendev.org/c/openstack/governance/+/919358

this commit remove the content of this project repo

Depends-On: https://review.opendev.org/c/openstack/project-config/+/919359/
Change-Id: I07209efe58bb1ea60fa43026b15beea112985d2b
This commit is contained in:
Ghanshyam Mann
2024-05-10 15:56:25 -07:00
parent 637f7d6d37
commit 4b967c365b
77 changed files with 8 additions and 16074 deletions
-10
View File
@@ -1,10 +0,0 @@
AUTHORS
ChangeLog
build
.tox
.venv
*.egg*
*.swp
*.swo
*.pyc
.testrepository
-7
View File
@@ -1,7 +0,0 @@
[DEFAULT]
test_command=OS_STDOUT_CAPTURE=${OS_STDOUT_CAPTURE:-1} \
OS_STDERR_CAPTURE=${OS_STDERR_CAPTURE:-1} \
OS_TEST_TIMEOUT=${OS_TEST_TIMEOUT:-60} \
${PYTHON:-python} -m subunit.run discover tests $LISTOPT $IDOPTION
test_id_option=--load-list $IDFILE
test_list_option=--list
-3
View File
@@ -1,3 +0,0 @@
- project:
templates:
- openstack-specs-jobs
-14
View File
@@ -1,14 +0,0 @@
The source repository for this project can be found at:
https://opendev.org/openstack/murano-specs
Pull requests submitted through GitHub are not monitored.
To start contributing to OpenStack, follow the steps in the contribution guide
to set up and use Gerrit:
https://docs.openstack.org/contributors/code-and-documentation/quick-start.html
This repository is for doing design review on feature proposal in Murano.
Please refer to `this document <https://opendev.org/openstack/murano-specs/src/branch/master/README.rst>`_
for more information.
-3
View File
@@ -1,3 +0,0 @@
This work is licensed under a Creative Commons Attribution 3.0 Unported License.
http://creativecommons.org/licenses/by/3.0/legalcode
+8 -64
View File
@@ -1,66 +1,10 @@
========================
Team and repository tags
========================
This project is no longer maintained.
.. image:: http://governance.openstack.org/badges/murano-specs.svg
:target: http://governance.openstack.org/reference/tags/index.html
The contents of this repository are still available in the Git
source code management system. To see the contents of this
repository before it reached its end of life, please check out the
previous commit with "git checkout HEAD^1".
.. Change things from this point on
===============================
OpenStack Murano Specifications
===============================
This git repository is used to hold approved design specifications for additions
to the Murano project. Reviews of the specs are done in gerrit, using a similar
workflow to how we review and merge changes to the code itself.
The layout of this repository is::
specs/<release>/
Where there are two sub-directories:
specs/<release>/approved: specifications approved but not yet implemented
specs/<release>/implemented: implemented specifications
This directory structure allows you to see what we thought about doing,
decided to do, and actually got done. Users interested in functionality in a
given release should only refer to the ``implemented`` directory.
You can find an example spec in `doc/source/specs/template.rst`.
Specifications are proposed for a given release by adding them to the
`specs/<release>` directory and posting it for review. The implementation
status of a blueprint for a given release can be found by looking at the
blueprint in launchpad. Not all approved blueprints will get fully implemented.
Specifications have to be re-proposed for every release. The review may be
quick, but even if something was previously approved, it should be re-reviewed
to make sure it still makes sense as written.
Prior to the Kilo development cycle this repository was not used for
spec reviews. Reviews prior to Juno were completed entirely through
Launchpad blueprints::
http://blueprints.launchpad.net/murano
Starting from the Kilo-1 developement milestone Murano performs the pilot of
the specs repos approach.
Please note, Launchpad blueprints are still used for tracking the
current status of blueprints. For more information, see::
https://wiki.openstack.org/wiki/Blueprints
For more information about working with gerrit, see::
http://docs.openstack.org/infra/manual/developers.html#development-workflow
To validate that the specification is syntactically correct (i.e. get more
confidence in the Jenkins result), please execute the following command::
$ tox
After running ``tox``, the documentation will be available for viewing in HTML
format in the ``doc/build/`` directory.
For any further questions, please email
openstack-discuss@lists.openstack.org or join #openstack-dev on
OFTC.
-274
View File
@@ -1,274 +0,0 @@
# -*- coding: utf-8 -*-
#
# Tempest documentation build configuration file, created by
# sphinx-quickstart on Tue May 21 17:43:32 2013.
#
# This file is execfile()d with the current directory set to its containing dir.
#
# Note that not all possible configuration values are present in this
# autogenerated file.
#
# All configuration values have a default; values that are commented out
# serve to show the default.
import datetime
import sys
import os
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
sys.path.insert(0, os.path.abspath('.'))
on_rtd = os.environ.get('READTHEDOCS', None) == 'True'
# -- General configuration -----------------------------------------------------
# If your documentation needs a minimal Sphinx version, state it here.
#needs_sphinx = '1.0'
# Add any Sphinx extension module names here, as strings. They can be extensions
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
extensions = ['redirect',
'sphinx.ext.autodoc',
'sphinx.ext.todo',
'sphinx.ext.viewcode',
'openstackdocstheme',
'yasfb',
]
# Feed configuration for yasfb
feed_base_url = 'https://specs.openstack.org/openstack/murano-specs'
feed_author = 'OpenStack Murano Team'
todo_include_todos = True
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
# The suffix of source filenames.
source_suffix = '.rst'
# The encoding of source files.
#source_encoding = 'utf-8-sig'
# The master toctree document.
master_doc = 'index'
# General information about the project.
project = u'Murano Specs'
copyright = u'%s, OpenStack Murano Team' % datetime.date.today().year
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#language = None
# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
#today = ''
# Else, today_fmt is used as the format for a strftime call.
#today_fmt = '%B %d, %Y'
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
exclude_patterns = [
'_build',
'**/template.rst',
]
# The reST default role (used for this markup: `text`) to use for all documents.
#default_role = None
# If true, '()' will be appended to :func: etc. cross-reference text.
#add_function_parentheses = True
# If true, the current module name will be prepended to all description
# unit titles (such as .. function::).
add_module_names = False
# If true, sectionauthor and moduleauthor directives will be shown in the
# output. They are ignored by default.
show_authors = False
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'native'
# A list of ignored prefixes for module index sorting.
modindex_common_prefix = ['murano-specs.']
# openstackdocstheme options
openstackdocs_repo_name = 'openstack/murano-specs'
openstackdocs_bug_project = 'murano'
openstackdocs_bug_tag = ''
# -- Options for man page output ----------------------------------------------
man_pages = []
# -- Options for HTML output ---------------------------------------------------
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
#html_theme_options = {}
# Add any paths that contain custom themes here, relative to this directory.
#html_theme_path = []
# The name for this set of Sphinx documents. If None, it defaults to
# "<project> v<release> documentation".
#html_title = None
# A shorter title for the navigation bar. Default is the same as html_title.
#html_short_title = None
# The name of an image file (relative to this directory) to place at the top
# of the sidebar.
#html_logo = None
# The name of an image file (within the static path) to use as favicon of the
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large.
#html_favicon = None
# If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities.
#html_use_smartypants = True
# Custom sidebar templates, maps document names to template names.
#html_sidebars = {}
# Additional templates that should be rendered to pages, maps page names to
# template names.
#html_additional_pages = {}
# If false, no module index is generated.
html_domain_indices = False
# If false, no index is generated.
html_use_index = False
# If true, the index is split into individual pages for each letter.
#html_split_index = False
# If true, links to the reST sources are added to the pages.
#html_show_sourcelink = True
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
#html_show_sphinx = True
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
#html_show_copyright = True
# If true, an OpenSearch description file will be output, and all pages will
# contain a <link> tag referring to it. The value of this option must be the
# base URL from which the finished HTML is served.
#html_use_opensearch = ''
# This is the file name suffix for HTML files (e.g. ".xhtml").
#html_file_suffix = None
# Output file base name for HTML help builder.
htmlhelp_basename = 'Murano-Specsdoc'
# -- Options for LaTeX output --------------------------------------------------
latex_elements = {
# The paper size ('letterpaper' or 'a4paper').
#'papersize': 'letterpaper',
# The font size ('10pt', '11pt' or '12pt').
#'pointsize': '10pt',
# Additional stuff for the LaTeX preamble.
#'preamble': '',
}
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title, author, documentclass [howto/manual]).
latex_documents = [
('index', 'Murano-specs.tex', u'Murano Specs',
u'OpenStack Murano Team', 'manual'),
]
# The name of an image file (relative to this directory) to place at the top of
# the title page.
#latex_logo = None
# For "manual" documents, if this is true, then toplevel headings are parts,
# not chapters.
#latex_use_parts = False
# If true, show page references after internal links.
#latex_show_pagerefs = False
# If true, show URL addresses after external links.
#latex_show_urls = False
# Documents to append as an appendix to all manuals.
#latex_appendices = []
# If false, no module index is generated.
#latex_domain_indices = True
# -- Options for Texinfo output ------------------------------------------------
# Grouping the document tree into Texinfo files. List of tuples
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents = [
('index', 'Murano-specs', u'Murano Design Specs',
u'OpenStack Murano Team', 'murano-specs', 'Design specifications for the Murano project.',
'Miscellaneous'),
]
# Documents to append as an appendix to all manuals.
#texinfo_appendices = []
# If false, no module index is generated.
#texinfo_domain_indices = True
# How to display URL addresses: 'footnote', 'no', or 'inline'.
#texinfo_show_urls = 'footnote'
# -- Options for Epub output ---------------------------------------------------
# Bibliographic Dublin Core info.
epub_title = u'Murano Specs'
epub_author = u'OpenStack Murano Team'
epub_publisher = u'OpenStack Murano Team'
epub_copyright = u'2014, OpenStack Murano Team'
# The language of the text. It defaults to the language option
# or en if the language is not set.
#epub_language = ''
# The scheme of the identifier. Typical schemes are ISBN or URL.
#epub_scheme = ''
# The unique identifier of the text. This can be a ISBN number
# or the project homepage.
#epub_identifier = ''
# A unique identification for the text.
#epub_uid = ''
# A tuple containing the cover image and cover page html template filenames.
#epub_cover = ()
# HTML files that should be inserted before the pages created by sphinx.
# The format is a list of tuples containing the path and title.
#epub_pre_files = []
# HTML files shat should be inserted after the pages created by sphinx.
# The format is a list of tuples containing the path and title.
#epub_post_files = []
# A list of files that should not be packed into the epub file.
#epub_exclude_files = []
# The depth of the table of contents in toc.ncx.
#epub_tocdepth = 3
# Allow duplicate toc entries.
#epub_tocdup = True
-78
View File
@@ -1,78 +0,0 @@
.. murano-specs documentation master file
=====================
Murano Specifications
=====================
Kilo specs:
.. toctree::
:glob:
:maxdepth: 1
specs/kilo/*
Liberty specs:
.. toctree::
:glob:
:maxdepth: 1
specs/liberty/*
Mitaka specs:
.. toctree::
:glob:
:maxdepth: 1
specs/mitaka/*
Newton specs:
.. toctree::
:glob:
:maxdepth: 1
specs/newton/approved/*
specs/newton/implemented/*
Ocata specs:
.. toctree::
:glob:
:maxdepth: 1
specs/ocata/approved/*
Pike specs:
.. toctree::
:glob:
:maxdepth: 1
specs/pike/approved/*
Queens specs:
.. toctree::
:glob:
:maxdepth: 1
specs/queens/approved/*
==========================
Murano apps Specifications
==========================
.. toctree::
:glob:
:maxdepth: 1
specs/murano-apps/*
==================
Indices and tables
==================
* :ref:`search`
-50
View File
@@ -1,50 +0,0 @@
# A simple sphinx plugin which creates HTML redirections from old names
# to new names. It does this by looking for files named "redirect" in
# the documentation source and using the contents to create simple HTML
# redirection pages for changed filenames.
# Stolen from openstack/nova-specs
import os.path
from sphinx.util import logging
LOG = logging.getLogger(__name__)
def process_redirect_file(app, path, ent):
parent_path = path.replace(app.builder.srcdir, app.builder.outdir)
with open(os.path.join(path, ent)) as redirects:
for line in redirects.readlines():
from_path, to_path = line.rstrip().split(' ')
from_path = from_path.replace('.rst', '.html')
to_path = to_path.replace('.rst', '.html')
redirected_filename = os.path.join(parent_path, from_path)
redirected_directory = os.path.dirname(redirected_filename)
if not os.path.exists(redirected_directory):
os.makedirs(redirected_directory)
with open(redirected_filename, 'w') as f:
f.write('<html><head><meta http-equiv="refresh" content="0; '
'url=%s" /></head></html>'
% to_path)
def emit_redirects(app, exc):
LOG.info('scanning %s for redirects...', app.builder.srcdir)
def process_directory(path):
for ent in os.listdir(path):
p = os.path.join(path, ent)
if os.path.isdir(p):
process_directory(p)
elif ent == 'redirects':
LOG.info(' found redirects at %s' % p)
process_redirect_file(app, path, ent)
process_directory(app.builder.srcdir)
LOG.info('...done')
def setup(app):
app.connect('build-finished', emit_redirects)
-1
View File
@@ -1 +0,0 @@
../../specs
-10
View File
@@ -1,10 +0,0 @@
# The order of packages is significant, because pip processes them in the order
# of appearance. Changing the order has an impact on the overall integration
# process, which may cause wedges in the gate later.
pbr>=2.0.0,!=2.1.0 # Apache-2.0
sphinx>=2.0.0,!=2.1.0 # BSD
testrepository>=0.0.18 # Apache-2.0/BSD
testtools>=1.4.0 # MIT
yasfb>=0.8.0
openstackdocstheme>=2.2.1 # Apache-2.0
-12
View File
@@ -1,12 +0,0 @@
[metadata]
name = murano-specs
summary = OpenStack Murano Project Development Specs
description-file =
README.rst
author = OpenStack
author-email = openstack-discuss@lists.openstack.org
home-page = http://specs.openstack.org/openstack/murano-specs/
classifier =
Intended Audience :: Developers
License :: OSI Approved :: Apache Software License
Operating System :: POSIX :: Linux
-22
View File
@@ -1,22 +0,0 @@
#!/usr/bin/env python
# Copyright (c) 2013 Hewlett-Packard Development Company, L.P.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# THIS FILE IS MANAGED BY THE GLOBAL REQUIREMENTS REPO - DO NOT EDIT
import setuptools
setuptools.setup(
setup_requires=['pbr>=2.0'],
pbr=True)
-542
View File
@@ -1,542 +0,0 @@
..
This work is licensed under a Creative Commons Attribution 3.0 Unported
License.
http://creativecommons.org/licenses/by/3.0/legalcode
==========================================
Environment Template Catalogue
==========================================
https://blueprints.launchpad.net/murano/+spec/blueprint-template
Problem description
===================
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.
Proposed change
===============
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.
::
{
"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": "tomcat",
"port": "8080",
"?": {
"type": "io.murano.apps.apache.Tomcat",
"id": "54cea43d-5970-4c73-b9ac-fea656f3c722"
}
}
]
}
Alternatives
------------
None
Data model impact
-----------------
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:
template :-
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)
REST API impact
---------------
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
::
{
'name': 'env_template_name'
}
2.- Specification of all the services
::
{
"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"
}
}
]
}
*Response*
::
{
"updated": "2015-01-26T09:12:51",
"networking":
{
},
"name": "template_name",
"created": "2015-01-26T09:12:51",
"tenant_id": "00000000000000000000000000000001",
"version": 0,
"id": "aa9033ca7ce245fca10e38e1c8c4bbf7",
}
+----------------+-----------------------------------------------------------+
| Code | Description |
+================+===========================================================+
| 200 | OK. Environment Template created successfully |
+----------------+-----------------------------------------------------------+
| 401 | User is not authorized to access this session |
+----------------+-----------------------------------------------------------+
| 409 | The environment template already exists |
+----------------+-----------------------------------------------------------+
**GET /templates/{env-temp-id}**
*Request*
+----------+--------------------------------+-------------------------------------------------+
| Method | URI | Description |
+==========+================================+=================================================+
| GET | /templates/{env-temp-id} | Obtains the environment template information |
+----------+--------------------------------+-------------------------------------------------+
*Parameters:*
* `env-temp-id` - environment template ID, required
*Content-Type*
application/json
*Response*
::
{
"updated": "2015-01-26T09:12:51",
"networking":
{
},
"name": "template_name",
"created": "2015-01-26T09:12:51",
"tenant_id": "00000000000000000000000000000001",
"version": 0,
"id": "aa9033ca7ce245fca10e38e1c8c4bbf7",
}
+----------------+-----------------------------------------------------------+
| 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
* payload - the service description
*Content-Type*
application/json
*Example*
::
{
"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"
}
}
*Response*
::
{
"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",
"?":
{
"type": "io.murano.apps.apache.Tomcat",
"id": "54cea43d-5970-4c73-b9ac-fea656f3c722"
},
"port": "8080"
}
+----------------+-----------------------------------------------------------+
| Code | Description |
+================+===========================================================+
| 200 | OK. Application added successfully |
+----------------+-----------------------------------------------------------+
| 401 | User is not authorized to access this session |
+----------------+-----------------------------------------------------------+
| 404 | The environment template does not exit |
+----------------+-----------------------------------------------------------+
**GET /templates/{env-temp-id}/services***
Request*
+----------+-------------------------------------+-----------------------------------+
| Method | URI | Description |
+==========+=====================================+===================================+
| GET | /templates/{env-temp-id}/services | It obtains the service description|
+----------+-------------------------------------+-----------------------------------+
*Parameters:*
* `env-temp-id` - The environment template ID, required
*Content-Type*
application/json
*Response*
::
[
{
"instance":
{
"assignFloatingIp": "true",
"keyname": "mykeyname",
"image": "cloud-fedora-v3",
"flavor": "m1.medium",
"?":
{
"type": "io.murano.resources.LinuxMuranoInstance",
"id": "ef984a74-29a4-45c0-b1dc-2ab9f075732e"
}
},
"name": "tomcat",
"?":
{
"type": "io.murano.apps.apache.Tomcat",
"id": "54cea43d-5970-4c73-b9ac-fea656f3c722"
},
"port": "8080"
},
{
"instance": "ef984a74-29a4-45c0-b1dc-2ab9f075732e",
"password": "XXX",
"name": "mysql",
"?":
{
"type": "io.murano.apps.database.MySQL",
"id": "54cea43d-5970-4c73-b9ac-fea656f3c722"
}
}
]
+----------------+-----------------------------------------------------------+
| Code | Description |
+================+===========================================================+
| 200 | OK. Tier created successfully |
+----------------+-----------------------------------------------------------+
| 401 | User is not authorized to access this session |
+----------------+-----------------------------------------------------------+
| 404 | The environment template does not exit |
+----------------+-----------------------------------------------------------+
**POST /templates/{env-temp-id}/create-environment**
*Request*
+----------+--------------------------------------------+--------------------------------------+
| Method | URI | Description |
+==========+============================================+======================================+
| POST | /templates/{env-temp-id}/create-environment| Create an environment |
+----------+--------------------------------------------+--------------------------------------+
*Parameters:*
* `env-temp-id` - The environment template ID, required
*Payload:*
* 'environment name': The environment name to be created.
*Content-Type*
application/json
*Example*
::
{
'name': 'environment_name'
}
*Response*
::
{
"environment_id": "aa90fadfafca10e38e1c8c4bbf7",
"name": "environment_name",
"created": "2015-01-26T09:12:51",
"tenant_id": "00000000000000000000000000000001",
"version": 0,
"session_id": "adf4dadfaa9033ca7ce245fca10e38e1c8c4bbf7",
}
+----------------+-----------------------------------------------------------+
| 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 |
+----------------+-----------------------------------------------------------+
Versioning impact
-------------------------
Murano client will change to include this new functionality.
Other end user impact
---------------------
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
Deployer impact
---------------
None
Developer impact
----------------
None
Murano-dashboard / Horizon impact
---------------------------------
New views will be required for including the environment template functionality
Implementation
==============
Assignee(s)
-----------
Primary assignee:
hmunfru
Other contributors:
jesuspg
TBC
Work Items
----------
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
Dependencies
============
Testing
=======
TBD
Documentation Impact
====================
Environment template documentation should be included.
References
==========
https://etherpad.openstack.org/p/GLLAQ0m1H7
-224
View File
@@ -1,224 +0,0 @@
..
This work is licensed under a Creative Commons Attribution 3.0 Unported
License.
http://creativecommons.org/licenses/by/3.0/legalcode
==============================
Configuration Language Support
==============================
https://blueprints.launchpad.net/murano/+spec/conf-language-support
Problem description
===================
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.
Proposed change
===============
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:
::
## 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
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::
{
orion::ports: 1026
orion::dbname: oriondb
"run_list": [
"recipe[orion::0.13.0_install]"
]
}
#. Executing chef-solo:
chef-solo -j node.json
For puppet,
#. Generating the manifest (site.pp)::
node 'default'
{
class{
'orion::install':
}
}
#. Creating the hiera data information: hiera.yaml::
## YAML Template.
---
orion::port: 1026
orion::dbname: oriondb
#. Executing:
puppet apply --hiera_config=hiera.yaml --modulepath=/opt/puppet/modules/orion site.pp
Alternatives
------------
None
Data model impact
-----------------
None
REST API impact
---------------
None
Versioning impact
-------------------------
None
Other end user impact
---------------------
None
Deployer impact
---------------
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.
Developer impact
----------------
None
Murano-dashboard / Horizon impact
---------------------------------
None
Implementation
==============
Assignee(s)
-----------
Primary assignee:
hmunfru
Other contributors:
jesuspg
Work Items
----------
#. Generate Chef executor
#. Generate Puppet executor
#. Work on configuration
Dependencies
============
None
Testing
=======
Integration tests will be done
Documentation Impact
====================
Information about how to defines application for Puppet and Chef will have
to be documented, explaining the different fields.
References
==========
* http://es.slideshare.net/hmunfru/fiware-and-murano-support-for-configuration-languages
* https://etherpad.openstack.org/p/conf-language-support-spec
-189
View File
@@ -1,189 +0,0 @@
..
This work is licensed under a Creative Commons Attribution 3.0 Unported
License.
http://creativecommons.org/licenses/by/3.0/legalcode
======================================================
Policy Guided Fulfillment - Congress Support in Murano
======================================================
URL of launchpad blueprint:
https://blueprints.launchpad.net/murano/+spec/congress-support-in-murano
Problem description
===================
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.
Proposed change
===============
We need to provide
* python congress client in Murano
We will use simulation feature of `congress API
<https://docs.google.com/document/d/14hM7-GSm3CcyohPT2Q7GalyrQRohVcx77hx
Ex4AO4Bk/edit#heading=h.ll03wo2z9pcb>`_.
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
Murano To Congress Mapping Details
----------------------------------
This section provides congress schema created for Murano environment mapping.
It will be created by Congress datasource drivers - see `murano driver spec
<https://blueprints.launchpad.net/congress/+spec/murano-driver>`_ .
* **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' ).
Alternatives
------------
None
Data model impact
-----------------
None
REST API impact
---------------
None
Versioning impact
-----------------
None
Other end user impact
---------------------
None
Deployer impact
---------------
None
Developer impact
----------------
None
Murano-dashboard / Horizon impact
---------------------------------
None
Implementation
==============
Assignee(s)
-----------
Primary assignee:
filip-blaha
Other contributors:
ondrej-vojta, radek-pospisil
Work Items
----------
1. Introduce Congress python client into Murano
2. Implement mapping of Murano Environment into Congress simulation API
update-sequence.
3. Provide tests
Dependencies
============
* Congress python client ( `GIT <https://opendev.org/openstack/python-congressclient>`_ )
will be added into Murano.
* *Murano datasource driver* in Congress `murano driver spec
<https://blueprints.launchpad.net/congress/+spec/murano-driver>`_
Testing
=======
Testing will use predefined Congress policy rules in order to test client and
mapping. See https://etherpad.openstack.org/p/policy-congress-murano-spec for
an example mapping and test.
Documentation Impact
====================
Documentation impact is specified in `Policy Enforcement Point <https://bluepri
nts.launchpad.net/murano/+spec/policy-enforcement-point>`_ blueprint.
References
==========
* *Murano datasource driver* in Congress
https://blueprints.launchpad.net/congress/+spec/murano-driver
* https://blueprints.launchpad.net/murano/+spec/policy-enforcement-point
* https://etherpad.openstack.org/p/policy-congress-murano-spec
-309
View File
@@ -1,309 +0,0 @@
..
This work is licensed under a Creative Commons Attribution 3.0 Unported
License.
http://creativecommons.org/licenses/by/3.0/legalcode
====================================================
Provide opportunity to manage application categories
====================================================
https://blueprints.launchpad.net/murano/+spec/enable-category-management
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.
Problem description
===================
Category management should be provided during:
* Packages uploading in dashboard;
* Packages modifying in dashboard;
* Packages uploading or modifying via command line;
Adding new category:
* Category name may contain spaces and other special characters;
* Category name limit is equal to 80 characters;
* Only admin users can add new category;
Deleting category:
* Category may be deleted only if no packages belong to this category;
* Only admin users can delete category;
Proposed change
===============
Changes required to support this feature:
* 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;
Alternatives
------------
Admin can edit a database to add or delete categories.
Data model impact
-----------------
None
REST API impact
---------------
**GET /catalog/categories**
The previous call /catalog/packages/categories is will still be valid to
support backward compatibility.
*Request*
+----------+----------------------------------+----------------------------------+
| Method | URI | Description |
+==========+==================================+==================================+
| Get | /catalog/categories | Get list of existing categories |
+----------+----------------------------------+----------------------------------+
*Response*
::
{"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
}]
}
**GET /catalog/categories/<category_id>**
*Request*
+----------+-----------------------------------+----------------------------------+
| Method | URI | Description |
+==========+===================================+==================================+
| Get | /catalog/categories/<category_id> | Get category detail |
+----------+-----------------------------------+----------------------------------+
*Parameters*
* `category_id` - category ID, required
*Response*
::
{
"id": "0420045dce7445fabae7e5e61fff9e2f",
"updated": "2014-12-26T13:57:04",
"packages": [
"Apache HTTP Server",
"Apache Tomcat",
"PostgreSQL"
],
"name": "Web",
"created": "2014-12-26T13:57:04"
}
+----------------+-----------------------------------------------------------+
| Code | Description |
+================+===========================================================+
| 200 | OK. Category retrieved successfully |
+----------------+-----------------------------------------------------------+
| 401 | User is not authorized to access this session |
+----------------+-----------------------------------------------------------+
| 404 | Not found. Specified category doesn`t exist |
+----------------+-----------------------------------------------------------+
**POST /catalog/categories**
+----------------------+------------+--------------------------------------------------------+
| Attribute | Type | Description |
+======================+============+========================================================+
| name | string | Category name |
+----------------------+------------+--------------------------------------------------------+
*Request*
+----------+----------------------------------+----------------------------------+
| Method | URI | Description |
+==========+==================================+==================================+
| POST | /catalog/categories | Create new category |
+----------+----------------------------------+----------------------------------+
*Content-Type*
application/json
*Example*
{"name": "category_name"}
*Response*
::
{
"id": "ce373a477f211e187a55404a662f968",
"name": "category_name",
"created": "2013-11-30T03:23:42Z",
"updated": "2013-11-30T03:23:44Z",
}
+----------------+-----------------------------------------------------------+
| Code | Description |
+================+===========================================================+
| 200 | OK. Category created successfully |
+----------------+-----------------------------------------------------------+
| 401 | User is not authorized to access this session |
+----------------+-----------------------------------------------------------+
| 403 | Forbidden. Category with specified name already exist |
+----------------+-----------------------------------------------------------+
**DELETE /catalog/categories**
*Request*
+----------+-----------------------------------+-----------------------------------+
| Method | URI | Description |
+==========+===================================+===================================+
| DELETE | /catalog/categories/<category_id> | Delete category with specified id |
+----------+-----------------------------------+-----------------------------------+
*Parameters:*
* `category_id` - category ID, required
*Response*
+----------------+-----------------------------------------------------------+
| Code | Description |
+================+===========================================================+
| 200 | OK. Category deleted successfully |
+----------------+-----------------------------------------------------------+
| 401 | User is not authorized to access this session |
+----------------+-----------------------------------------------------------+
| 404 | Not found. Specified category doesn`t exist |
+----------------+-----------------------------------------------------------+
| 403 | Forbidden. Category with specified name is assigned to |
| | the package, presented in the catalog. Only empty |
| | categories can be removed |
+----------------+-----------------------------------------------------------+
Versioning impact
-----------------
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.
Other end user impact
---------------------
None
Murano-dashboard / Horizon impact
---------------------------------
Category management will be available in dashboard.
Areas to be changed: (described in sections above)
* Manage section will have new panel;
Deployer impact
---------------
None
Developer impact
----------------
None
Implementation
==============
Assignee(s)
-----------
Ekaterina Chernova
Primary assignee:
<efedorova@mirantis.com>
Work Items
----------
* Introduce 2 additional calls in API
* Update API specification
* Provide these calls in python-muranoclient
* Implement changes in dashboard
* Enable CLI to manage categories
Dependencies
============
None
Testing
=======
New tests should be added in dashboard integration tests
Documentation Impact
====================
API specification should be updated.
All changes are already represented here, just need to copy.
References
==========
None
-165
View File
@@ -1,165 +0,0 @@
..
This work is licensed under a Creative Commons Attribution 3.0 Unported
License.
http://creativecommons.org/licenses/by/3.0/legalcode
==================================
Add timeouts to murano-agent calls
==================================
https://blueprints.launchpad.net/murano/+spec/murano-agent-timeouts
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.
Problem description
===================
* During the agent`s work there could be some problems with execution of scripts and
VM may hang. In this case user will wait indefinitely without knowing
what's happened.
* 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 solves these problems.
Proposed change
===============
1) 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::
- $.instance.agent.call($template, $resources, 300)
If the agent plan execution time exceeds the limit, it will be terminated.
2) 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::
template = {'Body': 'return', 'FormatVersion': '2.0.0', 'Scripts': {}}
and sends this plan once to agent by method *call*. It can be used by developer
to stop deployment before sending template of app if agent is inaccessible as
follows::
- $.instance.agent.waitReady()
- $.instance.agent.call($template, $resources)
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.
3) Add new method *isReady* in Agent class.
This method will 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/common/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.
Alternatives
------------
None
Data model impact
-----------------
None
REST API impact
---------------
None
Versioning impact
-------------------------
None
Other end user impact
---------------------
None
Deployer impact
---------------
None
Developer impact
----------------
None
Murano-dashboard / Horizon impact
---------------------------------
None
Implementation
==============
Assignee(s)
-----------
Primary assignee:lk
ddovbii
Work Items
----------
The change is simple and can be done in one Gerrit patch. Implementation is
acutally completed.
Dependencies
============
None
Testing
=======
Unit and integration tests must be done.
Documentation Impact
====================
MuranoPL specification should be updated.
References
==========
None
-141
View File
@@ -1,141 +0,0 @@
..
This work is licensed under a Creative Commons Attribution 3.0 Unported
License.
http://creativecommons.org/licenses/by/3.0/legalcode
==========================
murano-mistral-integration
==========================
https://blueprints.launchpad.net/murano/+spec/murano-mistral-integration-1
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.
Problem description
===================
A new capability in Murano modeling process should be added in order to answer
several use cases, including:
#. The application modeler wishes to leverage existing workflow that deploys
a specific component as part of a new application model creation process.
#. The application modeler wishes to add post-deployment logic to an
application model.
For example:
a. Check that the application has been successfully deployed.
b. Inject initial data to the deployed application.
Proposed change
===============
Adding a new system class for Mistral Client that allows to call Mistral
APIs from the Murano application model.
The system class will allow you to:
#. Upload a Mistral workflow to Mistral.
#. Trigger the already-deployed Mistral workflow, wait for completion and
return the execution output.
Alternatives
------------
None
Data model impact
-----------------
None
REST API impact
---------------
None
Versioning impact
-----------------
None
Other end user impact
---------------------
None
Deployer impact
---------------
None
Developer impact
----------------
None
Murano-dashboard / Horizon impact
---------------------------------
None
Implementation
==============
Assignee(s)
-----------
Primary assignee:
Natasha Beck
Work Items
----------
#. Add mistral client system class that can trigger pre-deployed Mistral
workflow.
#. Add ability to the client to upload the Mistral workflow.
#. Add test that deploys application which uploads the Mistral workflow from
Resources, triggers it and gets output as a result.
Dependencies
============
Openstack Mistral component.
Testing
=======
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.
Documentation Impact
====================
Murano-Mistral integration must be documented from the following perspectives:
* Setup configuration (for example with and without mistral)
* Include usage of Mistral workflow as a part of an application model
The following Murano documentation will be affected:
* Murano Installation Guide
Add section on Mistral requirement
* Murano Workflow
Add section on Murano-Mistral integration
* Murano Article (new)
Article on Murano-Mistral integration
References
==========
None
@@ -1,190 +0,0 @@
..
This work is licensed under a Creative Commons Attribution 3.0 Unported
License.
http://creativecommons.org/licenses/by/3.0/legalcode
=========================
Murano Repository Support
=========================
https://blueprints.launchpad.net/murano/+spec/muranoclient-marketplace-support
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.
Problem description
===================
Typical use cases:
* 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.
Proposed change
===============
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.
Alternatives
------------
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.
Data model impact
-----------------
It might be a good idea to store information about required apps and required
images, although it is not strictly required for the task.
REST API impact
---------------
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.
Versioning impact
-----------------
This proposition adds functionality both to python-muranoclient and to
murano-dashboard. It should be fully backward compatible.
Minor version of python-muranoclient should be increased, because we add
functionality.
Other end user impact
---------------------
See *Proposed Change* section, as it describes all the ways users would
interact with the feature
Deployer impact
---------------
None
Developer impact
----------------
None
Murano-dashboard / Horizon impact
---------------------------------
Package import dialog should be changed to reflect different ways of
importing an application.
Additional bundle-import dialog should be implemented.
Implementation
==============
Assignee(s)
-----------
Primary assignee:
<kzaitsev@mirantis.com>
Work Items
----------
* Add support for importing packages by url in client
* Add support for importing packages by name in client
* Add support for importing bundles by name/url in client
* Add support for recursive parsing of Require section of `manifest.yaml`
file in client
* Add support for image download/upload from `images.lst` file in client
* Handle `package exists` error in CLI client
* Add support for different ways to import a package in murano-dashboard
* Add support for bundle-import in murano-dashboard
* Add support for image/package requirements while importing packages and
bundles in murano-dashboard
Dependencies
============
None
Testing
=======
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`.
Documentation Impact
====================
Additional capabilities of the CLI client should be documented, otherwise
there should be no impact, since we do not change the API.
References
==========
None
-1
View File
@@ -1 +0,0 @@
../template.rst
-221
View File
@@ -1,221 +0,0 @@
..
This work is licensed under a Creative Commons Attribution 3.0 Unported
License.
http://creativecommons.org/licenses/by/3.0/legalcode
====================================
Plugable pythonic classes for Murano
====================================
https://blueprints.launchpad.net/murano/+spec/plugable-classes
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.
Problem description
===================
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.
Proposed change
===============
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.
Alternatives
------------
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.
Data model impact
-----------------
This proposal does not affect data model.
REST API impact
---------------
N/A
Versioning impact
-----------------
N/A
Other end user impact
---------------------
N/A
Deployer impact
---------------
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.
Developer impact
----------------
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`.
Murano-dashboard / Horizon impact
---------------------------------
No immediate changes required.
Implementation
==============
Assignee(s)
-----------
Primary assignee:
ativelkov
Work Items
----------
* Implement the PluginLoader class
* Modify MuranoEngine to register plugin-imported classes in class loader.
Dependencies
============
This requires stevedore library as a dependency. It is already part of
OpenStack Global Requirements, so no problems are expected.
Testing
=======
The unit-tests have to cover PluginLoader class using the make_test_instance
method of stevedore.
Separated tests should cover API method call.
Tempest tests are out of the scope of this spec.
Documentation Impact
====================
There should be created a "Plugin developer's Manual" which will describe the
process of plugin package creation.
References
==========
[1] http://docs.openstack.org/developer/stevedore/
[2] http://docs.openstack.org/developer/stevedore/managers.html#enabledextensionmanager
-207
View File
@@ -1,207 +0,0 @@
..
This work is licensed under a Creative Commons Attribution 3.0 Unported
License.
http://creativecommons.org/licenses/by/3.0/legalcode
====================================================
Policy Guided Fulfillment - Policy Enforcement Point
====================================================
URL of launchpad blueprint:
https://blueprints.launchpad.net/murano/+spec/policy-enforcement-point
Problem description
===================
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
* *message* text message of error
Murano environment serialization/decomposition is described in `Congress Support in Murano <https://blueprints.launchpad.net/murano/+spec/congress-support-in-murano>`_ and `Murano Congress Driver <https://blueprints.launchpad.net/congress/+spec/murano-driver>`_
Example (generic):
::
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) :- ....
Example (allow only environments where all VM instances has flavor with max 2048MB RAM):
::
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)
Enforcement point will use Congress simulation api to evaluate rules on passed mapped environment into Congress schema.
Proposed change
===============
When user executes *deploy* action on an environment following steps will be done
* environment will be mapped into *update sequence*
* Congress simulation API will be executed:
::
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
* if response will contain non empty result, then deployment will fails
Alternatives
------------
None
Data model impact
-----------------
None
REST API impact
---------------
None
Versioning impact
-------------------------
None
Other end user impact
---------------------
Environment deployment may fail due to policy validation failure.
Deployer impact
---------------
Policy enforcement will be used only if
* Enforcement is enabled in *murano.conf*
* Congress is available in Keystone catalog (i.e., it is deployed in OpenStack)
Developer impact
----------------
None
Murano-dashboard / Horizon impact
---------------------------------
None
Implementation
==============
Assignee(s)
-----------
Primary assignee:
ondrej-vojta
Other contributors:
filip-blaha, radek-pospisil
Work Items
----------
1. 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)
2. Provide Developer and User Documentation (see Documentation section).
Dependencies
============
* *Congress Support in Murano* https://blueprints.launchpad.net/congress/+spec/murano-driver
* *Murano datasource driver* in Congress https://blueprints.launchpad.net/congress/+spec/murano-driver
* *Policy enforcement specification* https://etherpad.openstack.org/p/policy-congress-murano-spec
Testing
=======
Unit and integration tests must be done.
Integration tests must cover following setups
* Openstack has Congress installed
* situations when Congress is running (i.e., responding) and not running (i.e., not responding) must be tested
* Openstack has not Congress installed
Documentation Impact
====================
Policy enforcement must be documented from following perspectives
* Setup configuration (e.g., with and without congress)
* Murano rules (i.e., Murano environment data decompositiion) in Murano policy
* How Murano policy affects environment deployment
Following Murano documentation will be affected
* Murano Installation Guide
Add section on Congress requirement and section on enabling policy enforcement
* Murano Workflow
Add section on Murano policy enforcement
* Murano Article (new)
Article on Murano policy rules (e.g., Murano environment decomposition to Congress)
References
==========
* *Congress Support in Murano* https://blueprints.launchpad.net/congress/+spec/murano-driver
* *Murano datasource driver* in Congress https://blueprints.launchpad.net/congress/+spec/murano-driver
* *Policy enforcement specification* https://etherpad.openstack.org/p/policy-congress-murano-spec
@@ -1,215 +0,0 @@
..
This work is licensed under a Creative Commons Attribution 3.0 Unported
License.
http://creativecommons.org/licenses/by/3.0/legalcode
=================================
Add support for heat environments
=================================
https://blueprints.launchpad.net/murano/+spec/add-support-for-heat-environments-and-files
Add support for using Heat environments, when saving and deploying Heat
templates.
Problem description
===================
Today there is no option to create stacks neither with an environment nor with
nested stacks via Murano. Only basic stacks are supported.
Use cases for deploying a stack with an environment:
* Supporting resource registry
* Supporting saving 'test' and 'production' parameter profiles for the same
template
Proposed change
===============
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.
Alternatives
------------
* The package structure can be different.
* 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.
Data model impact
-----------------
new data objects:
* 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.
REST API impact
---------------
None
Versioning impact
-----------------
None
Other end user impact
---------------------
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.
Deployer impact
---------------
None
Developer impact
----------------
None
Murano-dashboard / Horizon impact
---------------------------------
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.
Implementation
==============
new data objects:
* envs
* env_name
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-23\n\nparameters:\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-23\n\nparameters:\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.
Assignee(s)
-----------
Primary assignee:
michal-gershenzon
Other contributors:
noa-koffman
Work Items
----------
* 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.
Dependencies
============
None
Testing
=======
Unit tests should cover API calls changes:
* Test sending a Heat environment when adding a package to a Murano environment
(positive and negative).
* Test that the request for Heat is build correctly with Heat environment
Documentation Impact
====================
None
References
==========
* http://docs.openstack.org/developer/heat/template_guide/environment.html
@@ -1,168 +0,0 @@
..
This work is licensed under a Creative Commons Attribution 3.0 Unported
License.
http://creativecommons.org/licenses/by/3.0/legalcode
===========================================
Add support for heat environments and files
===========================================
https://blueprints.launchpad.net/murano/+spec/add-support-for-heat-environments-and-files
Add support for using Heat additional files, when saving and deploying Heat
templates.
Problem description
===================
Today there is no option to create stacks neither with an environment nor with
nested stacks via Murano. Only basic stacks are supported.
Use cases for deploying a stack with additional files:
* Supporting Heat nested stacks
* Supporting scripts
For more information see references section of this spec
Proposed change
===============
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.
Alternatives
------------
* The package structure can be different.
Data model impact
-----------------
None
REST API impact
---------------
None
Versioning impact
-----------------
None
Other end user impact
---------------------
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.
Deployer impact
---------------
None
Developer impact
----------------
None
Murano-dashboard / Horizon impact
---------------------------------
None.
Implementation
==============
new data objects:
* files
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.
Assignee(s)
-----------
Primary assignee:
michal-gershenzon
Other contributors:
noa-koffman
Work Items
----------
* 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.
Dependencies
============
None
Testing
=======
Unit tests should cover API calls changes:
* Test that the request for Heat is build correctly with Heat files
Documentation Impact
====================
None
References
==========
* http://docs.openstack.org/developer/heat/template_guide/hot_spec.html#get-file
@@ -1,214 +0,0 @@
..
This work is licensed under a Creative Commons Attribution 3.0 Unported
License.
http://creativecommons.org/licenses/by/3.0/legalcode
===========================
Artifact Repository Support
===========================
https://blueprints.launchpad.net/murano/+spec/artifact-repository-support
Glance has recently got a new feature - ability to store not only the VM images
but also data assets and their metadata for other OpenStack projects.
This specification defines the usage of this feature in Murano, so Murano may
store its packages in Glance and benefit from all its features.
Problem description
===================
The current implementation of Murano Package Repository as part of murano-api
has the following major drawbacks:
* Code duplication. Lot's of the logic to manage the packages is very similar
for other OpenStack projects. Sharing that code with others will help to
improve the overall quality of OpenStack ecosystem.
* Database storage is a bad idea. Currently we store all the murano-packages as
blob fields in the database tables. This dramatically decreases the
performance and limits the maximum size of the packages, thus preventing us
from putting actual application binaries inside the packages. Using glance
for this purpose will allow us to utilize all the backing stores supported by
glance, including Swift, Ceph, S3 and others.
* No cross-package dependencies. Current implementation of package repository
does not have any concept of cross-package dependency, so MuranoPL package
loaders have to detect package dependencies only in runtime. This leads to
issues when some of the package's dependencies are not present in the repo,
but this cannot be detected until the actual deployment starts. Using glance
which has a notion of cross-artifact dependencies solves this issue natively
at the repository level.
* Image dependencies are manual. Current implementation has some manual way of
managing dependencies of murano packages to glance images. When glance is
user dependencies on Images will have the same nature as cross-package
dependencies.
* No versioning of packages. Current implementation does not allow to attach
semver-based version strings to the packages, and so no filtering is possible
by this info. Glance Artifact Repository provides a rich versioning tools and
allows to filter by specific version spec and range.
* No ability to query packages based on dependency hierarchy. We need a way to
query the repository for the classes which inherit some specific base class.
Glance Artifact Repository provides such queries out of the box.
Proposed change
===============
It is proposed to create a Glance Plugin which will define the artifact type
"Murano Package" with the following type-specific metadata attributes:
* **type** - a string defining the type of the package, may have values of
either `Application` or `Library`. Immutable. Required.
* **author** - a string defining the author of the package. Immutable.
Required.
* **display_name** - a display name for the package to be shown in the catalog.
Mutable. Required.
* **enabled** - a boolean indicating if that package is available for usage.
Proposed temporary, until Glance v3 has a support of "disable" operation for
all the types of artifacts. Mutable, True by default.
* **categories** - a set of strings containing the categories attached to the
package. Mutable.
* **class_definitions** - a set of strings containing the fully-qualified names
of muranoPL classes contained within the package. Immutable.
* **inherits** - a dictionary in which the keys are the interfaces inherited by
the classes of the packages and the values are the list of the names of these
classes. Immutable.
* **keywords** - a set of keywords to simplify the search of the package in the
catalog. Mutable.
..and the following binary objects:
* **logo** - a blob containing the logo of a package
* **archive** - a blob containing the zip archive with the package
* **ui_definition** - a blob containing the yaml-based definition of app's UI
if the one is present.
If worth noting that currently v3 of Glance API is tagged as EXPERIMENTAL, and
both its implementation and interfaces may (and will) change in Mitaka release
cycle. So, some of the plugin implementation details may have to be changed as
well in the next cycle.
Because of this, it is suggested to add this functionality as EXPERIMENTAL as
well, maintaining the old behavior as a preferred alternative, selected by
default.
Alternatives
------------
We may continue using murano-api to manage our packages, at least till the
Glance v3 is STABLE, however this will require us to introduce lots of
temporary code to support things like versioning and dependencies. So, it is
better to add the Glance support as an experimental feature, facade it under
the python-muranoclient bindings, and migrate to it completely in the next
release cycle.
Data model impact
-----------------
No impact. When the migration is complete and Glance is the only storage of
packages, we'll need to drop the old data tables which are currently storing
the old package repositories.
REST API impact
---------------
No impact.
Versioning impact
-----------------
No impact.
Other end user impact
---------------------
No impact.
Deployer impact
---------------
The deployer will have to add the glance plugin package into their environment.
It should be deployed into the same python env with the regular Glance. They'll
have to enable the V3 API in the glance-api config as well.
Developer impact
----------------
None
Murano-dashboard / Horizon impact
---------------------------------
Only the configuration changes should be made in murano-dashboard.
Implementation
==============
Assignee(s)
-----------
Primary assignee: ativelkov
Work Items
----------
* Implement a glance plugin
* Copy the artifact-specific access logic from python-glanceclient into the
python-muranoclient, as glance is not going to release v3-aware clients until
the API is stable.
* Implement artifacts adapter in python-muranoclient
Dependencies
============
* Most of the artifacts functionality has been merged to Glance by L-1
milestone. However, several important bugfixes were merged only into the RC1.
So, the latest Glance master is required.
Testing
=======
As the new backend substitutes the old one, the regular testing of
package-related actions should be sufficient.
Documentation Impact
====================
New configuration settings have to be documented.
References
==========
None
-139
View File
@@ -1,139 +0,0 @@
..
This work is licensed under a Creative Commons Attribution 3.0 Unported
License.
http://creativecommons.org/licenses/by/3.0/legalcode
=================================================================
Download bundle of packages to local directory using muranoclient
=================================================================
https://blueprints.launchpad.net/murano/+spec/bundle-save
The purpose is to add command to muranoclient which allows to download the
bundle from application catalog to local dir.
Problem description
===================
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.
Proposed change
===============
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.
Alternatives
------------
None
Data model impact
-----------------
None
REST API impact
---------------
None
Versioning impact
-------------------------
None
Other end user impact
---------------------
User will have access to a new command.
Deployer impact
---------------
None
Developer impact
----------------
None
Murano-dashboard / Horizon impact
---------------------------------
None
Implementation
==============
Assignee(s)
-----------
Dmytro Dovbii
Primary assignee:
ddovbii
Work Items
----------
* Add method *save_image_local*
* Add method *save()* to *FileWrapperMixin* class
* Implement CLI command *bundle-save*
* Implement CLI commamd *package-save*
Dependencies
============
None
Testing
=======
Unit tests for CLI client must be updated
Documentation Impact
====================
CLI reference should be updated manually
References
==========
None
@@ -1,158 +0,0 @@
..
This work is licensed under a Creative Commons Attribution 3.0 Unported
License.
http://creativecommons.org/licenses/by/3.0/legalcode
=================================
Rework package class loader logic
=================================
https://blueprints.launchpad.net/murano/+spec/change-murano-class-loader
This spec describes rework of murano package class loader as part of the
another blueprint `simulated-execution-mode-murano-engine
<https://blueprints.launchpad.net/murano/+spec/simulated-execution-mode-murano-engine>`_.
The detailed logic regarding class modification would be described in this
specification.
Problem description
===================
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.
Proposed change
===============
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.
Alternatives
------------
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 <https://docs.djangoproject.com/en/1.7/ref/settings/#std:setting-TEMPLATE_LOADERS>`_
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.
Data model impact
-----------------
None
REST API impact
---------------
None
Versioning impact
-----------------
None
Other end user impact
---------------------
None
Deployer impact
---------------
Enabling loading packages from local directory will be set up in config file.
New key in config file will be added under *[engine]* section and look
like that:
# Directory used as a way to load packages from. (string value)
# local_packages_dir = <None>
Developer impact
----------------
None
Murano-dashboard / Horizon impact
---------------------------------
None
Implementation
==============
Assignee(s)
-----------
Primary assignee:
<efedorova>
Other contributors:
<ativelkov>, <slagun>
Work Items
----------
* Implement ``CombinedPackageLoader``:
* Perform testing
Dependencies
============
* Murano Simulation Mode:
https://blueprints.launchpad.net/murano/+spec/simulated-execution-mode-murano-engine
Testing
=======
Unit tests should be added/updated.
Documentation Impact
====================
Opportunity to load apps from local directory should be described in the
documentation.
References
==========
None
@@ -1,396 +0,0 @@
..
This work is licensed under a Creative Commons Attribution 3.0 Unported
License.
http://creativecommons.org/licenses/by/3.0/legalcode
==========================================
Implement Cloud Foundry Service Broker API
==========================================
https://blueprints.launchpad.net/murano/+spec/cloudfoundry-api-support
Cloud Foundry is PaaS which supports full lifecycle from initial development,
through all testing stages, to deployment. Most well known Cloud Foundry
flavours is Cloud Foundry OSS, Pivotal Cloud Foundry and Pivotal Web Services.
If we implement Cloud Foundry Service Broker API in murano, murano apps will
be available at Cloud Foundry as services. So Cloud Foundry users will be
granted an ability to operate murano applications.
Problem description
===================
Typical scenario of Cloud Foundry and murano collaboration will look like:
1. While configuring murano enable murano service broker in config file. Provide
host and port for it.
2. Add murano Service Broker in Cloud Foundry and grant access to murano apps for
Cloud Foundry organization.
3. Provision murano app as Cloud Foundry service instance using Cloud Foundry tools.
Proposed change
===============
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. Each Cloud Foundry space will be linked
wih murano environment. 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
{
"service_id": "service-guid-here",
"plan_id": "plan-guid-here",
"organization_guid": "org-guid-here",
"space_guid": "space-guid-here",
"parameters":{
"parameter1": 1,
"parameter2": "value"
}
}
It's planned to setup a Service Broker as a separate service. Additional
options should be added to the configs. Also we want to use Cloud Foundry
experimental asynchronous operations[3].
Alternatives
------------
None
Data model impact
-----------------
None
REST API impact
---------------
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**
*Request*
+----------+-----------------------------------------------------------+-------------------------------------------+
| Method | URI | Description |
+==========+===========================================================+===========================================+
| PUT | /v2/service_instances/:instance_id?accepts_incomplete=true| Create new service resources for developer|
+----------+-----------------------------------------------------------+-------------------------------------------+
::
{
"service_id": "service-guid-here",
"plan_id": "plan-guid-here",
"organization_guid": "org-guid-here",
"space_guid": "space-guid-here"
}
*Response*
+----------------+------------------------------------------------------------+
| Code | Description |
+================+============================================================+
| | OK. May be returned if the service instance already exists |
| 200 | and the requested parameters are identical to the existing |
| | service instance. |
+----------------+------------------------------------------------------------+
| 202 | Accepted. Service instance creation is in progress. |
+----------------+------------------------------------------------------------+
| 409 | Conflict. Should be returned if the requested service |
| | instance already exists. The expected response body is “{}”|
+----------------+------------------------------------------------------------+
| 422 | Should be returned if the request did not include |
| | ?accepts_incomplete=true |
+----------------+------------------------------------------------------------+
::
{
"dashboard_url": "http://example-dashboard.com/9189kdfsk0vfnku"
}
**PATCH /v2/service_instances/:instance_id?accepts_incomplete=true**
*Request*
+----------+-----------------------------------------------------------+----------------------------------+
| Method | URI | Description |
+==========+===========================================================+==================================+
| PATCH | /v2/service_instances/:instance_id?accepts_incomplete=true| Update existing service instance |
+----------+-----------------------------------------------------------+----------------------------------+
::
{
"plan_id": "plan_guid_here"
}
*Response*
+----------------+------------------------------------------------------------+
| Code | Description |
+================+============================================================+
| 200 | Return if only the new plan matches the old one completely |
+----------------+------------------------------------------------------------+
| 202 | Accepted. Service instance update is in progress. |
+----------------+------------------------------------------------------------+
| 422 | Should be returned if the request did not include |
| | ?accepts_incomplete=true |
+----------------+------------------------------------------------------------+
**DELETE /v2/service_instances/:instance_id?accepts_incomplete=true**
+----------+-----------------------------------------------------------+-----------------------------------+
| Method | URI | Description |
+==========+===========================================================+===================================+
| DELETE | /v2/service_instances/:instance_id?accepts_incomplete=true| Delete all resources create during|
| | | the provision. |
+----------+-----------------------------------------------------------+-----------------------------------+
*Response*
+----------+--------------------------------------------------+
| Code | Description |
+==========+==================================================+
| 202 | Accepted. Service instance deletion in progress. |
+----------+--------------------------------------------------+
| 410 | Returned if service does not exist |
+----------+--------------------------------------------------+
| 422 | Should be returned if the request did not include|
| | ?accepts_incomplete=true |
+----------+--------------------------------------------------+
**PUT /v2/service_instances/:instance_id/service_bindings/:binding_id**
*Request*
+----------+----------------------------------------------------------------+----------------------------------+
| Method | URI | Description |
+==========+================================================================+==================================+
| PUT | /v2/service_instances/:instance_id/service_bindings/:binding_id| Bind service |
+----------+----------------------------------------------------------------+----------------------------------+
::
{
"plan_id": "plan_guid_here",
"service_id": "service_guid_here",
"app_guid": "app_guid_here"
}
*Response*
+----------------+------------------------------------------------------------------+
| Code | Description |
+================+==================================================================+
| 201 | 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. |
+----------------+------------------------------------------------------------------+
::
{
"credentials": {
"uri": "mysql://mysqluser:pass@mysqlhost:3306/dbname",
"username": "mysqluser",
"password": "pass",
"host": "mysqlhost",
"port": 3306,
"database": "dbname"
}
}
**DELETE /v2/service_instances/:instance_id/service_bindings/:binding_id**
*Request*
+----------+----------------------------------------------------------------+----------------------------------+
| Method | URI | Description |
+==========+================================================================+==================================+
| DELETE | /v2/service_instances/:instance_id/service_bindings/:binding_id| Unbind service |
+----------+----------------------------------------------------------------+----------------------------------+
*Response*
+----------+-----------------------------------+
| Code | Description |
+==========+===================================+
| 200 | Binding was deleted |
+----------+-----------------------------------+
| 410 | Returned if binding does not exist|
+----------+-----------------------------------+
**GET /v2/service_instances/:instance_id/last_operation**
*Request*
+----------+--------------------------------------------------+-------------------------------+
| Method | URI | Description |
+==========+==================================================+===============================+
| GET | /v2/service_instances/:instance_id/last_operation| Polling status of the last 202|
| | | operation |
+----------+--------------------------------------------------+-------------------------------+
*Response*
+----------+--------------------------------------------------------+
| Code | Description |
+==========+========================================================+
| 200 | OK |
+----------+--------------------------------------------------------+
| 410 | GONE. Appropriate only for asynchronous delete requests|
| | Cloud Foundry will consider this response a success and|
| | remove the resource from its database. |
+----------+--------------------------------------------------------+
::
{
"state": "in progress",
"description": "Creating service (10% complete)."
}
Versioning impact
-------------------------
None
Other end user impact
---------------------
None
Deployer impact
---------------
Service Broker should be deployed and enabled in the murano config.
Developer impact
----------------
None
Murano-dashboard / Horizon impact
---------------------------------
None
Implementation
==============
Assignee(s)
-----------
Primary assignee:
starodubcevna
Work Items
----------
Changes can be split to this parts:
* Implement the stub of Service Broker itself. Add needed config opts and starting point.
* Implement basic Cloud Foundry API calls such as list and provision. Also on this step we
should add murano specific API calls.
* Series of extensions for Cloud Foundry API support:
* Add update and deprovision API calls
* Add bind/unbind API calls
Dependencies
============
None
Testing
=======
Unit tests should cover new API calls.
Documentation Impact
====================
Document "Murano and Cloud Foundry HowTo". It should be step by step guide for
Cloud Foundry and murano cooperation.
References
==========
[1] https://youtu.be/ezq9P1WN2LY
[2] http://docs.cloudfoundry.org/services/api.html
[3] https://docs.cloudfoundry.org/services/asynchronous-operations.html
@@ -1,146 +0,0 @@
..
This work is licensed under a Creative Commons Attribution 3.0 Unported
License.
http://creativecommons.org/licenses/by/3.0/legalcode
============================================================
Remove name field from fields and object model in dynamic UI
============================================================
https://blueprints.launchpad.net/murano/+spec/dynamic-ui-specify-no-explicit-name-field
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.
Problem description
===================
* '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.
Proposed change
===============
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.
Alternatives
------------
None
Data model impact
-----------------
None
REST API impact
---------------
None
Versioning impact
-----------------
This change introduces new version of dynamic UI form definition.
Only backward compatibility will be supported: new dashboard can work with old engine.
Other end user impact
---------------------
None
Deployer impact
---------------
None
Developer impact
----------------
None
Murano-dashboard / Horizon impact
---------------------------------
This spec is supposed to be implemented in murano-dashboard only.
User will see new field for adding app name.
Implementation
==============
Assignee(s)
-----------
Primary assignee:
<efedorova@mirantis.com>
Work Items
----------
* Implement automatic 'name' field insertion if version satisfies the requirements;
* Put 'name' field value to the object header area;
* Use 'name' attribute from object header or inside object modal root
in environments table;
* Implement new YAQL function, which returns applications name.
Dependencies
============
This change is a dependency for a future changes in engine
Testing
=======
CI tests should be updated and catch all errors.
Documentation Impact
====================
Dynamic UI form definition examples should be updated
References
==========
None
@@ -1,237 +0,0 @@
..
This work is licensed under a Creative Commons Attribution 3.0 Unported
License.
http://creativecommons.org/licenses/by/3.0/legalcode
===============================
Configure environments from CLI
===============================
Blueprint for this specification:
https://blueprints.launchpad.net/python-muranoclient/+spec/env-configuration-from-cli
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.
Problem description
===================
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.
Proposed change
===============
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 ``murano environment-edit env_id < app_patch.json``
An example ``app_patch.json`` might look like::
[
{ "op": "add", "path": "/services/-",
"value":
{'?':
{'id': '2fc3005d-b4f8-420d-9e15-f961b41f49ee',
'type': 'io.murano.apps.App1'
},
'instance':
{'?': {'id': '53366263-04e9-49d1-829d-50e27158749c',
'type': 'io.murano.resources.LinuxMuranoInstance'},
'assignFloatingIp': True,
'availabilityZone': 'nova',
'flavor': 'm1.medium',
'image': 'afc1aa61-f623-4c66-bbd8-5359261c5272',
'name': 'ilphvibwqyu6h1' },
'name': 'App1'
}
},
]
All operations would only apply to services field, so the `/services/` part of
the path can be ommitted.
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
``murano environment-action deploy`` should deploy the environment.
Alternatives
------------
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.
Data model impact
-----------------
None
REST API impact
---------------
None, CLI should reuse API calls, already used by dashboard
Versioning impact
-------------------------
Since we're adding functionality — None
Other end user impact
---------------------
None
Deployer impact
---------------
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.
Developer impact
----------------
None
Murano-dashboard / Horizon impact
---------------------------------
None
Implementation
==============
Assignee(s)
-----------
Primary assignee:
<kzaitsev>
Work Items
----------
#. ``environment-edit`` command
(should create session, check permissions, add
patch resulting model into ).
#. Input validation for ``envieonment-edit``
(request packages from API, check ID
uniqueness, check input field adequacy).
#. (optional) ``--format-id`` option support
#. (optional) syntax sugar command, that would allow easy addition of a package
to an environment.
#. Session controlling commands.
#. ``environment-action`` command.
#. Shell unit tests.
#. Integration tests.
Dependencies
============
None
Testing
=======
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.
Documentation Impact
====================
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.
References
==========
* http://jsonpatch.com
* https://tools.ietf.org/html/rfc6902
* https://tools.ietf.org/html/rfc7159
* https://pypi.org/project/jsonpatch
-180
View File
@@ -1,180 +0,0 @@
..
This work is licensed under a Creative Commons Attribution 3.0 Unported
License.
http://creativecommons.org/licenses/by/3.0/legalcode
==============================
Environment abandoning support
==============================
https://blueprints.launchpad.net/murano/+spec/environment-abandon
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.
Problem description
===================
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.
Proposed change
===============
The implementation of this feature consists of three stages:
1) 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.
2) 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.
3) 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.
Alternatives
------------
None
Data model impact
-----------------
None
REST API impact
---------------
**DELETE /environments/<environment_id>?abandon**
*Request*
+----------+----------------------------------+----------------------------------+
| Method | URI | Description |
+==========+==================================+==================================+
| DELETE | /environments/{id}?abandon | Remove specified environment. |
+----------+----------------------------------+----------------------------------+
*Parameters:*
* `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
*Response*
+----------------+-----------------------------------------------------------+
| Code | Description |
+================+===========================================================+
| 200 | OK. Environment deleted successfully |
+----------------+-----------------------------------------------------------+
| 403 | User is not allowed to delete this resource |
+----------------+-----------------------------------------------------------+
| 404 | Not found. Specified environment doesn`t exist |
+----------------+-----------------------------------------------------------+
Versioning impact
-------------------------
Murano dashboard will support only the version of the client, that includes
corresponding changes.
Other end user impact
---------------------
None
Deployer impact
---------------
None
Developer impact
----------------
None
Murano-dashboard / Horizon impact
---------------------------------
New action `Abandon` will be added to murano-dashboard. It will be always
available in the row of other action.
Dialog with warning should appear when user executes action
Implementation
==============
Assignee(s)
-----------
Dmytro Dovbii
Primary assignee:
<ddovbii@mirantis.com>
Work Items
----------
* Modify method 'delete' of environment API to support two delete modes
* Implement adding 'abandon' parameter to url in 'delete' method of environment
manager in muranoclient
* Add flag '--abandon' to CLI command 'environment-delete'
* Add new class 'AbandonEnvironment' which provide new button 'Abandon' in
murano-dashboard
Implementation is acutally completed.
Dependencies
============
None
Testing
=======
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.
Documentation Impact
====================
API specification should be updated
References
==========
None
-172
View File
@@ -1,172 +0,0 @@
..
This work is licensed under a Creative Commons Attribution 3.0 Unported
License.
http://creativecommons.org/licenses/by/3.0/legalcode
========================
Logging API for MuranoPL
========================
https://blueprints.launchpad.net/murano/+spec/logging-api-for-muranopl
The purpose is to add an ability to log actions while developing MuranoPL
applications
Problem description
===================
It is good practice to log basic stages during application execution.
Logging API should make debugging and troubleshooting processes easier.
Proposed change
===============
Implemention key points
1) New MuranoPL class `io.murano.system.Logger`
Class `Logger` will be part of the MuranoPL core library.
This class should contain basic logging functionality.
Usage example in MuranoPL::
$.log: logger('logger_name')
$.log.info('message: {0}', 'checkpoint')
that code should be equivalent of python code::
from oslo_log import log as logging
LOG = logging.getLogger('logger_name')
LOG.info(_LI('message: {0}').format('checkpoint'))
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.
2) 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`.
3) 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.
4) 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.
5) Default configuration
All logs written in the one file by default. Log rotation should be used,
so maximum size of logs is limited.
6) Logging naming conventions
A note about the logging naming conventions should be added to the MuranoPL
tutorial.
Alternatives
------------
None
Data model impact
-----------------
None
REST API impact
---------------
None
Versioning impact
-------------------------
None
Other end user impact
---------------------
None
Deployer impact
---------------
Deployer will get more information about application execution stages and additional
tool for more precise troubleshooting
Developer impact
----------------
Logging API will allow developer to debug application in a more effective manner
getting information from logs.
Murano-dashboard / Horizon impact
---------------------------------
None
Implementation
==============
Assignee(s)
-----------
Alexey Khivin
Primary assignee:
<akhivin@mirantis.com>
Work Items
----------
* Create new MuranoPL class `io.murano.system.Logger`
* Create new global MuranoPL function `logger()`
* Create method `Logger.exception`
* Add new section for logging parameters into the Murano Engine config
* Describe naming conventions for loggers in the Murano docs
Dependencies
============
None
Testing
=======
Functional tests for MuranoPL must be updated.
Documentation Impact
====================
MuranoPL
References
==========
None
-239
View File
@@ -1,239 +0,0 @@
..
This work is licensed under a Creative Commons Attribution 3.0 Unported
License.
http://creativecommons.org/licenses/by/3.0/legalcode
=====================
Migration to yaql 1.0
=====================
https://blueprints.launchpad.net/murano/+spec/migrate-to-yaql-vnext
yaql 1.0 has a long list of improvements over yaql 0.2 used by Murano.
But it is not a drop-in replacement for yaql 0.2 and requires to perform
serious changes to Murano in order to switch to it.
-------------------
Problem description
-------------------
While yaql 1.0 is more or less similar in terms of query language to that in
v0.2 it is very different in how its functionality exposed to a hosting
project. Most notable differences are:
* syntax for Python function declaration for yaql is different from that in
yaql 0.2.
* yaql 0.2 had so called #resolve() function. When it encountered function
call expression (say ``foo()``) it tried to call ``#resolve()`` so that it
will do the function resolution. If #resolve was not present in context of
failed to resolve function standard yaql 0.2 resolution procedure was used.
Murano used #resolve to catch attempts to call ``$obj.something()`` where obj
is a MuranoObject because it is impossible to register all possible methods
of all possible objects in advance. yaql 1.0 doesn't have neither
``#resolve()`` nor anything similar to it.
* yaql 1.0 doesn't have tuples syntax any more. In v0.2 ``foo(a => b)`` meant
``foo(tuple(a, b))``. In v1.0 ``=>`` syntax means keyword argument value.
Murano used to convert tuples to keyword arguments when calling MuranoPL
methods.
* in yaql 0.2 parser was a global object so that you could say yaql.parse().
In v1.0 parser itself is customizable and need to be constructed by the
hosting project so you need a parser instance (called YaqlEngine in v1.0)
to parse expressions.
* yaql 1.0 doesn't have ``#validate()`` function used to implement ``:`` in
ns:TypeName syntax. yaql 1.0 also doesn't have ':' operator but has a way
to define custom operators that can be used instead.
* there is a great overlap between MuranoPL and yaql 1.0. yaql have a rich
and extensible framework to decorate function parameters to specify their
type and requirements, to inject hidden parameters and to control parameter
laziness. Not only it used for validation but also for function overload
resolution. In MuranoPL there are argument contracts serving similar purpose.
However their implementation is completely independent from each other as for
the whole function invocation process. As a result for MuranoPL methods that
are writen in Python (system classes) it is impossible neither contracts nor
yaql specs, have additional injected parameters and so on.
---------------
Proposed change
---------------
In Murano Engine:
=================
* Create and store in a global variable YaqlEngine instance that will be used
through the application to parse expressions. Update all the places where
parsing takes place to use that object
* extend list of yaql 1.0 parameters specifications (smart-types) with
additional that will validate parameter value using contract expression.
* generate yaql 1.0 FunctionDefinitions from MuranoPL yaql methods using
introduced smart-type. As a result all MuranoPL methods will be directly
exposed as yaql functions. Actual function payload will still point to
MuranoDslExecutor code to perform correct context switching, locking and
logging
* do similar thing for native MuranoPL methods (those that are written in
Python). Python methods could use any yaql parameter declarations and full
potential of yaql 1.0 specs. So now yaql functions, Python methods and YAML
methods will all be unified as yaql functions/methods with full
interoperability. For native methods there will be 2 FunctionDefinition:
one is the interface stub that gets registered in yaql context and calls
executor.invoke_method() under the hood. And another one for a native method
itself to call methods via yaql mechanics (and apply all the smart-type
specs) rather that via custom reflection-based implementation that is found
in dsl code. For YAML methods method.body will still remain the dictionary
as it is now
* implement ``#operator_.`` (``.`` operator) in such a way that for expressions
of a form ``$obj.foo()`` where ``$obj`` is a MuranoObject it will discover
all possible methods of ``$obj``'s type (via added MuranoClass functionality)
and continue with ``foo(sender=$obj)`` execution in a child context with all
``$obj``'s method registered in it. This is a way to dynamically register
functions in context overcoming absence of yaql 0.2's ``#resolve()``
* configure yaql engine to have additional operator ``:`` with a highest
priority. Expressions of a form ns:Type should be resolved in place using
current Namespaces specification and resulting type name will be used to
obtain MuranoClass from class loader. As a result of operation return
special object (MuranoClassReference) that will wrap MuranoClass and could
be used to reference type in YAML MuranoPL code without providing access
to MuranoClass internals. That can be used later to implement static methods
with ``ns:Type.foo()`` syntax
* add one more yaql smart-type so that it will be possible to declare that
function requires type reference. This smart type should accept both strings
and MuranoClassReference objects. new() and class() functions should be
implemented with this smart-type. This will allow transparency between
string-based syntax new('io.murano.MyClass') and new(ns:MyClass) since
ns:MyClass will not be a string anymore
* change dsl's and engine's yaql functions to have new declaration syntax.
Remove functions that are already present in yaql 1.0 standard library.
* use yaql 1.0 legacy mode for backward compatibility with existing
MuranoPL applications
In python-muranoclient:
=======================
* create global YaqlEngine and update code to use it (and new yaql module
structure)
* update YaqlExpression code to use that global parser object and new yaql's
module structure
In Murano Dashboard:
====================
* make dashboard either use parser object from updated python-muranoclient or
create one for itself
* update yaql functions that were written for dynamicUI forms to have new
declaration syntax
* because dashboard uses expression serialization (pickling) and yaql 1.0
expressions are not serializable because of a outer AST expression contains
reference to YaqlEngine used to create it and YaqlEngine cannot be made
serializable there is a need for custom pickling code that will make pickle
not to try to serialize YaqlEngine instance
* use yaql 1.0 legacy mode for backward compatibility with existing
MuranoPL applications. In the future we can switch to non-legacy mode on
newer form format versions.
------------
Alternatives
------------
Try to fix some of the bugs in yaql 0.2 and not to switch to v1.0
Data model impact
=================
None
REST API impact
===============
None
Versioning impact
=================
yaql migration should not break existing applications so there is no versioning
impact here. However it may have an impact on how plugins/system classes for
MuranoPL are written. But since versioning is not implemented yet there is
nothing to increment and backward compatibility will be broken for those
classes.
Also this yaql legacy mode may be switched off for next engine version and
still be turned on for old applications
Other end user impact
=====================
Because new yaql is not 100% compatible with yaql 0.2 there is still a
possibility that some applications will break even with compatibility mode
turned on. For example there might be bugs in applications that remained
unnoticed with yaql 0.2 but cause exception to be raised with v1.0 or
application might have relied on yaql 0.2 buggy behavior that is not present
anymore.
Deployer impact
===============
None
Developer impact
================
Plugins will have to be updated to use yaql-style method declarations. But
because yaql can infer many things automatically changes are going to be
minor and will not require much efforts to do. However without any
modifications old plugins will likely to break after migration will be made.
Murano-dashboard / Horizon impact
=================================
dashboard code need to be updated to use new yaql. This will not affect user
experience
--------------
Implementation
--------------
Assignee(s)
===========
Primary assignee:
Stan Lagun <slagun>
Other contributors:
Ekaterina Chernova <efedorova>
Work Items
==========
Bullets from "proposed changes" section may be used as a work items directly
------------
Dependencies
------------
This spec depends on yaql 1.0 be released and the latest changes in it.
-------
Testing
-------
Because applications can break they should be re-tested. When incompatibility
found it is better to try to fix it in engine's code rather that in application
to capture similar cases in other applications.
--------------------
Documentation Impact
--------------------
Documentation for how to write plugins/system classes need to be updated.
Most of the newly introduced features to MuranoPL are direct consequence
of new yaql features and should be documented in yaql's scope rather than
copying it to MuranoPL documentation.
----------
References
----------
None
@@ -1,219 +0,0 @@
..
This work is licensed under a Creative Commons Attribution 3.0 Unported
License.
http://creativecommons.org/licenses/by/3.0/legalcode
===============================
Murano API - All Tenants Search
===============================
https://blueprints.launchpad.net/murano/+spec/murano-api-all-tenants-search
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).
Problem description
===================
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.
Proposed change
===============
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.
Alternatives
------------
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
Data model impact
-----------------
None
REST API impact
---------------
* List Environments
* *all_tenants* parameter is added. When set to *true*, then search over all tenants
is executed, otherwise search on token's tenant is done
Example (without *all_tenants*):
::
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"
}
]
}
Example (with *all_tenants* - note different *tenant_id*):
::
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"
}
]
}
Versioning impact
-------------------------
None
Other end user impact
---------------------
*python-muranoclient* will be changed as follows:
* *--all-tenants* on CLI
Example:
::
$ murano environment-list --all-tenants
* *search options* will be supported on API level
Example:
::
class EnvironmentManager(base.ManagerWithFind):
def list(self):
...
def list(self, search_opts):
...
Deployer impact
---------------
None
Developer impact
----------------
None
Murano-dashboard / Horizon impact
---------------------------------
None
Implementation
==============
Assignee(s)
-----------
Primary assignee:
filip-blaha
Work Items
----------
* Introduce *all_tenants* search option in
* file *murano/api/v1/environments.py*
* Modify *policy.json* file with rules
* file *etc/murano/policy.json*
* Add support for search options in *python-muranoclient*
* file *muranoclient/v1/environments.py*
* Add support for *--all-tenants* in *python-muranoclient* CLI
* file *muranoclient/shell.py*
Dependencies
============
None
Testing
=======
Unit tests should cover server API side also client and shell should be covered.
Documentation Impact
====================
REST API documentation will be modified to mention *all_tenants* search option.
References
==========
* https://wiki.openstack.org/wiki/PolicyGuidedFulfillmentLibertyPlanning
* https://wiki.openstack.org/wiki/PolicyGuidedFulfillmentLibertyPlanning_MuranoAPI
@@ -1,171 +0,0 @@
..
This work is licensed under a Creative Commons Attribution 3.0 Unported
License.
http://creativecommons.org/licenses/by/3.0/legalcode
=========================================================
Murano API - Core Model Component Integration Improvement
=========================================================
https://blueprints.launchpad.net/murano/+spec/murano-core-model-integration-improvements
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).
Problem description
===================
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*)
Proposed change
===============
Changes of core Murano model:
* **io.murano.resources.Instance**
* add property *openstackId* and fill the property with value once Heat provisioned
Instance
::
openstackId:
Contract: $.string()
Usage: Out
* **io.murano.resources.Network**
* add property *openstackId* and fill the property with value once Heat provisioned
network (as part of Instance provisioning)
::
openstackId:
Contract: $.string()
Usage: Out
Alternatives
------------
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
Data model impact
-----------------
None
REST API impact
---------------
None
Versioning impact
-------------------------
Murano package versioning is currently analyzed and it is planned for Liberty.
It makes sense to introduce it (modifications of the core Murano packages) as new
versions of core Murano packages.
On the other hand, proposed changes are backward compatible, so they can be
done prior versioning.
Other end user impact
---------------------
None
Deployer impact
---------------
If proposed changes will be done prior Murano package versioning, then after upgrade
the Murano objects won't have initialized introduced properties (*openstackId*).
Developer impact
----------------
None
Murano-dashboard / Horizon impact
---------------------------------
The change will simplify implementation of Horizon UI (instance detail)
Implementation
==============
Assignee(s)
-----------
Primary assignee:
filip-blaha
Work Items
----------
* introduce *openstackId* properties to
* *meta/io.murano/Classes/resources/Instance.yaml*
* *meta/io.murano/Classes/resources/Network.yaml*
* implemented instance and network *openstackId* property population
* *meta/io.murano/Classes/resources/Instance.yaml* , *deploy* method
* *meta/io.murano/Classes/resources/NeutronNetwork.yaml* , *deploy* method
* *meta/io.murano/Classes/resources/NovaNetwork.yaml* won't be modified, as nova
networking is deprecated
Dependencies
============
https://blueprints.launchpad.net/murano/+spec/murano-versioning
Testing
=======
Both unit and tempest tests of policy guided fulfillment will be enhanced to test properties *openstackId*.
Documentation Impact
====================
None
References
==========
* https://wiki.openstack.org/wiki/PolicyGuidedFulfillmentLibertyPlanning
* https://wiki.openstack.org/wiki/PolicyGuidedFulfillmentLibertyPlanning_MuranoAPI
-168
View File
@@ -1,168 +0,0 @@
..
This work is licensed under a Creative Commons Attribution 3.0 Unported
License.
http://creativecommons.org/licenses/by/3.0/legalcode
======================
Murano unified logging
======================
https://blueprints.launchpad.net/murano/+spec/unified-style-logging
Rewrite murano logging in unified OpenStack style proposed by
https://blueprints.launchpad.net/nova/+spec/log-guidelines
Problem description
===================
Now log levels and messages in murano are mixed and don't match the OpenStack
logging guideliness.
Proposed change
===============
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:
* Action execution:
.. code:: python
LOG.debug('Action:Execute <ActionId: {0}>'.format(action_id))
..
* Environment creation:
.. code:: python
LOG.info(_LI('Environments:Create {id} succeed>'.format(id=environment.id)))
..
* Package execution problems
.. code:: python
LOG.warning(_LW("Class is defined in multiple packages!"))
..
* Environment is not found
.. code:: python
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.
Alternatives
------------
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.
Data model impact
-----------------
None
REST API impact
---------------
None
Other end user impact
---------------------
None
Deployer impact
---------------
None
Developer impact
----------------
None
murano-image-elements impact
----------------------------
None
murano-dashboard / Horizon impact
---------------------------------
None
Implementation
==============
Assignee(s)
-----------
Primary assignee:
starodubcevna
Work Items
----------
* Unify existing logging system
* Unify logging messages
* Synchronize dasboard notifications and log entries
* Add additional logs if needed
Dependencies
============
None
Testing
=======
None
Documentation Impact
====================
None
References
==========
https://blueprints.launchpad.net/nova/+spec/log-guidelines
https://www.python.org/dev/peps/pep-3101/
-410
View File
@@ -1,410 +0,0 @@
..
This work is licensed under a Creative Commons Attribution 3.0 Unported
License.
http://creativecommons.org/licenses/by/3.0/legalcode
=================
Murano versioning
=================
https://blueprints.launchpad.net/murano/+spec/murano-versioning
This specification proposes set of arrangements that are going to allow Murano
keep backward compatibility with applications written for older version while
still making possible to introduce incompatible changes to any part of the
project.
Problem description
===================
Murano is a complex system that comprises from a number of services and
technologies including several domain specific/markup languages. All of them
evolve and change from release to release. New features are introduced, code is
being refactored and not always remains compatible with previous release.
But applications written for previous Murano versions must still work on newer
releases otherwise all applications would require at least retesting and often
code changes on each release.
Proposed change
===============
Because there are many different parts in Murano that can be broken it is
necessary to have versioning support to manage backward compatibility.
Murano packages versioning
''''''''''''''''''''''''''
Murano packages will have new optional attribute in their manifest called
``Version``. It will be standard SemVer format version string consisting
of 3 parts: ``Major.Minor.Patch`` and optional SemVer suffixes
``[-dev-build.label[+metadata.label]]``.
All MuranoPL classes are said to have version of the package they contained in.
If no version specified package version will be equal to "0.0.0"
Version number will become very important not just to distinguish modifications
of the same package but to determine compatibility between them. Two classes
(packages) said to be compatible for particular operation if class with newer
version number can be used instead of older class version without breaking
application/component written for that older version.
Compatibility rules differ for various class usages but they all assume
semantic versioning rules be strictly followed. Changes which break
backwards-compatibility should increment the major segment, non-breaking new
features increment the minor segment and all non-breaking bug fixes increment
the patch segment.
Changes that require major version segment to be incremented:
* class was removed from package
* public method or property was removed from any class in the package
* public method changed argument signature to incompatible with previous one.
For example argument removed or added without default value
* input property (or initializer argument) was added without ``Default`` value
and restrictive contract (e.g. one must provide its value)
* any other change (including in class behavior) that can break class
consumers (callers)
Minor version segment should be incremented upon:
* new class was introduced in the package
* new method or property was introduced in any package's class
* list of parents (``Extends`` section) changed for any class
* any other interface (including behavior) changes that don't break external
class users but can possibly break class inheritors
For all other backward compatible changes patch segment must be incremented.
One should not make changes to package contents without also updating version
number. However there is no requirement to do it on each change. Only released
packages need to differ in version. As a result:
#. several breaking changes can be accumulated into one version number change
#. major segment change may also imply changes that would normally affect minor
and/or patch segments and the same goes for minor version segment change
#. during one development iteration packages may be incompatible with each
other even if they have compatible version number
SemVer suffixes have no special meaning for Murano and affect how two version
strings compare to each other.
Murano core library is also a package which has its own version. The first
version to have a number will be 0.1.0 and be released in Liberty.
Murano Extension Plugins (i.e python packages which declare
setuptools-entrypoints in 'io.murano.extensions' namespace) also will have
similar versioning semantics: they will have a fully qualified name (defined
by the setuptools' package name) and a version (also defined by setuptools).
From the class-loader perspective the MuranoPL classes defined in the plugins
are no difference from the classes defined in a regular package. However
for initial implementation we may just assume that all exposed plugin
classes reside in a single MuranoPL package having a name of the Python package
and version `0.0.0` to keep backward compatibility until we find a better
way to represent MuranoPL packages using Python counterpart.
Package requirements
''''''''''''''''''''
Packages may require other packages for their work. Those requirements are
expressed via ``Require`` key in package manifest. It has a form of
.. code-block:: yaml
Require:
package1_FQN: version_spec_1
...
packageN_FQN: version_spec_N
``version_spec`` here denotes allowed version range.
It can be either in `semantic_version.Spec` pip-like format (for example
`>=1.2,<2.0,!=1.5` or `*`) or as partial version string. In the later case:
* x <==> x.0.0 <= version < (x+1).0.0
* x.y <==> x.y.0 <= version < x.(y+1).0
* z.y.z <==> version == x.y.z
* empty (null) <==> 0.0.0 <= version < 1.0.0
Upon package upload/validation it is checked that at least one package in
specified version range exists.
All packages considered to be dependent on ``io.murano`` package (core
library). If such requirement is absent from the list (or the list is empty or
even there is no ``Require`` key in package manifest) then dependency
``io.murano: 0`` will be automatically added (for package types other than
MuranoPL default version may differ).
Packages must explicitly request all other packages which types are mentioned.
This includes class() contracts, inheritance (``Extends``) and dynamic object
construction (``new()``). For any type name use type should not be resolved
by the engine if its not contained either in the class package itself nor in
any of its requirements. Transitional dependencies doesn't have to be
explicitly required.
Murano Extension Plugins treated as regular MuranoPL packages and thus need
to have a way to specify requirement via Python means.
Each package will also have implicit (unless specified explicitly) requirement
on itself of a form ``PackageFQN: X`` where ``X`` is the package major version
segment meaning package can tall to other versions of itself having the same
major version. This requirement is automatically satisfied by the package
itself.
Object version
''''''''''''''
Object in Object Model are also versioned by the version of object's class.
The version will be stored in ``?/classVersion`` attribute of each object.
When model loader tries to create object from its JSON representation it is
going to ask class loader for class of specified version. Versions of object's
parts that belong to parent classes are determined by normal package dependency
resolution rules (parent classes must be in package requirements for the class
version being loaded)
If no version specified then latest available version should be used.
If version is specified but is not present in catalog then:
#. latest class with the same major and minor segments used
#. if there is no match use latest class having the same major version segment
only
#. if there is no matching class then fail
class() contracts must validate object version against package requirements.
If class A has a property with contract $.class(B) then object passed in this
property when upcasted to B must have a version compatible with requirement
specification in A's package (requesting B's package)
Side by side versioning of packages
'''''''''''''''''''''''''''''''''''
There exist cases when several version of the same package may live in the
same environment:
* there are different versions of the same MuranoPL class inside single object
model (environment)
* several class versions encounter within class parents. For example class A
extends B and C and class C inherits B2 where B and B2 are two different
versions of the same class
This implies that class loader needs to:
#. be able to load/keep in memory several versions of the same class
independently
#. when asked for a class object (i.e. MuranoClass object) from MuranoPL code
(via ``class()`` contract or ``new()`` function analyzes caller's package
requirements and returns latest class version matches those requirements
(or fail otherwise)
#. when accessed from object model loader be able to return class version
specified in object header (and find compatible replacement when the request
cannot be satisfied)
The first case when 2 different versions of the same class need to talk to each
other is handled by the fact that in order to do that there must be a
``class()`` contract for that value and it will be validated by the rules from
previous section.
For the second case where single class will attempt to inherit from two
different versions of a same class engine (dsl) should attempt to to find a
version of this class which satisfies all parties and use it instead.
However if it is impossible all remained different versions of the same class
will be threatened as if they be unrelated classes.
For example: classA inherits classB from packageX and classC from packageY.
Both classB and classC inherit from classD from packageZ, however packageX
depends on the version 1.2.0 of packageZ, while packageY depends on the
version 1.3.0. This leads to a situation when classA transitively inherits
classD of both versions 1.2 and 1.3. So, an exception will be thrown.
However, if packageY's dependency would be just "1" (which means any of the
1.x.x family) the conflict would be resolved and a 1.2 would be used as it
satisfies both inheritance chains.
Engine versioning
'''''''''''''''''
Each package has a manifest attribute named ``Format`` of a form
[PackageType/]Version where PackageType is a language used for the package
with “MuranoPL” as a default and Version is a 3-component version string
with shortening rules ``null = 1 = 1.0 = 1.0.0``. Version indicates minimum
engine/language version to run.
Language, engine and manifest format versions are tied together into a
single version.
We assume that all of above are backward compatible or internally can handle
differences between versions. Engine internally knows what changed in each
version and can use that knowledge to emulate behavior of older versions.
Engine must ensure that for each incompatibility in execution behavior or in
YAQL functions particular class method gets properly initialized context with
functions and flags from requested engine version.
UI forms versioning
'''''''''''''''''''
UI forms are versioned using Format attribute inside YAML definition.
The only way to stay compatible with older format versions is either to
support several different formats internally in dashboard or have
auto-conversion utility that will upgrade forms on package upload.
API versioning
''''''''''''''
If single API service can handle several API versions simultaneously it
should be done via endpoint prefixes (/v1/, /v2/ etc.). Otherwise there
should be several separate services listening on different ports and
registered with different names in Keystone.
We assume that dashboard-API-engine are always consistent and upgraded as
the whole. We also assume to be acceptable for different API versions to
have separate databases or tables so that environments created with one
version would not be visible to APIs of other versions.
Alternatives
------------
Keep strict backward compatibility without ability to introduce breaking
changes.
Data model impact
-----------------
For current package API:
* need to store version number for each versioned entity in the database
* in many cases uniqueness must be constrained by name, version number
and tenant ID rather than by name and tenant ID alone
* requirements for each package need to be stored in database as well
However there is an ongoing process to move packages from Murano API to
Glance v3 Artifact Repository (GLARE).
In GLARE package manifest attributes like FQN and Version are going to be
naturally mapped to corresponding artifact attributes. The package dependencies
will be stored in Glance as cross-artifact dynamic dependencies (i.e.
dependencies not on a particular artifact but on the last artifact matching
the given name and the version range query) as soon as that feature is
implemented in Glance (currently only static dependencies are implemented
there). Until that dependencies are going to be stored as a regular list of
strings, and the Murano engine will process it and query Glance to fetch the
packages.
REST API impact
---------------
None
Versioning impact
-----------------
None
Other end user impact
---------------------
None
Deployer impact
---------------
All versions of released packages should be available simultaneously.
That implies that for core library and other essential packages instead
of importing only those packages at system installation all versions of
those libraries need to be imported.
If there would be several independent API services it would require additional
deployment efforts.
Developer impact
----------------
Development process need to be changed for correct version tracking.
Here is an example how it can be organized:
* for each released version of the package there is a separate folder called
after version number plus one additional folder called “dev”
* during development all changes go to “dev” folder. All packages and
requirements have a version “0.0.0” effectively turning versioning off.
* after code freeze release manager assign version number to the version about
to be released by examining commits happened between releases. It is advised
to mark such commits somehow (for example [changes major version],
[changes minor version], [changes revision] or something similar).
* requirements may be defined more accurately from the same source
* new folder for released version is created and final version of the “dev”
package is put there.
* bug/fix and backport commits can be made in between modifying either already
released package or making a copy of it with different revision version
number according to versioning requirements.
* we should write a script to package/upload packages from such versioned
folder (e.g. producing a package for each released version)
Murano-dashboard / Horizon impact
---------------------------------
In L cycle we are not going to show multiple versions of the same app in
Murano dashboard: only the last one will be shown if the multiple versions
are present. This is to minimize the changes at Dashboard side: in future
releases we'll add the ability to select the proper version.
Implementation
--------------
Assignee(s)
```````````
Primary assignee:
Stan Lagun <istalker2>
GLARE integration (API to access packages with versions and GLARE plugin):
Alexander Tivelkov <ativelkov>
Work Items
``````````
* Make Murano Engine access package manifest information
* Implement more flexible processing of package format string (currently it
requires strict version number)
* Make engine be able to setup independent YAQL context chain depending on
package's engine version requirements
* Update class loader to work with versions
* Add support for version numbers and package requirements to
DirectoryPackageLoader (including version-aware directory structure as in
``murano-apps`` repo)
* Update APIPackageLoader to work with GLARE Murano plugin
* Implement version compatibility rules for contracts and inheritance
Dependencies
============
None
Testing
=======
In general, after each release we should try to test old applications on new
release to make sure that nothing broke (which may happen if versioning rules
were not followed correctly). But it is clear that in practice this cannot be
done for all applications in catalog. So we may peek selected set of
applications and to try to deploy all versions of those applications on current
release. This set should be representative to test the most possible set of
futures.
Subset of those applications can be used for per-commit tests.
Documentation Impact
====================
Changes introduced by each version change of each component should be
documented. There should be possible to see documentation for specific previous
Murano version as it remains usable.
References
==========
None
-174
View File
@@ -1,174 +0,0 @@
..
This work is licensed under a Creative Commons Attribution 3.0 Unported
License.
http://creativecommons.org/licenses/by/3.0/legalcode
============================
MuranoPL object construction
============================
https://blueprints.launchpad.net/murano/+spec/object-construction
Object construction is ability to create instances of MuranoPL classes
(both YAML and Python-based) and initialize it property. It also directly
affect relations between those 2 types of classes just because they can
inherit from each other and have initializer of their own
Problem description
===================
There are several major problems with current object initialization:
* object created by ``new()`` function will always have an owner set to null.
Because of this you cannot create objects that expect themselves to be
nested in something (e.g. say ``find(std:Environment).require()``)
* there are ``initialize()`` method in Python classes and method with the same
name in YAML part, but they work completely different. YAML version is
currently doesn't invoked at all for ``new()`` making it useful for Python
classes only
* Python initializer may me called instead of YAML version in some cases as
they have the same name
* Python classes inherit from MuranoObject even if they not aware of it.
Because MuranoObject has ``__init__`` with many parameters and user
classes have constructor parameters of their own user class cannot have
``__init__`` or it will break MuranoObject. It looks very strange for a class
to inherit from Python's object and not being able to have ``__init__``.
* also because MuranoObject has many methods and properties of its own if user
class will define method with the same name it will break how MuranoPL work.
Proposed change
===============
* rename YAML initialize and destroy methods to ``.init"`` and ``.destroy``
as they are special. Make class loader automatically replace old names with
new ones for backward compatibility. Dot-prefixed names cannot be called from
MuranoPL directly as this will be a YAQL syntax error so there is no more
need to have special treatment for those names in MuranoDslExecutor and
block them from being called explicitly
* ``.init`` will be allowed to have parameters. During object initialization
object model values will go into .init parameters instead of properties
if parameter name matches key name in object model. Usual parameter contract
system applies here
* because ``.init`` need to be able to save values it receives in parameters to
corresponding objects it should be allowed to modify properties with
usage=In that are immutable in normal operation mode. The same extends to
functions that get called during initialization
* separate Python classes from MuranoObject. Classes will no longer inherit
from MuranoObject and thus will have ``__init__`` instead of initialize.
MuranoObject will store their native part in a property called ``extension``
* using YAQL injected parameters provide Python class with interface to access
its MuranoObject counterpart and invoke methods defined in YAML
* initialization should go as following:
1. YAML-defined properties initialized (in 1 pass for ``new()``, 2 passes
for object model load) except for those that can be found in ``.init``
parameters
2. Python ``__init__`` get called if present. The same property value used
to initialize object used as ``__init__`` parameters (i.e. subset of
them since ``__init__`` may have less parameters then number of declared
properties or not to have parameters at all)
3. For MuranoObject counterpart all ``.init`` methods in hierarchy get
invoked starting from the top-level classes and down to the class that
we are initializing. It should be invoked with special flag passed in
context that will allow it to write to even read-only properties.
Property values that were skipped on first stage become ``.init``
parameters on each hierarchy level. It is ``.init``'s job to set
corresponding properties (that might have different contract)
* Add ability to explicitly pass created object owner as a ``new()`` parameter
* Update object model serializer so that if object A is specified as an owner
of object B but doesn't references it and instead referenced by some other
object C that is nested inside A then reattach B to C. This will not break
object A since it remains nested in B. If A is referenced by several objects
conforming this criteria any one of them can be used.
Alternatives
============
None
Data model impact
=================
None
REST API impact
===============
None
Versioning impact
=================
* initialize and destroy will automatically be renamed to .init and .destroy
by the class loader so previously written apps won't break
* because currently initialize cannot have parameters at all backward
compatibility retained
* the same is true for ability to modify read-only properties in initializer
Other end user impact
=====================
Users gets ability to implement things like auto-scaling with
ability to create instances from within MuranoPL
Deployer impact
===============
None
Developer impact
================
None
Murano-dashboard / Horizon impact
=================================
None
Implementation
==============
Assignee(s)
```````````
Primary assignee:
Stan Lagun <slagun>
Work Items
``````````
Bullets from "proposed changes" section may be used as a work items directly
Dependencies
============
https://blueprints.launchpad.net/murano/+spec/migrate-to-yaql-vnext
Testing
=======
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).
Documentation Impact
====================
Mentioned changes need to be included into MuranoPL documentation
References
==========
None
@@ -1,164 +0,0 @@
..
This work is licensed under a Creative Commons Attribution 3.0 Unported
License.
http://creativecommons.org/licenses/by/3.0/legalcode
========================================
Policy Based Modification of Environment
========================================
https://blueprints.launchpad.net/murano/+spec/policy-based-env-modification
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.
Problem description
===================
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.
Proposed change
===============
**Changes**
* Introduce new Congress policy rule *predeploy_modify(eid,oid,modify-action-id,priority,
[key-val]\*)*
*predeploy_modify* policy rule is queried on all actions.
Simulation Congress API is used like in case of *predeploy_errors* policy rule.
If it returns non empty list of *modifications* for given environment, then
* *deploy* action is temporarily paused, until all modifications are processed
* if any of modification fails, then environment *deploy* fails
* Pluggable modification actions
Modification actions can be plug using setup *entry_points*.
Out of box, there will be following modification actions
* add_property( name=name, value=value)
* remove_property( name=name)
* set_property( name=name, value=value)
* add_relationship( name=name, source=source-uuid, target=target-uuid)
* remove_relationship( name=name, object=object-uuid)
* add_object( type=type, owner=owner-uuid, owner-rel-name=name, [name=val]*)
* remove_object( object=object-uuid)
Alternatives
------------
Alternative can be usage of *executes[]* of Congress policy, which executes modify
actions. In this approach
* modify action has to be implemented as Congress datasource action
* triggering of executes[] has to be solved
* it is not possible to order modify action ordering
* Murano session-id of REST API must be passed to Congress
* actions can be executed only as asynchronous, so it is not possible to postpone
*deploy* environment action until all modify actions are finished
Thus it is not alternative.
Data model impact
-----------------
None
REST API impact
---------------
None
Versioning impact
-------------------------
None
Other end user impact
---------------------
User (admin) can control modification by creating *predeploy_modify* Congress policy
rules.
Deployer impact
---------------
None
Developer impact
----------------
None
Murano-dashboard / Horizon impact
---------------------------------
None
Implementation
==============
Assignee(s)
-----------
Primary assignee:
filip-blaha
Work Items
----------
* design API of modify actions
* framework for pluggable modify actions - registering and managing available actions
* implement out-of-box actions
* add point to engine where congress called and returned action list is processed on given environment
Dependencies
============
None
Testing
=======
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.
Documentation Impact
====================
It is documented as part of policy guided fulfillment.
References
==========
@@ -1,206 +0,0 @@
..
This work is licensed under a Creative Commons Attribution 3.0 Unported
License.
http://creativecommons.org/licenses/by/3.0/legalcode
=============================
Simple Software Configuration
=============================
https://blueprints.launchpad.net/murano/+spec/simple-software-configuration
The purpose is to add to Murano core-library new functionality allowing to
simplify the process of software configuration.
Problem description
===================
At the moment a developer of murano applications often has difficulties with
configuration of software on the instance. They are related with fact that
developer always has to create execution plans even in situations when some
short scripts must be executed on VM.
For example, developer wants to run mysql service. In this case he should:
* Prepare template file for execution plan
* Prepare script containing only something like this:
..
service mysql-server start
..
* Describe in code of class the sending of plan to the murano agent
It is proposed to update the murano core-library to allow to user make express
software configuration instructions without writing explicit configuration
scripts and execution plans for Murano Agent in order to develop applications
faster, and have concise and clear workflows.
Proposed change
===============
The extension of library will support only Linux instances.
The new class **io.murano.configuration.Linux** will be added. In initial
implementation this class has two methods:
::
runCommand:
Arguments:
- agent:
Contract: $.class(sys:Agent)
- command:
Contract: $.string().notNull()
- helpText:
Contract: $.string()
* **runCommand** method sends specified string containing CLI command to
murano-agent and then it will be executed.
Arguments:
* *agent* - instance of murano-agent
* *command* - string with CLI command
* *helpTest* - string (optional), description for logging. Will be used as
name of execution plan. If it is *Null* value of *command* will be used.
::
putFile:
Arguments:
- agent:
Contract: $.class(sys:Agent)
- fileContent:
Contract: $.string().notNull()
- path:
Contract: $.string().notNull()
- helpText:
Contract: $.string()
* **putFile** method takes content of file and writes it to specified path
on VM
Arguments:
* *agent* - instance of murano-agent
* *fileContent* - string, content of file
* *path* - string, path for writing
* *helpTest* - string (optional), description for logging. Will be used as
name of execution plan. If it is *Null*, value of *path* will be used.
The both methods actually use the same procedure of sending the execution plans
to the agent and require corresponding templates for that, but hide from a
developer this routine.
**Example of usage**
The next example describes how new feature can be used. This code demonstrates
workflow of method in WordPress application, which used for re-configuration
of database settings.
::
changeDatabaseConnection:
Arguments:
- dbHost:
Contract: $.string().notNull()
- dbName:
Contract: $.string().notNull()
- dbUser:
Contract: $.string().notNull()
- dbPassword:
Contract: $.string().notNull()
Body:
- $resources: new(sys:Resources)
# Creating instance of Linux class
- $linux: new(conf:Linux)
# First we need to stop server. 'runCommand' can be used here
- $linux.runCommand($.instance.agent, 'service apache2 stop')
# Creating a dictionary for replacement
- $configReplacements:
"%DB_HOST%": $dbHost
"%DB_NAME%": $dbName
"%DB_USER%": $dbUser
"%DB_PASS%": $dbPassword
# Making a replacement. `wp-config.php' is included to package
- $confFileContent: $resources.string('wp-config.php').replace($configReplacements)
# Putting ready content to necessary path on VM
- $linux.putFile($.instance.agent, $confFileContent, '/var/www/html/wordpress/wp-config.php')
# Now we can start Apache again
- $linux.runCommand($.instance.agent, 'service apache2 start')
Alternatives
------------
Instead of using the common procedure with creating execution plans and
communication with murano-agent some software configuration resources of heat
probably can be used. During updating of library it can be used in the future.
Data model impact
-----------------
None
REST API impact
---------------
None
Versioning impact
-------------------------
None
Other end user impact
---------------------
None
Deployer impact
---------------
None
Developer impact
----------------
Application developers will be able to use new functionality in their apps.
Existing apps will not be affected.
Murano-dashboard / Horizon impact
---------------------------------
None
Implementation
==============
Assignee(s)
-----------
Primary assignee:
ddovbii
Work Items
----------
* Create new class *io.murano.configuration.Linux*
* Implement methods *putFile* and *runCommand*
* Update Murano PL docs
Dependencies
============
None
References
==========
None
@@ -1,282 +0,0 @@
..
This work is licensed under a Creative Commons Attribution 3.0 Unported
License.
http://creativecommons.org/licenses/by/3.0/legalcode
==========================================
Simulated Execution Mode For Murano Engine
==========================================
https://blueprints.launchpad.net/murano/+spec/simulated-execution-mode-murano-engine
Problem description
===================
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.
Proposed change
===============
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, which 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.
Test-case prototype may look like that:
::
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
Alternatives
------------
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 VMs cant be
Data model impact
-----------------
None
REST API impact
---------------
None
Versioning impact
-----------------
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.
Other end user impact
---------------------
None
Deployer impact
---------------
None
Developer impact
----------------
None
Murano-dashboard / Horizon impact
---------------------------------
None
Implementation
==============
Assignee(s)
-----------
Primary assignee:
<efedorova@mirantis.com>
Work Items
----------
#. 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
#. Make changes to the class-loader, located in engine, to not use API.
Separate spec is provided for this change (https://review.opendev.org/#/c/198745/).
#. 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 |
+-----------------------------+-----------------------------------------------------------------+
Private methods:
initialize, __call__, _patch, __enter__, __exit__
Dependencies
============
None
Testing
=======
None
Documentation Impact
====================
New testing framework will be documented from scratch.
References
==========
Discussions in IRC will be provided
-267
View File
@@ -1,267 +0,0 @@
..
This work is licensed under a Creative Commons Attribution 3.0 Unported
License.
http://creativecommons.org/licenses/by/3.0/legalcode
========================================
Add network selection element to UI form
========================================
Include the URL of your launchpad blueprint:
https://blueprints.launchpad.net/murano/+spec/ui-network-selection
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.
Problem description
===================
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] <https://wiki.openstack.org/wiki/Murano/Specifications/Network_Management>`_
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.
Proposed change
===============
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.
Alternatives
------------
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.
Data model impact
-----------------
No impact. The existing data structures will be used.
REST API impact
---------------
No impact. The existing API methods will be used.
Versioning impact
-----------------
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
Other end user impact
---------------------
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.
Deployer impact
---------------
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.
Developer impact
----------------
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.
Murano-dashboard / Horizon impact
---------------------------------
The whole change proposed in this spec is a change of murano-dashboard.
No other components are modified.
Implementation
==============
Assignee(s)
-----------
Primary assignee:
ativelkov
Other contributors:
ddovbii
Work Items
----------
* Implement the shared logic to retrieve and filter the list of networks
* Implement the DynamicUI control to select networks in apps
* Add a dropdown field to a static Create Environment form to select the
default network of the environment.
* Add the support of the new control in the existing murano apps in murano-apps
repository.
Dependencies
============
* 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?
Testing
=======
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.
Documentation Impact
====================
A new Dynamic UI field type has to be documented at `Dynamic UI definition
specification` guide at [3]
References
==========
* [1] https://wiki.openstack.org/wiki/Murano/Specifications/Network_Management
* [2] https://review.opendev.org/#/c/201659/
* [3] https://murano.readthedocs.org/en/latest/draft/appdev-guide/muranopackages/dynamic_ui.html#dynamicuispec
-33
View File
@@ -1,33 +0,0 @@
Mitaka specifications
======================
This directory is supposed to hold approved specifications for the 'Mitaka' release.
You are welcome in contributing to Murano!
Murano
------
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.
Murano Project Resources
------------------------
* `Murano Official Documentation <http://murano.readthedocs.org>`_
* Project status, bugs, and blueprints are tracked on
`Launchpad <https://launchpad.net/murano>`_
* Additional resources are linked from the project
`Wiki <https://wiki.openstack.org/wiki/Murano>`_ page
* `Python client <https://github.com/openstack/python-muranoclient>`_
License
-------
Apache License Version 2.0 http://www.apache.org/licenses/LICENSE-2.0
@@ -1,262 +0,0 @@
..
This work is licensed under a Creative Commons Attribution 3.0 Unported
License.
http://creativecommons.org/licenses/by/3.0/legalcode
=====================================
Actions authentication and visibility
=====================================
URL of launchpad blueprint:
https://blueprints.launchpad.net/murano/+spec/actions-authentication-and-visibility
Application actions is a way for external systems to perform action related
procedures such as maintenance, scaling etc. However those 3rd party
systems are incapable to authenticate themselves to Keystone to call this
API securely.
Problem description
===================
Currently in order to call an action caller needs to have a valid Keystone
token or trust. It is not always possible for cases where 3rd party system is
supposed to be such caller.
There can be a 4 types of authentication for application actions:
#. Public actions. Anybody can call them. No authentication required.
Usually those are the actions without side effect, but if they do
they do that on environment owner behalf.
#. Actions that require authentication and could be invoked from both Murano
UI/CLI (considering user has valid OpenStack credentials) and automation
systems that cannot authenticate to Keystone.
#. Actions that are supposed to be called from automation systems only.
#. Actions that are supposed to be called by admin only and thus require
valid OpenStack token.
It must be possible to associate actions with one of the categories above
and to handle authentication according to type that is chosen.
Proposed change
===============
It is proposed to implement pre-authenticated URLs for the actions.
We assume that any external system will be able to execute POST query
on a fixed HTTP URI that doesn't require authentication. Thus application
during deployment phase (when it has a valid Keystone token or trust)
may allocate such a secret URI on murano API server than when invoked would
trigger particular action on behalf of the user that owns the application
(environment).
There should be an ReST API call to allocate such URI and there also should
be a MuranoPL method to call it from inside of applications.
This API call works as following:
#. Creates a keystone trust for special service user (specified in config file)
to perform particular action
#. Creates a record in database that holds trust ID, project ID, environment
ID, target object ID, action name and action parameters - everything that
is necessary to call particular action on particular application with
specified input.
#. Returns URI that has ID of an inserted record.
#. Murano API should be configured to bypass authentication for such URIs.
#. When such URI is accessed, murano API should extract record ID from the URI.
Then obtain trust ID and action parameters from the database and call
the actions using trust ID putting it instead of Keystone token into
object model.
#. Existing API for calling actions should also work without authentication.
If it is accessed with Keystone token in HTTP header then it must be
validated in the API code. Otherwise only public actions (those that do
not require authentication) must be allowed there.
#. Pre-authenticated URIs can be revoked by revoking the trust and then
deleting the record from database. This should be also possible from within
MuranoPL code.
Alternatives
------------
None
Data model impact
-----------------
New database table holding:
* Record ID
* Trust ID
* OpenStack project ID
* Murano environment ID
* Target object (application) ID
* Action name
* Action parameters (JSON)
REST API impact
---------------
Several new API endpoints are added:
**POST /environments/<env_id>/actions-auth/<action_id>**
*Request*
+--------+-------------------------------------------------+----------------------------------------------+
| Method | URI | Description |
+========+=================================================+==============================================+
| POST | /environments/<env_id>/actions-auth/<action_id> | Creates pre-authenticated URI for the action |
+--------+-------------------------------------------------+----------------------------------------------+
::
{
"arg1": "value1",
"arg2": "value2"
}
*Response*
+----------------+-------------------------------------+
| Code | Description |
+================+=====================================+
| 200 | Authentication URI has been created |
+----------------+-------------------------------------+
::
{
"uri": "full pre-authenticated URI",
"id": "auth_id"
}
**DELETE /environments/<env_id>/actions-auth/<auth_id>**
*Request*
+-----------+-----------------------------------------------+------------------------------------+
| Method | URI | Description |
+===========+===============================================+====================================+
| DELETE | /environments/<env_id>/actions-auth/<auth_id> | Revokes authentication for auth_id |
+-----------+-----------------------------------------------+------------------------------------+
*Response*
+----------------+----------------------------+
| Code | Description |
+================+============================+
| 200 | Authentication was revoked |
+----------------+----------------------------+
**POST /environments/<env_id>/actions/pre-auth/<auth_id>**
*Request*
+--------+---------------------------------------------------+----------------------------------------------------+
| Method | URI | Description |
+========+===================================================+====================================================+
| POST | /environments/<env_id>/actions/pre-auth/<auth_id> | Calls action by its auth_id. If Keystoke header is |
| | | provided in HTTP readers it takes presendence over |
| | | trust_id. |
+--------+---------------------------------------------------+----------------------------------------------------+
*Response*
+----------------+----------------------------+
| Code | Description |
+================+============================+
| 200 | Action was executed |
+----------------+----------------------------+
Versioning impact
-----------------
None
Other end user impact
---------------------
None
Deployer impact
---------------
Service user credentials should be configured in murano.conf.
Also base part of the URI need to be there as well so that API server
would know load balancer IP it stands behind. Keystone v3 should be enabled.
Developer impact
----------------
None
Murano-dashboard / Horizon impact
---------------------------------
There should be a way for the user to create pre-auth URI from Murano
dashboard.
Implementation
==============
Assignee(s)
-----------
Stan Lagun <slagun@mirantis.com>
Work Items
----------
#. Define a markup for action visibility in MuranoPL.
#. Improve object model serialization to include action visibility.
#. Create database migration and model code to work with new table.
#. Add support for missing config parameters.
#. Create API endpoint to create pre-authenticated URI.
#. Create API endpoint to revoke pre-authenticated URI.
#. Create API endpoint to invoke pre-authenticated URI.
#. Configure authentication in paste.ini.
#. Improve python-muranoclient with support for new endpoints
#. Implement MuranoPL functions to create/revoke pre-authenticated URIs for
particular action. Function should return existing Action API endpoint
for public and token-only actions.
#. Provide the same capabilities in Murano dashboard.
Dependencies
============
None
Testing
=======
Develop sample application that would deploy some 3rd part system
and provide it with pre-authenticated URI that it could call periodically.
Observe action invocation fact by its side-effects (logs etc.)
Documentation Impact
====================
New ReST and MuranoPL APIs need to be documented.
References
==========
None
-207
View File
@@ -1,207 +0,0 @@
..
This work is licensed under a Creative Commons Attribution 3.0 Unported
License.
http://creativecommons.org/licenses/by/3.0/legalcode
====================
Engine Package Cache
====================
Include the URL of your launchpad blueprint:
https://blueprints.launchpad.net/murano/+spec/murano-engine-package-cache
This specification provides means to improve caching of packages to fasten
consecutive deployments and action executions, that use the same package.
Problem description
===================
When murano-engine performs a deployment or executes an action on a deployed
environment it needs access to the code of the package. Currently it downloads
a package from API for each deployment and stores it in a local cache for the
duration of the deployment, but deletes it after the deployment has finished.
This means, that a consecutive deployment of the environment that uses the same
package would have to download it again. Same is true for actions. This puts an
undesired strain on murano-api and network, as the same package is downloaded
many times even if it didn't change
Currently murano-engine stores packages on disc, using package-id as cache key.
This further means that if two environments are using the same package the
first to finish would delete the cache, leaving the second environment in an
unexpected state. This can potentially lead to unexpected and hard to pinpoint
bugs.
Among other things the cache system should be able to satisfy and correctly
work around the following corner cases:
#. Several different versions of single package may be used simultaneously by
parallel deployments/actions.
#. Package may be deleted or re-uploaded to API (with or without
version change) while there are ongoing deployments that use previous
package version.
#. Deployment/action may require to download the package that is currently
being downloaded for another deployment/action.
#. Packages might need to be eventually invalidated and space constrained.
Generally there are 2 situation when a package cache needs to be invalidated:
#. A new package of the same version and FQN has been updated, meaning old one
is no longer available, but might still be used by an ongoing deployment
#. A package has not been used for long time (but may be exactly the same as
the most recent package in the API)
Proposed change
===============
Proposed change includes modifying current cache mechanism to allow it to
persist the packages on disk and not clean them up after deployment/action has
ended.
#. Change cache storage directory path from {id} to {fqn}/{version}/{id}
This would allow to easily detect outdated versions of the same package.
Listing {fqn}/{version} directory *before* asking API for an id would give
engine exact list of packages that are in cache and should be invalidated
#. Whenever engine starts executing a task it would acquire shared *usage*
lock on 2 levels: eventlet-based lock (to synchronise tasks from the
current execution task with other execution tasks) and file-system based
lock, using flock or similar primitives (to synchronise use of package
cache between different murano-engine processes). The lock should be
released after the package is no longer required.
#. If the package is not available in cache execution task would attempt to
acquire exclusive *download* lock on 2 levels (eventlet/file-based), thus
allowing only one download per id at a time. The lock should be released
after the download is finished.
#. The task/process, downloading the package would be the one responsible
for deleting outdated versions of the same package.
To do so it would acquire exclusive
*usage* lock on 2 levels for the packages it wishes to delete as part of
cleanup. This would ensure, that ongoing deployments would not be affected
by the cleanup.
Usage lock has to be acquired before download lock. Otherwise there is a
race condition where 2 versions of the same package were downloaded within
a very short interval of time by 2 tasks, and the newer version has finished
downloading before the first one did (for example the newer package is
significantly smaller) and engine started cleanup. This could lead to
newer version being the first to acquire the exclusive *usage* lock and
cleaning the package, that is in use.
(Alternatively we could have used just one *usage* lock and upgrade it from
shared to exclusive if the operation would be available for all types of
locks. Unfortunately this is not true for flock/fcntl based locks in
linux/bsd system. While the upgrade/downgrade operation is available it is
not guaranteed to be atomic, therefore we risk a race condition. See
respective man pages for more clarifications. Therefore it's not an option)
If the process crashes or is killed all the
locks held by it would be released. This is ensured by nature of flock/fcntl
locks and is obviously true for eventlet-based locks. Therefore new process
would not get deadlocked by those locks.
Limitations
-----------
This spec only aims to address the problem of invalidating package cache of
packages, that are outdated.
Solving the problem of invalidating of packages, that have not been used in a
while requires a separate cache-manager, process/service, which in turn would
require additional more fine grained locks to be implemented and it doesn't
look like a real problem right now as the size of the packages is relatively
small and the number of packages in a typical murano installation is not that
large to consume all of the space on the server.
However we should be aware of this situation and probably work on that solution
some time in the future.
Alternatives
------------
One of the alternatives would be to add HTTP headers for caching control, for
example If-Modified-Since. While this is a good idea as of itself it would
impact murano-api, python-muranoclient and murano-engine, thus making it a lot
harder to implement and test.
Instead of having 2-layer locking we could implement spin-locks around file
locks, which doesn't look like a good idea though.
Data model impact
-----------------
None
REST API impact
---------------
None
Versioning impact
-----------------
None
Other end user impact
---------------------
None
Deployer impact
---------------
Since package cache would persist on disk — it would be possible to drain disk
resources by it. This is still possible to do today by creating a really large
amount of simultaneous deployments, although in the current situation the
package cache would be eventually deleted, and space would be reclaimed.
If we believe that this is a serious security flaw — we need to implement cache
invalidation/caps of max cache storage before M release
Developer impact
----------------
None
Murano-dashboard / Horizon impact
---------------------------------
None
Implementation
==============
Assignee(s)
-----------
Primary assignee:
kzaitsev
Work Items
----------
#. Implement caching mechanisms.
#. Implement unit/functional tests.
Dependencies
============
None
Testing
=======
Looks like unit tests would be enough for proper coverage, although
functional tests against race conditions might be benefitial.
Documentation Impact
====================
Usual docs update required
References
==========
* `FreeBSD flock man page
<https://www.freebsd.org/cgi/man.cgi?query=flock&sektion=2>`_
* `Linux flock man page <http://linux.die.net/man/2/flock>`_
@@ -1,106 +0,0 @@
..
This work is licensed under a Creative Commons Attribution 3.0 Unported
License.
http://creativecommons.org/licenses/by/3.0/legalcode
================================================
Middleware for external (non-OpenStack) requests
================================================
https://blueprints.launchpad.net/murano/+spec/external-request-middleware
When request is coming to murano (or any other service) from outside of OpenStack
it has no OpenStack-specific requests headers at all. So, it's hard to use
standart middlewares and authentication methods for exteranal requests.
Problem description
===================
Now we need to recreate keystoneclient and get authentication information for each request
which comes from outside of OpenStack using basic auth credentials. This can be look
better if we can use standart keystone middleware for external service requests,
but we don't have enough info (at least token) in the external requests.
Now you can see this behaviour in murano service broker for Cloud Foundry.
Proposed change
===============
Create a new middleware which will handle external requests and add X-Auth-Token
header. This should be enough for keystone middleware and murano context middleware.
Middleware should be added to all external services adaptors (now we have only
service broker). It's not recommended to add it directly to murano-api because
it can be real security issue.
Alternatives
------------
Take everything as it is.
Data model impact
-----------------
None
REST API impact
---------------
None
Versioning impact
-------------------------
None
Other end user impact
---------------------
None
Deployer impact
---------------
None
Developer impact
----------------
Developers which will create adapters for external service shouldn't worry about
how it will authenticate and work with murano. They can simply add this middleware
to their applications.
Murano-dashboard / Horizon impact
---------------------------------
None
Implementation
==============
Assignee(s)
-----------
Primary assignee:
starodubcevna
Work Items
----------
* Implement external requests middleware
Dependencies
============
None
Testing
=======
Now this can be tested in a bunch of functional tests for Cloud Foundry service
broker.
Documentation Impact
====================
None
-218
View File
@@ -1,218 +0,0 @@
..
This work is licensed under a Creative Commons Attribution 3.0 Unported
License.
http://creativecommons.org/licenses/by/3.0/legalcode
================================================
Mocking machinery for MuranoPL testing framework
================================================
https://blueprints.launchpad.net/murano/+spec/mocking-machinery
Currently we have separate executor, that allows to run MuranoPL code in
testing mode without dashboard. But the main purpose of this executor is to
provide 'mock' availability. This specification describes how this can be done.
Problem description
===================
It's not possible to provide unit-testing without mocking machinery.
The whole idea of murano simulation mode was in deployment imitation.
During the deployment of murano applications, a lot of external objects,
that are not connected to the app itself are involved, such as *murano agent*,
*networks*, *heat stacks* and etc.
All of the classes that should be mocked can be divided into:
* python classes
* yaml classes
* dependent applications
Mocks can really help with new application development (especially compound
ones).
Mock implementation will enable:
* Real deployment simulation
* Run several deployments with different parameters
Actually, list of use-cases is unlimited, since user will be allowed to provide
any alternative function implementation to speed up the development.
Proposed change
===============
Test-runner executor should have new context manager, that will take into
consideration specified mocks. Mocks will be specified with new global YAQL
function.
This will be first step to enable mocking. Later improvements will be added and
described in a separate specification.
Alternatives
------------
None
Data model impact
-----------------
None
REST API impact
---------------
None
Versioning impact
-----------------
None. Will be not available in the previous murano versions.
Other end user impact
---------------------
None
Deployer impact
---------------
None
Developer impact
----------------
None, only new opportunity for developers
Murano-dashboard / Horizon impact
---------------------------------
None
Implementation
==============
Assignee(s)
-----------
Primary assignee:
<efedorova@mirantis.com>
Work Items
----------
#. Create MockContextManager.
Context manager is responsible for providing a valid context with
corresponding attributes and functions for the current object.
Modified context manager will be used for mock implementation. It will be
inherited from the original one and will be called ``MockContextManager``.
It will store instructions which objects or classes are needed to be
replaced with mocks and return context with mock definition instead of the
original function. For that purpose several dictionaries should be used:
one for mapping objects with mocks and other one for class mapping.
If mock for the current object exist, new linked context
(``murano.dsl.linked_context.LinkedContext``) will be returned. It links
existing context with the new context, where mock definition is presented.
So if mocked function will be called, context will contain two
definitions with that function: mock and original one, but mock will have
higher priority.
If there is no mock for the current object or class, existing context
will be returned. If there is no existing context, *None* will be returned.
#. Add global YAQL functions (it will be available only in test-runner mode) to
set scope of mocking and mock definition. It will be called ``inject`` and
will have several declarations for different purposes:
* ``inject`` for set up mock for *class* or *object*, where mock definition
is a *name of the test class method*
* `def inject(target, target_method, mock_object, mock_name)`
* ``inject`` for set up mock for *a class* or *object*, where mock
definition is a *YAQL expression*
* `def inject(target, target_method, yaql_expr)`
Description:
* *target*: MuranoPL class name (namespaces can be used or full class name
in quotes) or MuranoPL object
* *target_method*: Method name to mock in target
* *mock_object*: Object, where mock definition is contained
* *mock_name* Name of method, where mock definition is contained
* *yaql_expr*: YAQL expression, parameters are allowed
So user is allowed to specify concrete method to use instead of original,
or to provide YAQL expression from which new function will be composed.
Advantages of defining mock with YAQL expression:
* Simplicity
Thus, if you need your methods to return different constants, you can
return it inline instead of creating different methods for each constant.
* Restricted context
By default Local variables are not seen in the mock function scope, but
it's possible to specify which variables to pass to the expression.
#. Add `withOriginal` YAQL function
* `withOriginal(a => $x, b => $y)`
YAQL function, registered in the mock context.
Allows to pass values from the original context to the mock context,
where mock function is executed. Suppose, we have ``$x: 2`` in the mock
function and ``$x: 1`` in the original function. We can not just combine
the contexts since we want to use both 'x' variables and it will be
unclear which. With new YAQL function original variables can be passed to
a mock context with configurable name. So original context need to be
saved in advanced and ``withOriginal`` function should have access to it.
* `originalMethod()`
YAQL function, registered in the context of inject function.
Calls the original method and can be used in a mock function.
#. Add `OneOf` Smart type
In new function for injection mock parameter can be class or object.
So we need to accept one of those. This new type will check function
parameter for belonging to one of type in the provided list.
Dependencies
============
None
Testing
=======
New code should be 100% covered by unit tests.
Documentation Impact
====================
Separate documentation for the whole test-runner and mock machinery will
be provided.
References
==========
None
-161
View File
@@ -1,161 +0,0 @@
..
This work is licensed under a Creative Commons Attribution 3.0 Unported
License.
http://creativecommons.org/licenses/by/3.0/legalcode
=======================
Multiple engine workers
=======================
URL of launchpad blueprint:
https://blueprints.launchpad.net/murano/+spec/multiple-engine-workers
This specification is to implement multiple workers to murano-engine.
Problem description
===================
murano-engine is currently single process. It's a problem for scalability.
Proposed change
===============
Implement multiple workers to murano-engine by oslo.service library.
When starting service, murano-engine forks the number of workers which is
written in configuration file. When a configuration reload is required, restart
service is needed. If child process is killed, murano-engine forks new worker.
Most of the OpenStack projects use oslo.service.
Alternatives
------------
There are some external tools.
Configuration management tool such as Puppet, Chef, Ansible
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Configuration management tool controls services which is managed by init systems
like systemd, upstart. Configuration management tool does not manage processes.
Init systems
~~~~~~~~~~~~
Systemd, upstart are init systems of Unix like systems. Upstart is default init
system until Ubuntu 14.10 or RHEL6. Systemd is default init system of Ubuntu
15.04 or RHEL7, and other Linux systems.
Systemd manages processes based on configuration file. If process spawns child
processes, systemd recognizes child processes properly and manages under single
control group by a configuration file. Systemd can be configured automatically
restart process on crash but does not have ability to spawn process.
Supervisor
~~~~~~~~~~
Supervisor is time-proven process management tool written in python.
Supervisor can control a number of processes on UNIX-like operating systems.
Supervisor starts processes as subprocesses , so can true up/down and can be
configured automatically restart them on a crash.
Supervisor has good function itself, but must managed by init systems and
considered high availability. Supervisor is not working under Python 3. The
whole Openstack and murano are going to support python 3. This is not
appropriate for alternatives.
Combination of configuration management tool and systemd can be altenative for
implementing multiple processes. configuration management tool deploys services,
each service manages single murano-engine process.
Both proposed change and alternative can process restart if process crashed.
Proposed change can manage multi processes easier than alternative. Proposed
change has main process which spawns child processes. If you change the number
of processes, update configuration file and then restart service. On the other
hand, alternative needs to rewrite conf file of configuration managenment tool
and redeploy.
Proposed change can manage control group of murano-engine processes easier than
alternative. Because proposed change can change control group settings by update
a configuration file of systemd. On the other hand, alternative needs to update
each confifiguration file of systemd.
Data model impact
-----------------
None
REST API impact
---------------
None
Versioning impact
-------------------------
None
Other end user impact
---------------------
None
Deployer impact
---------------
The number of murano-engine workers config option is added in
murano.conf under engine section named workers. The default value
is oslo_concurrency.processutils.get_worker_count().
Developer impact
----------------
None
Murano-dashboard / Horizon impact
---------------------------------
None
Implementation
==============
Assignee(s)
-----------
Primary assignee:
<nakamura-h>
Work Items
----------
* Add the number of murano-engine workers config option to murano.conf
* Replace oslo_service.service.ServiceLauncher with
oslo_service.service.launch in murano.engine.cmd module.
Worker parameter of oslo_service.service.launch method takes
the number of murano-engine workers config option.
Dependencies
============
* oslo_concurrency
Testing
=======
* Unit tests on murano-engine
Documentation Impact
====================
None
References
==========
* `Oslo.service <https://github.com/openstack/oslo.service>`_
* `Puppet <https://github.com/puppetlabs/puppet>`_
* `Chef <https://github.com/chef/chef>`_
* `Ansible <https://github.com/ansible/ansible>`_
* `Upstart <http://upstart.ubuntu.com/>`_
* `Systemd <http://www.freedesktop.org/wiki/Software/systemd/>`_
* `Supervisor <http://supervisord.org/>`_
-222
View File
@@ -1,222 +0,0 @@
..
This work is licensed under a Creative Commons Attribution 3.0 Unported
License.
http://creativecommons.org/licenses/by/3.0/legalcode
=================================================
MuranoPL metadata to properties, classes, methods
=================================================
https://blueprints.launchpad.net/murano/+spec/metadata-in-muranopl
MuranoPL metadata is a way to attach additional information to various MuranoPL
entities such as classes, packages, methods etc. That information might be used
by both applications (to implement dynamic programming techniques) or by the
external callers (API consumers like UI or even by the Murano Engine itself
to impose some runtime behavior based on well known meta values).
Problem description
===================
With time and development of the language new challenges arrived and MuranoPL
need to be extended with new keywords for new features. For example, it may
be needed to mark some method as the one that serves special purpose to
distinguish it from other methods in the program workflow. Let's say one
wants to obtain the list of all methods within the class and choose only
methods that can be called by the unprivileged user. The one way to do
it is to introduce a new possible value for the `Usage` attribute, something
like `Usage: Non-admin`. Another way is to introduce even new keyword. The
problem is that every application developer may need to attach different kinds
of such information depending on the needs of their apps, and the range of
these needs can be endless. With the current approach, every new sort of
additional information requires modification of the core MuranoPL language
code.
In order to solve this problem, metadata will be used to store new
information about various MuranoPL entities. With this new feature MuranoPL
will become more flexible and go away from the "new keyword for new feature"
rule. All the developer will need to do is to define his own kind of data he
wants to apply to the elements of his application (in the form of the custom
MuranoPL class) and use it.
Proposed change
===============
The proposed solution is to introduce another type of classes - meta-classes.
Meta classes are similar to regular classes but has additional attributes
that control how and where instances of that meta-class can be attached.
To distinguish meta-classes from regular classes new class-level attribute
will be introduced called `Usage`. When `Usage` is `Class` (which is a default)
the rest of markup is interpreted as a class. Usage `Meta` is used to define
meta-class.
In addition to Usage the following attributes are available for meta-classes:
#. `Cardinality` - either `One` or `Many` - controls if there can be more than
one instance of the meta-class attached to a single language entity.
Default is `One`.
#. `Applies` - one of `Package`, `Type`, `Method`, `Property`, `Argument` or
`All` - controls to which of the language entities instances of the meta-
class can be attached. It is possible to specify several values using YAML
list notation. Default is `All`.
#. `Inherited` - `true` or `false` - specifies if the metadata retained for
child classes, overridden methods and properties. Default is `false`.
Now, let's take a look at the examples of the meta-class in MuranoPL:
.. code-block:: yaml
Name: FooMetaOne
Usage: Meta
Applies: Property
Cardinality: One
Properties:
description:
Contract: $.string()
Default: null
count:
Contract: $.int()
Default: null
.. code-block:: yaml
Name: FooMetaMany
Usage: Meta
Applies: [Property, Method]
Cardinality: Many
The instances of meta-classes will never have an owner and thus cannot use
`find()` function.
Instances of `FooMetaOne` class can be attached to properties only and each
property may have at most on attached `FooMetaOne` instance.
To attach this class to a property is used `Meta` keyword in a property
description.
.. code-block:: yaml
Namespaces:
=: io.murano.apps.apache
std: io.murano
res: io.murano.resources
sys: io.murano.system
meta: io.murano.meta
Name: ApacheHttpServer
Extends: std:Application
Properties:
enablePHP:
Contract: $.bool()
Default: false
instance:
Contract: $.class(res:Instance).notNull()
Meta:
meta:FooMetaOne:
description: "Stub metaclass"
count: 2
In example above Meta keyword has a scalar value because it is only one
instance get attached. However it can also be an array:
.. code-block:: yaml
Meta:
- meta:FooMetaOne:
description: "Stub metaclass"
count: 2
- meta:FooMetaMany:
- meta:FooMetaMany:
Metadata can be accessed from MuranoPL using reflection capabilities and from
Python code using existing yaql mechanism (additional yaql smart type/helper
interface may be needed to simplify the task).
Alternatives
------------
Add new keyword for new feature when we need it.
Data model impact
-----------------
None
REST API impact
---------------
None
Versioning impact
-----------------
None
Other end user impact
---------------------
None
Deployer impact
---------------
None
Developer impact
----------------
None
Murano-dashboard / Horizon impact
---------------------------------
None
Implementation
==============
Assignee(s)
-----------
Primary assignee:
starodubcevna
Work Items
----------
#. Create a new basic class instead of `MuranoType`.
#. Create 2 new classes which will inherit from new basic class - one for regular
data structures and the other one will be `MetaAttribute`.
#. Provide possibility to create instances of meta-classes.
#. Provide an access to meta-classes.
#. Create a mechanism to attach instances of meta-classes to related objects and
store it.
Dependencies
============
None
Testing
=======
New unit tests should be added to packages.
Documentation Impact
====================
New documents about metadata usage should be added to the documents pool.
References
==========
None
-169
View File
@@ -1,169 +0,0 @@
..
This work is licensed under a Creative Commons Attribution 3.0 Unported
License.
http://creativecommons.org/licenses/by/3.0/legalcode
=======================
Pluggable Package Types
=======================
URL of launchpad blueprint:
https://blueprints.launchpad.net/murano/+spec/pluggable-package-types
This spec is about making possible to support different package formats
(besides `MuranoPL/1.x` and `Heat.HOT/1.0`) via package format plugins.
Problem description
===================
There are many different formats that can be used to describe applications
besides MuranoPL. Currently Murano supports 2 package types `MuranoPL/1.x` and
`Heat.HOT/1.0`. However because they both are parts of Murano source codes
it is impossible to add additional types without merging them into main source
tree thus making Murano team responsible for all of them.
Proposed change
===============
It is proposed to have support for non-MuranoPL packages the same way HOT
support is implemented: by dynamic generation of MuranoPL code at run time.
However the package types themselves need to be pluggable so that anyone
could extend Murano with additional package type by installing corresponding
plugin.
It is proposed to use stevedore library and similar approach to how MuranoPL
python plugins are currently handled.
Package types plugins will be identified by dedicated namespace
`io.murano.plugins.packages`. To specify package type one should append to
plugin's `setup.cfg` file
.. code-block:: ini
io.murano.plugins.packages =
FORMAT_STRING = CLASS_IDENTIFIER
For example:
.. code-block:: ini
io.murano.plugins.packages =
Cloudify.TOSCA/1.0 = murano_cloudify_plugin.cloudify_tosca_package:CloudifyToscaPackage
If target package type requires some utility to construct it (e.g. put right
files in right folders, zip them, generate manifest and so on) than it
should also be included in the plugin as additional shell endpoint.
Alternatives
------------
None
Data model impact
-----------------
None
REST API impact
---------------
None
Versioning impact
-----------------
None. There cannot be 2 versions of the same plugin simultaneously.
However single plugin may support several different package formats including
severals different versions of the same format using single of several Python
classes. Version number remains part of format string.
Other end user impact
---------------------
None
Deployer impact
---------------
Plugins need to be deployed to each Murano node (or to all machines running
either Murano API or Murano Engine) in order to support particular package
type. Installation is done as usually in python (`pip install PATH` or
`python setup.py install` etc.)
Developer impact