Add Fuel Plugin SDK Guide

There are TBD sections as well as large portions of
good information. This is iteration 1 of the guide, so
I suggest we merge this and work from there. I mean merge,
if this one passess peer review for the existing chapters.

Change-Id: I0fc184b9bca466ee3bd458db1641eca4a9e93738
This commit is contained in:
Evgeny Konstantinov 2016-06-03 17:07:49 +03:00
parent 38fb26ba0d
commit 1d84ebe9ce
27 changed files with 1368 additions and 0 deletions

View File

@ -39,3 +39,13 @@ interact with each other.
devdocs/buildsystem
devdocs/infra
devdocs/packaging
Plugin documentation
~~~~~~~~~~~~~~~~~~~~
Learn how to develop and work with Fuel plugins
.. toctree::
:maxdepth: 1
plugindocs/fuel-plugin-sdk-guide

View File

@ -0,0 +1,18 @@
.. index:: Fuel Plugin SDK Guide
.. _fuel-plugin-sdk-guide:
=====================
Fuel Plugin SDK Guide
=====================
.. toctree::
:maxdepth: 3
fuel-plugin-sdk-guide/introduction.rst
fuel-plugin-sdk-guide/how-plugins-work.rst
fuel-plugin-sdk-guide/existing-plugins.rst
fuel-plugin-sdk-guide/create-plugin.rst
fuel-plugin-sdk-guide/requirements.rst
fuel-plugin-sdk-guide/limitations.rst
fuel-plugin-sdk-guide/additional-information.rst

View File

@ -0,0 +1,15 @@
.. _additional-information:
Additional information
======================
To file a defect for this document, do the following:
#. Go to the `Fuel Launchpad project <https://launchpad.net/fuel>`_.
#. Click :guilabel:`Report a bug.`
#. Put ``[SDK]`` in the :guilabel:`Summary` field and provide a summary
of the defect.
#. Provide a detailed description of the defect in the ticket body.
#. Once you save the bug, tag it with ``area-docs``.
TBD development guide & other links

View File

@ -0,0 +1,22 @@
.. _create-plugin:
Create a Fuel plugin
====================
To create a Fuel plugin, you must:
* Install Fuel Plugin Builder on the Fuel Master node.
* Create a plugin.
This section includes the following topics:
.. toctree::
:maxdepth: 3
create-plugin/install-plugin-builder.rst
create-plugin/create-auto-plugin.rst
create-plugin/describe-plugin.rst
create-plugin/define-plugin-actions.rst
create-plugin/actions-existing-roles.rst
create-plugin/plugin-settings.rst
create-plugin/plugin-node-roles.rst

View File

@ -0,0 +1,254 @@
.. _actions-existing-roles:
Actions for existing roles
--------------------------
The ``deployment_tasks.yaml`` file contains tasks that define actions.
The tasks that define actions execute on the existing roles.
Basic syntax for a task definition:
.. code-block:: ini
type: <type of task>
groups: [<one or more of existing roles>]
required_for: [<the list of tasks, which requires this one>]
requires: [<the list of tasks, which a required for this one>]
parameters:
<parameter name>: <parameter value>
.. note:: You can represent the lists in the full form or the abbreviated
form:
* Full:
.. code-block:: ini
keyword:
- value1
- value2
- value3
* Abbreviated:
.. code-block:: ini
keyword: [ value1, value2, value3 ]
**Examples**
We will provide examples of tasks that define actions. We will also provide
examples of how to test the tasks.
We will list possible keyword values for reference.
Prerequisites
* A deployed Fuel environment with one controller node and one compute node.
* A plugin enabled in the environment settings.
You can make live changes to the plugin's deployment tasks, as this is much
faster to test the changes this way rather than do the full environment
reinstallation for every task change.
.. tip:: Here is how plugin live update works. When a plugin is installed,
its files are in the directory
``/var/www/nailgun/plugins/<plugin name>`` on the Fuel Master node:
``plugin root directory`` or ``plugin root``; the definitions of tasks
are in the Nailgun database.
To quickly change and debug the plugin tasks, edit the files in
the ``/var/www/nailgun/plugins/<plugin name>`` directory without
rebuilding and reinstalling the plugin. Then synchronise the Nailgun
database content with the filesystem with the command
:command:`fuel plugins --sync`.
You can also update the plugin from one version to a newer one with
the command
:command:`fuel plugins --update <rpm package for a new version of the plugin>`.
In this case you also need to run :command:`fuel plugins --sync`
after that.
You can also download all task definitions, including the core and
plugins tasks, for the environment with the command
:command:`fuel env --env <env-id> --deployment-tasks --download`
and verify that your plugin's tasks are present by searching for
the task IDs.
You can also change the tasks inside this file directly and then
upload it. This way you can change and debug the already existing
core tasks on the Fuel Master node in ``/etc/puppet/modules``,
not related to your plugin, but this is outside of the scope of this
guide.
To make it simple, we will delete the automatically generated ``tasks.yaml``
and ``deployment_tasks.yaml`` files. We will create a new
``deployment_tasks.yaml`` from scratch.
Add a task to execute shell commands:
.. code-block:: ini
- id: fuel-plugin-example-iotop
type: shell
role: '*'
requires: [post_deployment_start]
required_for: [post_deployment_end]
parameters:
cmd: apt install iotop && echo `date` ' iotop installed' >>
/tmp/post_deployment || echo `date` ' failed to install iotop'
>> /tmp/post_deployment
Then sync the plugin tasks, execute the newly defined one, and verify the resultsЖ
.. code-block:: console
# fuel plugins --sync
# fuel node --nodes 1,2 --tasks fuel-plugin-example-iotop
# ssh node-1 "cat /tmp/post_deployment; iotop --version"
Fri May 20 12:48:08 UTC 2016 iotop installed
iotop 0.6
.. note:: In the snippet above, the values for the node IDs and the node
name are just examples and they may differ from the ones in your
installation. To find the correct values, use the command
``fuel nodes``.
The task in the example executes the shell commands listed in the parameter
``cmd``: the task installs the package iotop on all the nodes in the
environment; or, in our test, in the subset listed after the key '--nodes'.
Pay attention to the parameters ``requires`` and ``required_for``: they define
when exactly during installation the task will run and are required for the
task execution. The task will usually run in the post-deployment stage, but in
our example we forced it to run alone. After the task execution, you can use
the command :command:`iotop` to monitor the I/O on the environment nodes.
.. note:: If you receive the error message ``400 Client Error: Bad Request
(Problem with loading YAML file /var/www/nailgun/plugins/
fuel-plugin-example-1.0/deployment_tasks.yaml)``, verify the syntax
of ``deployment_tasks.yaml``.
The error ``400 Client Error: Bad Request (Tasks fuel-plugin-example
-iotop are not present in deployment graph)`` means that your tasks
failed to synchronise with the Nailgun database or that your plugin
is not enabled for the environment with the nodes that you specified.
If other issues, check the Astute log on the Fuel Master node at
``/var/log/docker-logs/astute/astute.log``. Alternatively, check
the :guilabel:`Logs` tab in the Fuel web UI.
In our example, we used the asterisk '*' as the value for the keyword
``role``. To run the tasks only on particular roles, but not the others,
replace the value with the list of roles on which to run; for example:
.. code-block:: ini
role: [ primary-controller, controller, compute]
.. note:: Use the list even if your task needs to run on only one role;
for example ``role: [compute]``. This will not work:
``role: compute``.
.. note:: The roles ``primary-controller`` and ``controller`` are not the
same. The ``controller`` role does not include the
``primary-controller`` role, so they should be specified explicitly.
.. note:: While you can run tasks on particular roles, you cannot run tasks on
all roles except a particular role. For example, there is option
to run tasks on all roles except for a compute role.
Our example task with the commands listed in the cmd parameter is not suitable
for more than two shell commands; but we always can put the commands in
a shell script and call the script instead:
.. code-block:: ini
parameters:
cmd: bash install_iotop.sh
Put the script ``install_iotop.sh`` in the subdirectory ``deployment_scripts``
in ``plugin root``. If you run the plugin task, the result will be the same as
in the previous case, when we defined all the commands in
``deployment_tasks.yaml``.
The mechanism behind this is as follows. Before the plugin task runs, all the
files inside the ``plugin root`` are synced by rsync protocol to the directory
``/etc/fuel/plugins/<plugin name>`` on target nodes. This directory is set as
the default working directory for plugin tasks -- although you can override it
by specifying the explicit ``cwd`` parameter for the task, so the command
:command:`bash install_iotop.sh` will run the script from it.
Considering that deployment scripts are copied to target nodes before any of
the tasks run, you can skip the step for syncing tasks if you only change the
contents of the deployment scripts in the process of debugging and run the
tasks directly after the changes.
You can use any script language or executable as long as they can be called
from shell, but Puppet is the most common tool to write Fuel plugins and there
is support for Puppet tasks.
Let us rewrite the same task using Puppet manifests.
``deployment_tasks.yaml``:
.. code-block:: ini
- id: fuel-plugin-example-iotop
type: puppet
role: '*'
requires: [post_deployment_start]
required_for: [post_deployment_end]
parameters:
puppet_manifest: puppet/manifests/install_iotop.pp
puppet_modules: puppet/modules:/etc/puppet/modules
``deployment_scripts/puppet/manifests/install_iotop.pp``:
.. code-block:: ini
notice('MODULAR: fuel-plugin-example/iotop')
package { 'iotop':
ensure => 'installed',
}
.. note:: All plugin tasks must be idempotent: each plugin task must be able
to run multiple times without changing the results. Puppet manifests
have an inherent advantage of idempotency and this is one of the
reasons to use Puppet for plugin tasks.
We changed the ``type`` attribute of the deployment task to ``puppet`` and
replaced the ``cmd`` parameter with the two Puppet specific ones:
``puppet_manifest`` and ``puppet_modules``. If you are familiar with Puppet,
these parameters are self-explanatory. The values of the parameters are path
specifications relative to the ``deployment_scripts`` directory in
``plugin root``. Follow the standard Puppet conventions and keep Puppet
manifests in modules in separate subdirectories. In our example we are using
no modules, but in any other not so trivial case it is good to keep the code
modular. The parameter ``puppet_modules`` is required.
.. note:: Pay attention to the first line of our Puppet manifest:
.. code-block:: ini
notice('MODULAR: fuel-plugin-example/iotop')
This is a convention to start any of your Puppet tasks in a plugin
with the notice statement that starts with a substring ``MODULAR:``
followed by the name of the plugin and the name of the task itself.
This output is in the Puppet logs. You can find the output in the
:guilabel:`Logs`of the Fuel web UI, at ``/var/log/puppet.log`` on
the Fuel target node, or at
``/var/log/remote/<target node IP>//puppet-apply.log``. This
convention is very helpful for debugging.
**Related links**
See also `Deployment Tasks on Fuel Wiki <https://wiki.openstack.org/wiki/Fuel/Plugins#deployment_tasks.yaml>`_.
.. toctree::
:maxdepth: 3
create-plugin/actions-existing-roles/deployment-stages.rst
create-plugin/actions-existing-roles/skip-core-tasks.rst

View File

@ -0,0 +1,126 @@
.. _deployment-stages:
Pre- and post-deployment stages
-------------------------------
Fuel can execute tasks in the pre- or post-deployment stages.
For information on how to put tasks in a post-deployment stage, see
:ref:`actions-existing-roles`.
**To put a task in a pre-deployment stage**
Change the snippet:
.. code-block:: ini
requires: [post_deployment_start]
required_for: [post_deployment_end]
to
.. code-block:: ini
requires: [pre_deployment_start]
required_for: [pre_deployment_end]
.. note:: Fuel defines a number of tasks organised in a graph. Fuel traverses
this graph during deployment; each task from the graph executes in
its turn. See the in-depth description of the process in the
*Modular Architecture* section of *Developer Guide*.
We will call the tasks that are already defined by Fuel *core tasks*,
as opposed to *plugin tasks*.
The core tasks execute Puppet manifests from the directory
``/etc/puppet/modules/osnailyfacter/modular/`` on the target nodes.
The entire ``/etc/puppet`` tree in turn syncs from the Fuel Master
node to target nodes before the deployment.
If you need to put plugin tasks in a specific position of the graph,
examine the graph and determine the right place for your task. To get
the graph, use the command :command:`fuel graph`. You can get the
plain text representation of the graph in the
`DOT <https://en.wikipedia.org/wiki/DOT_(graph_description_language)>`_
format using the command
:command:`fuel graph --env 1 --download > graph.gv`. After that you
can generate the picture in the PNG format from it, using the
command :command:`fuel graph --render graph.gv --tred; ensure you
install additional packages to the Fuel Master node with the
following commands:
.. code-block:: console
yum install graphviz
rpm -i https://www.dropbox.com/s/1fyv9p55kslbxkg/python-pygraphviz-1.3-3.rc2.el7-mos1.x86_64.rpm
The key ``--tred`` is optional, but it forces the graph to be
`transitionally reducted <https://en.wikipedia.org/wiki/Transitive_reduction>`_,
in other words -- much simpler.
See a `sample graph generated for Fuel 8.0 Maintenance Update 1
environment <https://www.dropbox.com/s/xbq9w018pvmbgbb/graph.gv.tred.png>`_.
**To put a task in a main deployment stage**
#. Change the keyword ``role`` to ``groups`` -- ensure the singular ``role``
and the plural ``groups``. The keyword ``groups`` supports the list of
roles on which the task runs as the value, but does not support the
wildcard '*', so it is necessary to specify each role explicitly.
#. Specify a timeout in the parameters of the task, otherwise it will not run.
#. The start and the end of the main deployment stage are ``deploy_start``
and ``deploy_end``. Do not confuse these with ``deployment_start`` and
``deployment_end``, which are the counterparts for other stages, not the
main stage.
A working example for the main deployment stage:
.. code-block:: ini
- id: fuel-plugin-example-iotop
type: puppet
groups: [primary-controller, controller, compute]
requires: [deploy_start]
required_for: [deploy_end]
parameters:
puppet_manifest: puppet/manifests/install_iotop.pp
puppet_modules: puppet/modules:/etc/puppet/modules
timeout: 720
.. note:: For testing purposes, you can run not one task, but a range
of them. To do this, use the following form of the command
:command:`fuel node`:
.. code-block:: console
fuel node --node <node-id>--start <name of the first task>
--end <name of the last task> [ --skip <list of the tasks that
should be skipped> ]
For example, to make the task run between the main stage's tasks
``firewall`` and ``hosts``:
.. code-block:: ini
- id: fuel-plugin-example-iotop
type: puppet
groups: [compute]
requires: [firewall]
required_for: [hosts]
parameters:
puppet_manifest: puppet/manifests/install_iotop.pp
puppet_modules: puppet/modules:/etc/puppet/modules
timeout: 720
To run a range of tasks from ``firewall`` to ``hosts``, skipping
the tasks related to SSL, use the following command:
.. code-block:: console
fuel node --node 2 --start firewall --end hosts --skip
ssl-add-trust-chain ssl-keys-saving ssl-dns-setup
Started tasks [u'firewall', u'fuel-plugin-example-iotop',
u'hosts'] for nodes nodes [7].

View File

@ -0,0 +1,25 @@
.. _skip-core-tasks:
Skipping core tasks
-------------------
Core tasks are the tasks defined by Fuel, as opposed to plugin tasks.
You can disable core tasks from running on target nodes either completely
or to overrun the core tasks with your plugin tasks.
For example, networking plugins often disable creation of the default
networks, which are usually created by Fuel during deployment. You can
do this by describing the task with the same ID as the existing one and
the type ``skipped``:
``deployment_tasks.yaml``:
.. code-block:: ini
- id: openstack-network-networks
type: skipped
.. note:: If you try to redefine a core task by creating a new task with same
ID as the one of the existing, the deployment will fail.

View File

@ -0,0 +1,116 @@
.. _create-auto-plugin:
Create an automatically generated plugin
----------------------------------------
The automatically generated plugin is a template for your plugin.
The automatically generated plugin does the following:
#. Creates the file ``/tmp/plugin.all`` on all nodes in the environment.
#. Runs the ``deployment_scripts/deploy.sh`` script. This creates the
``/tmp/fuel-plugin-example file`` on the controllers.
#. Creates a new role ``fuel-plugin-example_role``.
**To create an automatically generated plugin**
#. Log into the Fuel Master node.
#. Run:
.. code-block:: console
fpb --create fuel-plugin-example
This will generate the following files:
+----------------------------------------------+--------------------------------------------------+
| File | Descrption |
+==============================================+==================================================+
|``components.yaml`` |Fuel web UI components |
+----------------------------------------------+--------------------------------------------------+
|``deployment_scripts`` |Directory for the plugin tasks code |
+----------------------------------------------+--------------------------------------------------+
|``deployment_scripts/deploy.sh`` |Shell script sample |
+----------------------------------------------+--------------------------------------------------+
|``deployment_tasks.yaml`` |Definition of plugin tasks |
+----------------------------------------------+--------------------------------------------------+
|``environment_config.yaml`` |Fuel web UI plugin parameters |
+----------------------------------------------+--------------------------------------------------+
|``fuel-plugin-example-1.0-1.0.0-1.noarch.rpm``|A plugin package created after you build a plugin |
+----------------------------------------------+--------------------------------------------------+
|``LICENSE`` |Standard Apache 2.0 license file |
+----------------------------------------------+--------------------------------------------------+
|``metadata.yaml`` |Plugin information |
+----------------------------------------------+--------------------------------------------------+
|``network_roles.yaml`` |Network roles data |
+----------------------------------------------+--------------------------------------------------+
|``node_roles.yaml`` |Definition of new node roles created by the plugin|
+----------------------------------------------+--------------------------------------------------+
|``pre_build_hook`` |Actions to run on plugin build |
+----------------------------------------------+--------------------------------------------------+
|``README.md`` |Free-form description of plugin |
+----------------------------------------------+--------------------------------------------------+
|``repositories`` |Directory for plugin specific packages |
+----------------------------------------------+--------------------------------------------------+
|``repositories/centos`` |Directory for plugin CentOS packages |
+----------------------------------------------+--------------------------------------------------+
|``repositories/ubuntu`` |Directory for plugin Ubuntu packages |
+----------------------------------------------+--------------------------------------------------+
|``tasks.yaml`` |Deprecated, use ``deployment_tasks.yaml`` instead |
+----------------------------------------------+--------------------------------------------------+
|``volumes.yaml`` |Mapping between node roles and volume allocation. |
| |You can also define new volumesand map them to the|
| |new or existing nodes. |
+----------------------------------------------+--------------------------------------------------+
#. Build the automatically generated plugin:
.. code-block:: console
fpb --build fuel-plugin-example
#. Copy the plugin to the Fuel Master node.
#. Deploy a new environment.
#. Install the plugin:
.. code-block:: console
fuel plugins --install fuel-plugin-example/fuel-plugin-example-1.0-1.0.0-1.noarch.rpm
The resulting RPM file is what you need to redistribute to the end user.
After installing the plugin, you can view it in the Fuel web UI on the
:guilabel:`Plugins` tab.
You can also verify the plugin installation using Fuel CLI:
.. code-block:: console
# fuel plugins --list
id | name | version | package_version
---|---------------------|---------|----------------
1 | fuel-plugin-example | 1.0.0 | 4.0.0
**To enable the installed plugin**
#. In the Fuel web UI, click :guilabel:`Other`, then :guilabel:`Settings`.
#. Check the plugin box.
.. note:: If you can see your plugin in the ``fuel plugins --list`` output,
but not in the Fuel web UI, then your plugin does not support the
installed version of Fuel. Specifically, the plugin does not have
the version of the Fuel Master node in its ``metadata.yaml``.
.. tip:: By default, all plugin settings are under the group 'Other'. To place
your plugin settings to a different group, specify it
``in environment_config.yaml``.
.. tip:: Tip: Although after you install the plugin, you see the plugin
settings in the deployed environment, you cannot enable the plugin.
Enabling a plugin after deployment makes sense only in one case:
when this adds a new node role and a node with this role can be
added after the environment is deployed. In this case use the keyword
``is_hotppluggable`` in ``metadata.yaml``

View File

@ -0,0 +1,34 @@
.. _define-plugin-actions:
Define plugin actions
---------------------
All actions that a plugin can execute fall into the following categories:
* Actions for the existing roles -- all nodes have one or more roles
associated with them; for example, controller or compute. You can
change the deployment process for the roles defined by Fuel or add
new actions for these roles.
* Actions for plugin specific roles -- you can create a new role; for
example, if you want to deploy a product that runs on the nodes separate
from the ones running the OpenStack services deployed by Fuel,
and define all the actions that should be executed on such nodes.
* Actions executed on the Fuel Master node -- you can change the Fuel Master
node. Generally this is not recommended, as you may accidentally affect
the environments on which the user does not want the plugin to be enabled.
There are options to do this.
.. note:: There are two files with the definitions of plugin actions:
``tasks.yaml`` and ``deployment_tasks.yaml``.
The ``tasks.yaml`` file is deprecated and can only contain
definitions of tasks in the outdated format used in Fuel 6.0.
You can only describe the pre- and post-deployment tasks using
the old format.
The file ``deployment_tasks.yaml`` can contain tasks in the same old
format, but also tasks in the new format, which supports the main
deployment tasks and task dependencies.
Use ``deployment_tasks.yaml`` and only the new format for all task
definitions.

View File

@ -0,0 +1,57 @@
.. _describe-plugin:
Describe your plugin
--------------------
The Fuel Plugin Builder generates three files:
* LICENSE -- free-form information file.
* README.md -- free-form information file.
* ``metadata.yaml`` -- mandatory file in YAML format. Your plugin cannot
build without ``metadata.yaml``.
.. note:: You can put any files -- even the ones not directly related to
Fuel Plugin Builder -- in the plugin directory. Fuel Plugin Builder
will add all the files to the plugin package.
**To describe your plugin**
#. Edit the ``LICENSE`` file so that it contains the license, under which
your plugin can be redistributed. You may want to use the
`Apache 2.0 <http://www.apache.org/licenses/LICENSE-2.0>`_ license.
All plugin files that provide intellectual property must have a respective
copyright.
#. Edit the ``README.md`` file -- put some free-form description of the plugin
here. Describe the purpose of your plugin and give instructions on the
installation. If you publish the code of your plugin on GitHub, the contents
of this file will be on the main page of the repository. You can use
MarkDown formatting in the file. For more information see
`Getting started with writing on GitHub <https://help.github.com/articles/getting-started-with-writing-and-formatting-on-github/>`_. Good examples of plugin description:
`Mellanox <https://github.com/openstack/fuel-plugin-mellanox/blob/stable/3.0.0/README.md>`_
and `LMA Collector <https://github.com/openstack/fuel-plugin-lma-collector>`_.
#. Edit the ``metadata.yaml`` file with the list of required parameters:
* ``name`` -- Name of the plugin that will be in the plugin's RPM filename.
* ``title`` -- Human-readable plugin name.
* ``version`` -- Plugin version.
* ``description`` -- A short description of the plugin purpose. This will
be displayed in the Fuel web UI, once the environment with the plugin is
deployed.
* ``fuel_version`` -- The Fuel version that your plugin is compatible with.
* ``licenses`` -- List the licenses under which your plugin can be
distributed.
* ``authors`` -- Name of the plugin author. A company or an individual.
* ``homepage`` -- A link to page with your plugin. This can be your plugin's
GitHub repository page.
* ``groups`` -- A group to which your plugin belongs on the Fuel web UI.
* ``releases: os`` -- A compatible operating system for the plugin.
* ``releases: version`` -- A compatible OpenStack version.
* ``releases: mode`` -- Plugin mode.
* ``releases: deployment_scripts_path`` -- A path for the deployment script.
* ``releases: repository_path`` -- A path for the compatible operating system.
* ``package_version`` -- Version of the plugin package.
See the `metadata.yaml example <https://github.com/openstack/fuel-plugin-openbook/blob/master/metadata.yaml>`_.

View File

@ -0,0 +1,67 @@
.. _install-plugin-builder:
Install Fuel Plugin Builder
---------------------------
You must install the Fuel Plugin Builder on the Fuel Master node.
You must use the Fuel Master node as the build environment.
**To install the Fuel Plugin Builder**
#. Log into the Fuel Master node.
#. Install the required packages:
.. code-block:: console
yum install -y git python-mako createrepo dpkg-devel dpkg-dev rpm rpm-build
#. Clone the Fuel Plugin Builder repository:
.. code-block:: console
git clone https://github.com/openstack/fuel-plugins
#. Change to the ``fuel-plugins`` directory:
.. code-block:: console
cd fuel-plugins
#. Check out a specific commit from the Fuel Plugin Builder repository
compatible with Fuel 8.0:
.. code-block:: console
git checkout a22bc32
Without this commit you should always have the deprecated ``tasks.yaml``
in the plugin, even if it is empty or the plugin will not build.
.. note:: If the plugin metadata does not specify the same version of
OpenStack as the one supported by the Fuel Master node,
on which the plugin is installed, you will not see any
plugin fields in the Fuel web UI. To be compatible with Fuel 8.0,
the ``metadata.yaml`` file of the plugin must contain the
following lines:
.. code-block:: ini
releases:
- os: ubuntu
version: liberty-8.0
mode: ['ha']
#. Build and install the Fuel Plugin Builder:
.. code-block:: console
python setup.py install
#. Verify the installed version of the Fuel Plugin Builder:
.. code-block:: console
python -c 'import pkg_resources; print pkg_resources.get_distribution("fuel-plugin-builder").version'
This should display ``4.0.0``.

View File

@ -0,0 +1,28 @@
.. _plugin-node-roles:
Plugin node roles
-----------------
Defining a new role allows you to explicitly define all the tasks that run on
it.
Defining a new role is convenient if you need to run some services on
separate nodes:
* If you deploy a service with some specific hardware or security
requirements.
* If your software conflicts with some of the packages installed on
the existing roles
* If the tasks that you execute conflict with the existing tasks.
.. toctree::
:maxdepth: 3
create-plugin/plugin-node-roles/define-new-role.rst
create-plugin/plugin-node-roles/volume-allocation.rst
create-plugin/plugin-node-roles/hot-pluggable.rst
create-plugin/plugin-node-roles/modify-ui.rst
create-plugin/plugin-node-roles/plugin-repos.rst

View File

@ -0,0 +1,132 @@
.. _define-new-role:
Define a new role
-----------------
You must define a new role in ``node_roles.yaml``.
The automatically generated plugin contains one example role in the file,
but you can delete the contents of the file and start with a new role:
.. code-block:: ini
fuel-plugin-example_role:
name: Example plugin role
description: Just a test role
weight: 1000
The only required field besides the ID here is ``name``, but this is always
a good idea to provide some description of the role's purpose. The parameter
``weight`` defines relative placement of the role in the list of roles in the
Fuel web UI. Standard roles have weights from 10 to 100, with the weight 1000
your role will appear at the end of the list. You can look up the exact values
as well as the definitions for the standard roles at
`openstack.yaml on GitHub <https://github.com/openstack/fuel-web/blob/stable/8.0/nailgun/nailgun/fixtures/openstack.yaml#L9>`_ .
Like plugin tasks and unlike plugin settings, role definitions are affected by
the :command:`fuel --sync`` command and can be easily updated.
To verify that your new role is defined and can be assigned to new nodes use
the button :guilabel:`Add nodes` in the :guilable:`Nodes` UI tab:
url ``http://<fuel ip>:8000/#cluster/<cluster id>/nodes/add``.
.. note:: Keep in mind that a plugin should be enabled for its roles to appear
in the Fuel web UI.
You must define a new group for the tasks that belong to the new role in
``deployment_tasks.yaml``:
.. code-block:: ini
- id: fuel-plugin-example_role
type: group
role: [fuel-plugin-example_role]
tasks: [globals]
parameters:
strategy:
type: parallel
The ID of the group must be the same as the ID of the new role. You define
the list of the core tasks, which run on the new role, in the field ``tasks``.
The parameter ``strategy`` is required and it defines how the deployment
should proceed if there are multiple nodes to be deployed with the role.
The possible values for ``strategy`` are:
* ``one-by-one`` -- all the nodes with the role will be deployed
sequentially, one after another
* ``parallel`` -- nodes will be deployed in parallel, at the same time
.. note:: Fuel 8.0 Maintenance Update 1 runs hooks on the target nodes with
a new role even if you defined no tasks for the role. One of such
hooks creates the file ``/etc/hosts`` on targets and it will fail
with the error ``Could not find data item node_name_prefix_for_
messaging in any Hiera data file and no default supplied at
/etc/puppet/modules/osnailyfacter/modular/hosts/hosts.pp:6``
if the task ``globals`` was not run before it. You should always add
``globals`` or the one that depends on it in the list of the tasks
for a new role; the task ``global``, in turn, depends on tasks
``hiera``, ``setup_repostories``, and ``fuel_pkgs``, which provide
some basic configuration of the node: for example, the ``hiera``
task configures hiera, so all of the settings defined via the Fuel
web UI are available through hiera.
The next step after determining core tasks that should be run on your role,
will be to define plugin tasks and the process is the same as the one that
described in :ref:`actions-existing-roles`. The only difference is that you
will use the ID of the new role in the task definition:
.. code-block:: ini
- id: fuel-plugin-example-iotop
type: puppet
role: [fuel-plugin-example_role]
requires: [post_deployment_start]
required_for: [post_deployment_end]
parameters:
puppet_manifest: puppet/manifests/install_iotop.pp
puppet_modules: puppet/modules:/etc/puppet/modules
The difference between the deployment of the nodes with the new role and the
pre-existing ones is that only the core tasks that you explicitly defined in
the tasks field of the role's group definition will run on the node with the
new role, while there is a predefined list of core tasks to run on the nodes
with pre-existing roles.
.. tip:: For debugging purposes, deploy the environment consisting only of
the node with the role defined by a plugin. By default, you cannot
deploy an environment without a controller from the Fuel web UI, so
here is an example showing how to do this with the help of Fuel CLI:
.. code-block:: console
# fuel env create --name test-plugin-role-1 --rel 2
Environment 'test-plugin-role-1' with id=3 was created!
# id=`fuel env | grep test-plugin-role-1 | tr -d ' ' |cut -d\| -f1`
# fuel --env $id settings download
# awk -F: 'BEGIN {OFS = FS} $1 ~ "fuel-plugin-example" { f=1 } f && $1 ~
"enabled" { f=0; $2=" true"} { print } ' settings_${id}.yaml > tmp && mv
tmp settings_${id}.yaml
# fuel --env $id settings upload
# fuel --env $id node set --node 10 --role fuel-plugin-example_role
Nodes [10] with roles ['fuel-plugin-example_role'] were added to environment 3
# fuel --env $id deploy-changes
This example does the following:
* Creates a new environment.
* Downloads the settings.
* Changes the plugin to be enabled in the settings by changing the
plugin ``enabled`` parameter from ``false`` to ``true`` through
AWK.
* Uploads the settings back to the Nailgun database.
* Adds a new node with the role ``fuel-plugin-example_role`` to the
environment.
* Deploys this new environment consisting only of one node with the
new role.
You can create a new environment, enable the plugin in it, and add
a single node with the new role from the Fuel web UI, using only the
last command to deploy the environment then.

View File

@ -0,0 +1,7 @@
.. _hot-pluggable:
Hot pluggable plugins
---------------------
TBD

View File

@ -0,0 +1,7 @@
.. _modify-ui:
Modify the Fuel web UI
----------------------
TBD

View File

@ -0,0 +1,7 @@
.. _plugin-repos:
Plugin repositories
-------------------
TBD

View File

@ -0,0 +1,7 @@
.. _volume-allocation:
Volume allocation
-----------------
TBD

View File

@ -0,0 +1,16 @@
.. _plugin-settings:
Plugin settings
---------------
You can add plugin setting to the Fuel web UI, set restrictions, task
conditions, and override the core task settings.
.. toctree::
:maxdepth: 3
create-plugin/plugin-settings/add-settings.rst
create-plugin/plugin-settings/settings-restrictions.rst
create-plugin/plugin-settings/task-conditions.rst
create-plugin/plugin-settings/override-core-settings.rst

View File

@ -0,0 +1,261 @@
.. _add-settings:
Add plugin settings to the Fuel web UI
--------------------------------------
You can add your plugin settings to the Fuel web UI.
**To add plugin settings to the Fuel web UI**
To place plugin specific settings to the Fuel web UI on the
:guilabel:`Settings` tab, you must edit the ``environment_config.yaml`` file.
An automatically generated plugin contains only one example text field setting
in the group :guilabel:`Other`:
.. code-block:: ini
attributes:
metadata:
# Settings group can be one of "general", "security", "compute", "network",
# "storage", "logging", "openstack_services" and "other".
group: 'other'
fuel-plugin-example_text:
value: 'Set default value'
label: 'Text field'
description: 'Description for text field'
weight: 25
type: "text"
Change the file to include more UI elements definitions:
.. code-block:: ini
attributes:
# Text field
fuel_plugin_example_text:
type: "text"
weight: 10
value: "default value"
label: "Text field label"
description: "Field description"
regex:
source: '\S'
error: "Error field cannot be empty"
# Select
fuel_plugin_example_select:
type: "select"
weight: 20
value: "value2"
label: "Select label"
description: "Select description"
values:
- data: "value1"
label: "Value 1 label"
- data: "value2"
label: "Value 2 label"
- data: "value3"
label: "Value 3 label"
# Checkbox
fuel_plugin_example_checkbox:
type: "checkbox"
weight: 30
value: true
label: "Checkbox label"
description: "Checkbox description"
# Radio button
fuel_plugin_example_radio:
type: "radio"
weight: 40
value: "data1"
label: "Radio buttons label"
values:
- data: "data1"
label: "Label data1"
description: "Description data1"
- data: "data2"
label: "Label data2"
description: "Description data2"
- data: "data3"
label: "Label data3"
description: "Description data3"
.. note:: There is no ``group`` for plugin settings in this example, so the
settings for the plugin are under the default group
:guilabel:`Other` in the :guilabel:`Settings` tab of the Fuel web
UI. You can specify one of the values ``general``, ``security``,
``compute``, ``network``, ``storage``, ``logging``,
``openstack_services``, ``other`` as the group to place plugin
settings in. All of the groups with the exception of ``network``
will be placed in the :guilabel:`Settings` tab, settings in the
``network`` group will be put in the :guilabel:`Networks` tab.
Currently it is not possible to spread the settings for one plugin
between multiple groups.
**Debug the Fuel web UI settings**
Changes in ``environment_config.yaml`` affect only the environments which you
create after the changes, even if you use :command:`fuel plugins --sync`.
The Nailgun database stores each piece of the environment settings at the time
of the environment creation. During this time the synchronisation process does
not update the settings.
To debug the Fuel web UI settings, use one of the following approaches:
* Create a new environment after changing the settings definition. This might
be tedious, but you can speed up the process by using the command like this
from Fuel CLI:
.. code-block:: console
# fuel env create --name settings-test --rel 2 ; read -p 'Press any key
to delete test env...' key; fuel env --delete --env `fuel env | grep
settings-test | cut -d\| -f1`
Environment 'test2' with id=20 was created!
Press any key to delete test env...
Environment with id=20 was deleted
This command creates an environment with the name ```settings-test``, waits
while you press any key, then deletes it. Unfortunately, you cannot just
reload the web page with the UI settings after using this command, as the
URL contains the environment ID, which is new for each created environment.
* Download the settings for the existing environment with the command
:command:`fuel --env <env-id> settings --download`, find your settings by
searching for the substring with the name of your plugin in the downloaded
file -- named ``settings_<env-id>.yaml`` -- and then upload the file back
with the command :command:`fuel --env <env-id> settings --upload`. The plugin
must be enabled in the environment for this method to work.
Ensure that your browser does not use a stale page cache. In many browsers you
can use the shortcut SHIFT-F5 (CMD-R in Mac OS) to reload the page skipping
browser's cache.
.. note:: This is always a good idea to ensure that your browser bypasses
cache before trying to debug issues with the Fuel web UI.
Before the deployment starts, Astute uploads all settings to the the
``/etc/astute.yam``l file on each of the target nodes. This file contains
the section for the plugin:
.. code-block:: ini
fuel-plugin-example:
fuel_plugin_name_checkbox: true
fuel_plugin_name_radio: data1
fuel_plugin_name_select: value2
fuel_plugin_name_text: default value
metadata:
always_editable: false
class: plugin
enabled: true
label: Title for fuel-plugin-example plugin
plugin_id: 1
plugin_version: 1.0.0
toggleable: true
weight: 70
The metadata fields, which are not defined explicitly in
``environment_config.yaml``, receive default values, while each of the UI
elements sets a corresponding parameter in ``astute.yaml``.
One of the core tasks named ``hiera`` configures hiera so that ``astute.yaml``
becomes one of the sources of information for it. Using ``hiera`` to get the
values for the settings as opposed to manual parsing of ``astute.yaml`` is
strongly recommended.
Examples of ``hiera`` lookups:
Bash:
.. code-block:: ini
STR=$(hiera “str”)
HASH=$(hiera -h “hash_name”)
ARRAY=$(hiera -a “array_name”)
Puppet:
.. code-block:: ini
$str = hiera(str, )
$arr = hiera_array(arr_name, [])
$hash = hiera_hash(hash_name, {})
Ruby:
.. code-block:: ini
#!/usr/bin/env ruby
require 'hiera'
ENV['LANG'] = 'C'
hiera = Hiera.new(:config => '/etc/hiera.yaml')
glanced = hiera.lookup 'glance', {} , {}, nil, :hash
nodes_array = hiera.lookup 'nodes', [], {}, nil, :array
Use :command:`hiera <plugin name>' to verify all of the plugin settings
from the shell prompt on a target node:
.. code-block:: console
# hiera fuel-plugin-example
{"fuel_plugin_name_select"=>"value2",
"fuel_plugin_name_checkbox"=>true,
"fuel_plugin_name_radio"=>"data1",
"fuel_plugin_name_text"=>"default value 1",
"metadata"=>
{"plugin_version"=>"1.0.1",
"group"=>"other",
"always_editable"=>false,
"weight"=>70,
"enabled"=>true,
"label"=>"Title for fuel-plugin-example plugin",
"toggleable"=>true,
"plugin_id"=>1,
"class"=>"plugin"}}
Use the plugin settings to generalize the *iotop* task, so it will install
the packages from the list specified in the UI settings. Currently it is not
possible to dynamically add settings to the Fuel web UI, so use the
``textarea field``, which contains the names of the packages that you want
to install on the target node, one per line.
.. note:: You can dynamically add setting starting with Fuel 9.0.
See the `blueprint <https://blueprints.launchpad.net/fuel/+spec/dynamic-fields>`_.
``environment_config.yaml``:
.. code-block:: ini
attributes:
fuel_plugin_example_packages:
description: Field description
label: Text field label
type: textarea
value: default value
Update the Puppet manifest, so it will install all the packages in the
variable ``fuel_plugin_example_packages``, which it will get from hiera:
``deployment_scripts/puppet/manifests/install_iotop.pp``:
.. code-block:: ini
notice('MODULAR: fuel-plugin-example/iotop')
$fuel_plugin_example = hiera(fuel-plugin-example, {})
$packages = split($fuel_plugin_example['fuel_plugin_example_packages'], '\n')
package { $packages:
ensure => 'installed',
}
.. note:: If you do not want to provide Fuel web UI settings for your plugin,
except for the :guilabel:`Enable plugin` checkbox, you still need to
fill the ``environment_config.yaml`` with metadata for that checkbox.

View File

@ -0,0 +1,7 @@
.. _override-core-settings:
Override core settings
----------------------
TBD

View File

@ -0,0 +1,50 @@
.. _settings-restrictions:
Settings restrictions
---------------------
Plugin functionality can depend on some core features of Fuel or on the
features of other plugins. You can provide only some subset of the
functionality when some core feature is disabled and, vice versa, the
full functionality. You can also provide different functions depending
on what kind of hypervisor the user selects. Settings restrictions provide
a way to dynamically change the settings provided by a plugin. The general
information on the settings restrictions is in
*Developer Guide* -> *Extending OpenStack Settings* -> *Restrictions*.
Settings restrictions are defined in ``environment_config.yaml`` and can be
applied not only to any specific setting but also for a plugin as a whole.
In this case, the restrictions should be applied to plugin metadata.
This is an example of using restrictions in `Fuel Xenserver plugin <https://github.com/openstack/fuel-plugin-xenserver/blob/8.0/environment_config.yaml>`_:
.. code-block:: ini
attributes:
metadata:
restrictions:
- "settings:common.libvirt_type.value == 'kvm'"
- "settings:storage.volumes_ceph.value == true"
- "settings:storage.images_ceph.value == true"
- "settings:storage.ephemeral_ceph.value == true"
- "settings:storage.objects_ceph.value == true"
- "settings:additional_components.sahara.value == true"
- "settings:additional_components.murano.value == true"
- "settings:additional_components.ceilometer.value == true"
- "settings:additional_components.mongo.value == true"
- "settings:additional_components.ironic.value == true"
If any of the listed settings are enabled, then the user cannot enable the
plugin. The restrictions are bidirectional, i.e. if you enable the plugin,
you cannot enable any of the listed settings without disabling the plugin
first.
You can use other entry points to the Fuel API besides ``settings`` as
context. Some of the valid contexts are ``networking_parameters``,
``version``, and ``cluster``. Settings restrictions are used extensively
for the core Fuel settings.
To examine them, use the command
:command:`fuel --env 38 settings --default` to download the default settings
from one of the existing environments and look for the substring
``restrictions`` in the resulting file.

View File

@ -0,0 +1,41 @@
.. _task-conditions:
Conditions for plugin tasks
---------------------------
You can restrict plugin tasks from running, depending on whether some specific
settings in the Fuel web UI are enabled or not. The syntax slightly differs
from the one for the settings restriction as in the case of the task you
provide the opposite to the restriction -- a condition that must be true for
the task to run, but the net result is the same -- restricting the task from
running if the condition is not true.
Here is an example.
``deployment_tasks.yaml``:
.. code-block:: ini
- id: upload_cirros
type: shell
role: ['primary-controller']
condition: "settings:swiftstack.upload_cirros_test.value == true"
In this example, the default task ``upload_cirros`` will only run when
a specific setting for it is enabled in the Fuel web UI. The setting
itself can be defined as:
``environment_config.yaml``:
.. code-block:: ini
upload_cirros_test:
weight: 20
type: "checkbox"
value: true
label: "Enable upload test"
description: "Upload cirros base image when the deployment is done"
.. note:: Conditions can only use settings and cluster contexts of the
Fuel API.

View File

@ -0,0 +1,7 @@
.. _existing-plugins:
Overview of existing plugins
============================
* `Fuel plugins on GitHub <https://github.com/search?utf8=%E2%9C%93&q=fuel-plugin+in%3Aname>`_.
* `DriverLog <http://stackalytics.com/report/driverlog?project_id=openstack/fuel>`_.

View File

@ -0,0 +1,6 @@
.. _how-plugins-work:
How plugins work
================
TBD

View File

@ -0,0 +1,27 @@
.. index:: Introduction
.. _plugin-sdk-introduction:
Introduction to the Fuel Plugin SDK Guide
=========================================
The Fuel Plugin SDK Guide provides instructions on how to build, test, and
troubleshoot your plugins; the guide also gives an overview of the existing
plugins.
This guide focuses on Fuel Plugin Builder Version 4 delivered with Fuel 8.0
Maintenance Update 1.
Before you read this document, you must do the following:
#. Install Fuel 8.0. See :ref:`fuel-install-guide`.
#. Update the Fuel Master node to Maintenance Update 1.
See :ref:`upgrade_apply_patches`.
#. Deploy an OpenStack environment with one controller and one compute node.
See :ref:`create-env-ug`.
This guide is a work in progress and will eventually have most of
the information you need on Fuel Plugin SDK. In the meantime, use
the `community Wiki page <https://wiki.openstack.org/wiki/Fuel/Plugins>`_
as a supplementing reference.

View File

@ -0,0 +1,6 @@
.. _plugin-limitations:
Limitations
===========
TBD limitations and bugs

View File

@ -0,0 +1,15 @@
.. _plugin-requirements:
Requirements
============
* Plugin code must be idempotent.
* Do not copy modules from fuel-library. Add the module path
into task description instead and use fuel-library as framework:
``puppet_modules: "puppet/modules:/etc/puppet/modules"``
* If you use plugin pre-deployment scripts that somehow change the state of
the Fuel Master node -- for example, changes to Nailgun database --
ensure that all these changes are removed in the post-deployment script.
* TBD Fuel code style guidelines
* TBD Use puppet-lint and pep8 (+bash?)
* TBD recommendation on pre_build_hook