<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
		<id>https://wiki.openstack.org/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Adidenko</id>
		<title>OpenStack - User contributions [en]</title>
		<link rel="self" type="application/atom+xml" href="https://wiki.openstack.org/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Adidenko"/>
		<link rel="alternate" type="text/html" href="https://wiki.openstack.org/wiki/Special:Contributions/Adidenko"/>
		<updated>2026-07-04T22:35:53Z</updated>
		<subtitle>User contributions</subtitle>
		<generator>MediaWiki 1.28.2</generator>

	<entry>
		<id>https://wiki.openstack.org/w/index.php?title=Fuel/Plugins&amp;diff=104997</id>
		<title>Fuel/Plugins</title>
		<link rel="alternate" type="text/html" href="https://wiki.openstack.org/w/index.php?title=Fuel/Plugins&amp;diff=104997"/>
				<updated>2016-02-22T16:54:52Z</updated>
		
		<summary type="html">&lt;p&gt;Adidenko: /* Configuration of Fuel Plugins with new roles */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== What is Pluggable Architecture ==&lt;br /&gt;
Beginning with 6.0 version, Fuel features the ability to install plugins along with your environment. Fuel plugins are downloadable software components that enable you to add new capabilities to your environments in a flexible, repeatable and reliable manner. There is no need to install drivers and patches manually after Fuel deploys your cloud – plugins do this for you.&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Fuel plugins enable you to install and configure additional capabilities for your cloud, such as additional storage types and networking functionality. For example, a Load Balancing as a Service (LBaaS) plugin allows you to add network load balancing functionality to your cloud so that incoming traffic can be spread across multiple nodes. Or you might want to use the GlusterFS plugin so that you can use a Gluster file system as a backend for block storage (Cinder).&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Fuel offers an open source framework for creating these plugins, so there’s a wide range of capabilities that you can enable Fuel to add to your OpenStack clouds. If you’re a hardware vendor that has created drivers that enable OpenStack to work with your product, you can create a plugin so Fuel can deploy those drivers when it’s standing up new clouds. Or you might simply want to enable OpenStack functionality that’s not readily available in Fuel. Because Fuel includes a pluggable framework, you’re not limited to what’s provided “out of the box”.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You are also free to use [[DriverLog#How_To:_Add_a_new_Fuel_Plugin_to_DriverLog|DriverLog]] as the single registry for all Fuel Plugins.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Architecture limitations''' &amp;lt;br/&amp;gt;&lt;br /&gt;
* Core-functionality Fuel plugins can only be installed before configuring and deploying the environment. Otherwise, you will have to redeploy the environment to enable the core plugin. Apllication level plugins can be installed later on top of already deployed environments.&lt;br /&gt;
* Fuel plugins cannot be upgraded from major to another major version.&lt;br /&gt;
* Fuel plugins for SDN solutions cannot create a new networking option in the Fuel web UI/UI wizard.&lt;br /&gt;
&lt;br /&gt;
=== 6.1 features ===&lt;br /&gt;
&lt;br /&gt;
* plugins are shipped in RPMs&lt;br /&gt;
* plugins support updates from major to minor version (1.0.0 to 1.0.1)&lt;br /&gt;
&lt;br /&gt;
=== 7.0 features ===&lt;br /&gt;
&lt;br /&gt;
* [https://blueprints.launchpad.net/fuel/+spec/role-as-a-plugin define a new role in Fuel via a plugin] see [[Fuel/Plugins#Configuration_of_Fuel_Plugins_with_new_roles|Configuration of Fuel Plugins with new roles]].&lt;br /&gt;
* [https://blueprints.launchpad.net/fuel/+spec/vip-reservation reserve VIPs via Fuel plugin's metadata], see [https://wiki.openstack.org/wiki/Fuel/Plugins#Virtual_IP_reservation_via_Fuel_Plugin.27s_metadata| Virtual IP reservation via Fuel plugins's metadata].&lt;br /&gt;
* [https://blueprints.launchpad.net/fuel/+spec/ui-plugins-list view installed plugins]&lt;br /&gt;
* [https://wiki.openstack.org/wiki/Fuel/Plugins#How_to_separate_services_from_Controller_with_a_plugin separate services from Controller with a plugin]&lt;br /&gt;
&lt;br /&gt;
=== 8.0 features ===&lt;br /&gt;
&lt;br /&gt;
* [https://blueprints.launchpad.net/fuel/+spec/plugin-after-deployment install a plugin after deployment]&lt;br /&gt;
* [https://blueprints.launchpad.net/fuel/+spec/external-dashboard-links-in-fuel-dashboard plugin links and metadata in environment dashboard]&lt;br /&gt;
* [https://blueprints.launchpad.net/fuel/+spec/component-registry component registry]&lt;br /&gt;
* [https://blueprints.launchpad.net/fuel/+spec/segment-settings-tab-logically settings tab plugin assignment]&lt;br /&gt;
&lt;br /&gt;
====Plugin links and metadata in environment dashboard====&lt;br /&gt;
&lt;br /&gt;
You can make an API request via your Puppet manifests and register a non-standard dashboard.&lt;br /&gt;
&lt;br /&gt;
'''Examples'''&lt;br /&gt;
&lt;br /&gt;
* absolute-dashboard-link.pp:&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;&lt;br /&gt;
notice('PLUGIN: fuel_plugin_example_v4/absolute-dashboard-link.pp')&lt;br /&gt;
&lt;br /&gt;
$cluster_id = hiera('deployment_id')&lt;br /&gt;
$master_ip = hiera('master_ip')&lt;br /&gt;
$network_metadata = hiera_hash('network_metadata', {})&lt;br /&gt;
$os_public_vip = $network_metadata['vips']['public']['ipaddr']&lt;br /&gt;
&lt;br /&gt;
$dashboard_name = 'Demo Plugin Dashboard #1'&lt;br /&gt;
$dashboard_desc = 'A Sample Absolute Dashboard Link'&lt;br /&gt;
$dashboard_link = &amp;quot;http://${os_public_vip}/dashboard&amp;quot;&lt;br /&gt;
&lt;br /&gt;
$json_hash = { title       =&amp;gt; $dashboard_name,&lt;br /&gt;
               description =&amp;gt; $dashboard_desc,&lt;br /&gt;
               url         =&amp;gt; $dashboard_link, }&lt;br /&gt;
&lt;br /&gt;
$json_message = inline_template('&amp;lt;%= require &amp;quot;json&amp;quot;; JSON.dump(@json_hash) %&amp;gt;')&lt;br /&gt;
&lt;br /&gt;
exec { 'create_dashboard_link':&lt;br /&gt;
  command =&amp;gt; &amp;quot;/usr/bin/curl -H 'Content-Type: application/json' -X POST \&lt;br /&gt;
-d '${json_message}' \&lt;br /&gt;
http://${master_ip}:8000/api/clusters/${cluster_id}/plugin_links&amp;quot;,&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* relative-dashboard-link.pp:&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;&lt;br /&gt;
notice('PLUGIN: fuel_plugin_example_v4/relative-dashboard-link.pp')&lt;br /&gt;
&lt;br /&gt;
$cluster_id = hiera('deployment_id')&lt;br /&gt;
$master_ip = hiera('master_ip')&lt;br /&gt;
&lt;br /&gt;
$dashboard_name = 'Demo Plugin Dashboard #2'&lt;br /&gt;
$dashboard_desc = 'A Sample Relative Dashboard Link'&lt;br /&gt;
$dashboard_link = &amp;quot;/dashboard&amp;quot;&lt;br /&gt;
&lt;br /&gt;
$json_hash = { title       =&amp;gt; $dashboard_name,&lt;br /&gt;
               description =&amp;gt; $dashboard_desc,&lt;br /&gt;
               url         =&amp;gt; $dashboard_link, }&lt;br /&gt;
&lt;br /&gt;
$json_message = inline_template('&amp;lt;%= require &amp;quot;json&amp;quot;; JSON.dump(@json_hash) %&amp;gt;')&lt;br /&gt;
&lt;br /&gt;
exec { 'create_dashboard_link':&lt;br /&gt;
  command =&amp;gt; &amp;quot;/usr/bin/curl -H 'Content-Type: application/json' -X POST \&lt;br /&gt;
-d '${json_message}' \&lt;br /&gt;
http://${master_ip}:8000/api/clusters/${cluster_id}/plugin_links&amp;quot;,&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* deployment_tasks.yaml:&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;&lt;br /&gt;
- id: fuel_plugin_example_v4&lt;br /&gt;
  type: group&lt;br /&gt;
  role: [fuel_plugin_example_v4]&lt;br /&gt;
  tasks:&lt;br /&gt;
    - hiera&lt;br /&gt;
    - globals&lt;br /&gt;
  required_for: [deploy_end]&lt;br /&gt;
  requires: [deploy_start]&lt;br /&gt;
  parameters:&lt;br /&gt;
    strategy:&lt;br /&gt;
      type: parallel&lt;br /&gt;
&lt;br /&gt;
- id: fuel_plugin_example_v4-controller-deployment&lt;br /&gt;
  type: puppet&lt;br /&gt;
  groups: [primary-controller, controller]&lt;br /&gt;
  required_for: [connectivity_tests, deploy_end]&lt;br /&gt;
  requires: [netconfig, deploy_start]&lt;br /&gt;
  parameters:&lt;br /&gt;
    puppet_manifest: &amp;quot;deploy.pp&amp;quot;&lt;br /&gt;
    puppet_modules: &amp;quot;.&amp;quot;&lt;br /&gt;
    timeout: 3600&lt;br /&gt;
&lt;br /&gt;
- id: fuel_plugin_example_v4-deployment&lt;br /&gt;
  type: puppet&lt;br /&gt;
  groups: [fuel_plugin_example_v4]&lt;br /&gt;
  required_for: [deploy_end]&lt;br /&gt;
  requires: [deploy_start]&lt;br /&gt;
  parameters:&lt;br /&gt;
    puppet_manifest: &amp;quot;deploy.pp&amp;quot;&lt;br /&gt;
    puppet_modules: &amp;quot;.&amp;quot;&lt;br /&gt;
    timeout: 3600&lt;br /&gt;
    retries: 10&lt;br /&gt;
&lt;br /&gt;
- id: fuel_plugin_example_v4-post-deployment-sh&lt;br /&gt;
  type: shell&lt;br /&gt;
  role: [fuel_plugin_example_v4]&lt;br /&gt;
  required_for: [post_deployment_end]&lt;br /&gt;
  requires: [post_deployment_start]&lt;br /&gt;
  parameters:&lt;br /&gt;
    cmd: bash deploy.sh&lt;br /&gt;
    retries: 3&lt;br /&gt;
    interval: 20&lt;br /&gt;
    timeout: 180&lt;br /&gt;
&lt;br /&gt;
- id: fuel_plugin_example_v4-absolute-dashboard-link&lt;br /&gt;
  type: puppet&lt;br /&gt;
  role: [fuel_plugin_example_v4]&lt;br /&gt;
  required_for: [post_deployment_end]&lt;br /&gt;
  requires: [post_deployment_start]&lt;br /&gt;
  parameters:&lt;br /&gt;
    puppet_manifest: &amp;quot;absolute-dashboard-link.pp&amp;quot;&lt;br /&gt;
    puppet_modules: &amp;quot;/etc/puppet/modules&amp;quot;&lt;br /&gt;
    timeout: 180&lt;br /&gt;
&lt;br /&gt;
- id: fuel_plugin_example_v4-relative-dashboard-link&lt;br /&gt;
  type: puppet&lt;br /&gt;
  role: [fuel_plugin_example_v4]&lt;br /&gt;
  required_for: [post_deployment_end]&lt;br /&gt;
  requires: [post_deployment_start]&lt;br /&gt;
  parameters:&lt;br /&gt;
    puppet_manifest: &amp;quot;relative-dashboard-link.pp&amp;quot;&lt;br /&gt;
    puppet_modules: &amp;quot;/etc/puppet/modules&amp;quot;&lt;br /&gt;
    timeout: 180cluster_id}/plugin_links&amp;quot;,&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* node_roles.yaml:&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;&lt;br /&gt;
fuel_plugin_example_v4:&lt;br /&gt;
  name: &amp;quot;Set here the name for the role. This name will be displayed in the Fuel web UI.&amp;quot;&lt;br /&gt;
  description: &amp;quot;Write description for your role&amp;quot;&lt;br /&gt;
  has_primary: false                # whether has primary role or not&lt;br /&gt;
  public_ip_required: true          # whether requires public net or not&lt;br /&gt;
  weight: 100                       # weight that will be used for ordering on fuel ui&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Example of a plugin API added to a post-install task — post_install.sh:&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;&lt;br /&gt;
#!/bin/sh&lt;br /&gt;
&lt;br /&gt;
PLUGIN_NAME=fuel_plugin_example_v4&lt;br /&gt;
DASHBOARD_TITLE=Dashboard&lt;br /&gt;
DASHBOARD_DESC=&amp;quot;A Sample Dashboard Link&amp;quot;&lt;br /&gt;
DASHBOARD_URL=&amp;quot;/dashboard&amp;quot;&lt;br /&gt;
&lt;br /&gt;
function obtain_token {&lt;br /&gt;
&lt;br /&gt;
# Request a token for admin user&lt;br /&gt;
TENANT_NAME=admin&lt;br /&gt;
ADMIN_USERNAME=`python -c &amp;quot;import sys; import yaml; f = open('/etc/fuel/astute.yaml'); astute = yaml.load(f); print astute['FUEL_ACCESS']['user'];&amp;quot;`&lt;br /&gt;
ADMIN_PASSWORD=`python -c &amp;quot;import sys; import yaml; f = open('/etc/fuel/astute.yaml'); astute = yaml.load(f); print astute['FUEL_ACCESS']['password'];&amp;quot;`&lt;br /&gt;
TENANT_ID=admin&lt;br /&gt;
&lt;br /&gt;
REQUEST=&amp;quot;{\&amp;quot;auth\&amp;quot;: {\&amp;quot;tenantName\&amp;quot;:\&amp;quot;$TENANT_NAME\&amp;quot;, \&amp;quot;passwordCredentials\&amp;quot;: {\&amp;quot;username\&amp;quot;: \&amp;quot;$ADMIN_USERNAME\&amp;quot;, \&amp;quot;password\&amp;quot;: \&amp;quot;$ADMIN_PASSWORD\&amp;quot;}}}&amp;quot;&lt;br /&gt;
RAW_TOKEN=`curl -s -d &amp;quot;$REQUEST&amp;quot; -H &amp;quot;Content-type: application/json&amp;quot; &amp;quot;http://localhost:5000/v2.0/tokens&amp;quot;`&lt;br /&gt;
TOKEN=`echo $RAW_TOKEN | python -c &amp;quot;import sys; import json; response = json.loads(sys.stdin.read()); print response['access']['token']['id'];&amp;quot;`&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function plugin_link {&lt;br /&gt;
&lt;br /&gt;
which fuel &amp;gt; /dev/null&lt;br /&gt;
if [[ $? -eq 0 ]]; then&lt;br /&gt;
&lt;br /&gt;
local num_retries=10&lt;br /&gt;
local i=0&lt;br /&gt;
&lt;br /&gt;
while true; do&lt;br /&gt;
    # Fail if number of retries exeeded&lt;br /&gt;
    if [[ $i -gt $((num_retries + 1)) ]]; then&lt;br /&gt;
        # Report that plugin not registered&lt;br /&gt;
        echo &amp;quot;WARNING: Plugin failed to register before the timeout.&amp;quot;&lt;br /&gt;
        echo &amp;quot;         Plugin dashboard link will not be added.&amp;quot;&lt;br /&gt;
        return 1&lt;br /&gt;
    fi&lt;br /&gt;
&lt;br /&gt;
    LAST_PLUGIN_ID=`fuel plugins -l | grep $PLUGIN_NAME | cut -d ' ' -f1`&lt;br /&gt;
    if [ &amp;quot;$LAST_PLUGIN_ID&amp;quot; != &amp;quot;&amp;quot; ]; then&lt;br /&gt;
        PLUGIN_ID=$LAST_PLUGIN_ID&lt;br /&gt;
        echo &amp;quot;Plugin ID is: $PLUGIN_ID&amp;quot;&lt;br /&gt;
        curl -H 'Content-Type: application/json' -H &amp;quot;X-Auth-Token: $TOKEN&amp;quot; -X POST -d \&lt;br /&gt;
&amp;quot;{\&amp;quot;title\&amp;quot;:\&amp;quot;$DASHBOARD_TITLE\&amp;quot;,\&amp;quot;description\&amp;quot;:\&amp;quot;$DASHBOARD_DESC\&amp;quot;,\&amp;quot;url\&amp;quot;:\&amp;quot;$DASHBOARD_URL\&amp;quot;}&amp;quot; \&lt;br /&gt;
http://127.0.0.1:8000/api/v1/plugins/$PLUGIN_ID/links&lt;br /&gt;
        return 0&lt;br /&gt;
    fi&lt;br /&gt;
&lt;br /&gt;
    sleep 1&lt;br /&gt;
    i=$((i++))&lt;br /&gt;
done&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
obtain_token&lt;br /&gt;
echo $TOKEN&lt;br /&gt;
&lt;br /&gt;
plugin_link &amp;amp;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
====Component compatibility registry====&lt;br /&gt;
&lt;br /&gt;
Component registry is a component compatibility mechanism in Fuel. See [https://specs.openstack.org/openstack/fuel-specs/specs/8.0/component-registry.html blueprint].&lt;br /&gt;
&lt;br /&gt;
'''Specifying component requirements'''&lt;br /&gt;
&lt;br /&gt;
Consider two components: Component A and Component B.&lt;br /&gt;
Component A requires Component B to function.&lt;br /&gt;
&lt;br /&gt;
In a DSL model this relation can be described explicitly:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;&lt;br /&gt;
        - name: 'A'&lt;br /&gt;
            requires:&lt;br /&gt;
                - name: 'B'&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The DSL model can be described in the Fuel openstack.yaml file for core components and in the components.yaml file for components provided from a plugin.&lt;br /&gt;
&lt;br /&gt;
In the Fuel web UI, if Component B is not selected, then Component A will be disabled and respective message displayed.&lt;br /&gt;
&lt;br /&gt;
Consider three components: Component A, Component B, and Component C.&lt;br /&gt;
Component A requires Component B and Component B to function.&lt;br /&gt;
&lt;br /&gt;
This relation can be described explicitly:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;&lt;br /&gt;
        - name: 'A'&lt;br /&gt;
            requires:&lt;br /&gt;
                - name: 'B'&lt;br /&gt;
                - name: 'C'&lt;br /&gt;
                message: 'C and B'&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this case Component A can be selected only when both Component B and Component C are selected.&lt;br /&gt;
&lt;br /&gt;
There is currently a limitation for cases when Component A requires Component B or Component C or more.&lt;br /&gt;
&lt;br /&gt;
Example of requirements for the DVS plugin:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;&lt;br /&gt;
        - name: 'network:neutron:ml2:dvs'&lt;br /&gt;
          label: 'Neutron with VMware DVS'&lt;br /&gt;
          description: 'Neutron with VMware DVS ML2 plugin'&lt;br /&gt;
          requires:&lt;br /&gt;
            - name: 'network:neutron:core:ml2'&lt;br /&gt;
            - name: 'hypervisor:vmware'&lt;br /&gt;
            message: 'The VMware DVS plugin requires vCenter as the hypervisor option.'&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Specifying component compatibility'''&lt;br /&gt;
&lt;br /&gt;
Compatibility of Component A with Components B means that Component A has been tested and proved to function with Component B.&lt;br /&gt;
&lt;br /&gt;
DSL model example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;&lt;br /&gt;
        - name: 'A'&lt;br /&gt;
            compatible:&lt;br /&gt;
                - name: 'B'&lt;br /&gt;
                - name: 'C'&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If either Component B or Component B is selected in the Fuel web UI, then the UI representation of Component A will have a green tooltip.&lt;br /&gt;
&lt;br /&gt;
'''Specifying component incompatibility'''&lt;br /&gt;
&lt;br /&gt;
Incompatibility of Component A with Component B means that Component A has been tested and proved to not function with Component B.&lt;br /&gt;
&lt;br /&gt;
DSL model example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;&lt;br /&gt;
        - name: 'A'&lt;br /&gt;
            incompatible:&lt;br /&gt;
                - name: 'B'&lt;br /&gt;
                message: 'B incompatible with A'&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Selecting Component A or Component B will disable the other one in the Fuel web UI. You will be able to select only Component A or Component B, but not both.&lt;br /&gt;
&lt;br /&gt;
'''Components with unspecified compatibility'''&lt;br /&gt;
&lt;br /&gt;
The Fuel web UI shows a grey tooltip with a respective message for the components with unspecified compatibility.&lt;br /&gt;
&lt;br /&gt;
====Settings tab plugins assignment====&lt;br /&gt;
&lt;br /&gt;
There is a `groups` attribute in the ''environment_config.yaml'' file that you can use to assign your plugins to.&lt;br /&gt;
&lt;br /&gt;
Plugins can form any group in one of the default groups: General, Security, Compute, Storage, Logging, OpenStack Services.&lt;br /&gt;
If your plugin uses a custom group name it will automatically go to the `Other` group.&lt;br /&gt;
&lt;br /&gt;
See [https://github.com/openstack/fuel-plugins/blob/master/fuel_plugin_builder/templates/v4/plugin_data/environment_config.yaml.mako#L2-L5 environment_config.yaml template].&lt;br /&gt;
&lt;br /&gt;
== How to develop a plugin for Fuel ==&lt;br /&gt;
&lt;br /&gt;
=== Planning to create a plugin for Fuel===&lt;br /&gt;
&lt;br /&gt;
==== Entry development requirements ====&lt;br /&gt;
&lt;br /&gt;
When planning to write up a plugin for Fuel, mind the following recommendations:&lt;br /&gt;
&lt;br /&gt;
* Provide deb and rpm packages together with their dependencies.  For instructions on creating packages, see [https://www.google.com/url?q=https%3A%2F%2Ffedoraproject.org%2Fwiki%2FHow_to_create_an_RPM_package&amp;amp;sa=D&amp;amp;sntz=1&amp;amp;usg=AFQjCNGKbtd1Lk5xHa3voWMPBjnbspqOrg Fedora project] wiki and [http://packaging.ubuntu.com/html/ Ubuntu Packaging Guide].&lt;br /&gt;
* Create puppet manifests according to the Official OpenStack documentation. For nice code examples and workflow, see [[Puppet-openstack|Puppet in OpenStack]].&lt;br /&gt;
&lt;br /&gt;
==== Repo ====&lt;br /&gt;
&lt;br /&gt;
It is recommended that you create a repo for your plugin in /openstack namespace.&lt;br /&gt;
&lt;br /&gt;
'''NOTE:'''&lt;br /&gt;
Previously (before September 2015), plugin repos were created in Stackforge namespace. Due to it retirement, all plugin projects are now registered&lt;br /&gt;
under /openstack.&lt;br /&gt;
&lt;br /&gt;
Your plugin project should look like ''https://github.com/openstack/fuel-plugin-&amp;lt;your_plugin_name&amp;gt;.''&lt;br /&gt;
&lt;br /&gt;
====== How to create a project ======&lt;br /&gt;
&lt;br /&gt;
#  Make sure you're registered at the following resources:&lt;br /&gt;
#* LaunchPad. If not, see [http://docs.openstack.org/infra/manual/developers.html the official OpenStack documentation].&lt;br /&gt;
#* review.openstack.org. It is required for developers to be included into core and release groups.&lt;br /&gt;
# Request the repo creation in Fuel project. Enter [https://launchpad.net/fuel Fuel project at Launchpad] and click '''Report a bug''' link.  [[File:report-a-bug.png]]&lt;br /&gt;
# In '''Summary''', specify ''Create a Fuel Plugin project in /Openstack''.    [[File:bug-report-sum.png]]&lt;br /&gt;
# Bug description should consist of:&lt;br /&gt;
#*  Plugin name (for example, HA Fencing)&lt;br /&gt;
#*  Plugin functionality overview (for example, enables STONITH-based fencing in HA mode)&lt;br /&gt;
#*  Developer's contact information (email, skype, etc.) - please make sure core group members are registered at review.openstack.org. Otherwise they wont be added as a core members.&lt;br /&gt;
#*  List of developers with contact information (name, email on which review.openstack.org is registered) to enter core reviewers group ([https://review.openstack.org/#/admin/groups/691,members example])- used to merge changes&lt;br /&gt;
#*  List of developers with contact information ( (name, email on which review.openstack.org is registered)) to enter release group ([https://review.openstack.org/#/admin/groups/692,members example]) - used to create release branches and tags in the repo.    You will need to review the commit for your project and make sure both lists of developers to enter core and release groups are correct.&lt;br /&gt;
# Click '''Extra''' options. In the menu, specify ''devops'' tag.    [[File:bug-report-devops.png|200px]]&lt;br /&gt;
#  After the repo is created (that means, your bug should be marked as ''Fix Committed'' or ''Fix Released'') you can start filling your repo with the required files:&lt;br /&gt;
#* Plugin code itself&lt;br /&gt;
#* Documentation - see [[Fuel/Plugins#Creating_documentation_for_Fuel_Plugins|the corresponding section]] for more details.&lt;br /&gt;
&lt;br /&gt;
====== Requesting community help for code review ======&lt;br /&gt;
&lt;br /&gt;
Once your code is being prepared  and uploaded into repo under ''/openstack'' project, you&lt;br /&gt;
are free to request the OpenStack community for review to make sure the code meets the development requirements&lt;br /&gt;
and common guidelines for Fuel Plugin Framework as listed below. &amp;lt;br&amp;gt;&lt;br /&gt;
This is aligned with the [http://docs.openstack.org/infra/manual/developers.html Gerrit workflow] used in the OpenStack community.&lt;br /&gt;
To request review, you can enter '''#fuel-dev''' channel in IRC.&lt;br /&gt;
&lt;br /&gt;
==== Working with tags and branches  ====&lt;br /&gt;
&lt;br /&gt;
To track the release cycle in a more efficient manner, you can use:&lt;br /&gt;
* release branches&lt;br /&gt;
* tags&lt;br /&gt;
&lt;br /&gt;
Here is the difference between these 2 concepts:&lt;br /&gt;
* A tag represents a version of a particular branch at a moment in time.&lt;br /&gt;
* A branch represents a separate thread of development that may run concurrently with other development efforts on the same code base. Changes to a branch may eventually be merged back into another branch to unify them.&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
It is recommended that you used branches to let end users build a your plugin themselves.&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
For this, you need to:&lt;br /&gt;
* create a corresponding branch.&lt;br /&gt;
* edit README file to provide build instructions. For more details, see [[Fuel/Plugins#Creating_documentation_for_Fuel_Plugins|the corresponding section]].&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also use tags for tracking progress within one branch.&lt;br /&gt;
Here are 2 examples:&lt;br /&gt;
* tagging the plugin repo - [https://github.com/stackforge/fuel-plugin-neutron-vpnaas VPNaaS plugin] repo:&lt;br /&gt;
  [[File:repo-tags-1.png]]&lt;br /&gt;
* creating a separate branch - [https://github.com/stackforge/fuel-plugin-neutron-lbaas LBaaS plugin] repo:&lt;br /&gt;
   [[File:Plugin-branch.png]]&lt;br /&gt;
&lt;br /&gt;
==== Branches naming convention ====&lt;br /&gt;
&lt;br /&gt;
Since plugins are published in [[Fuel/Plugins#Add_your_plugin_to_DriverLog|DriverLog]], the only way for end users to get the plugin RPM is to build it themselves.&lt;br /&gt;
'''Thus, you should take the following into consideration:'''&lt;br /&gt;
* the branch name should coincide with the compatible Fuel version.&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
'''SEE ALSO'''&lt;br /&gt;
* To learn more about best practices in creating branches, see [http://nvie.com/posts/a-successful-git-branching-model A successful Git branching model]&lt;br /&gt;
blogpost.&lt;br /&gt;
* For instructions on creating a tag, see the official [http://docs.openstack.org/infra/manual/drivers.html#tagging-a-release Project Driver's Guide].&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
'''NOTE:'''&lt;br /&gt;
* You should add a tag once you get all the required files added into the repo and checked&lt;br /&gt;
if they contain copyrights. Otherwise, you will have to create new tags.&lt;br /&gt;
* You should create tags with gpg key using console gnupg. '''Please, ensure it is present and not expired.'''&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Creating branches ====&lt;br /&gt;
&lt;br /&gt;
There are 2 ways of creating branches:&lt;br /&gt;
* from CLI:&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;&lt;br /&gt;
git push &amp;lt;remote&amp;gt; &amp;lt;localref&amp;gt;:&amp;lt;remotebranch&amp;gt;&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where &amp;lt;remote&amp;gt; is the name of your gerrit remote or the full remote url, &amp;lt;localref&amp;gt;&lt;br /&gt;
is the refname (could be a branch or something else) and &amp;lt;remotebranch&amp;gt; is the name of the branch you want created from it.&lt;br /&gt;
&lt;br /&gt;
* from the web UI:&lt;br /&gt;
*# Make sure you are the core reviewer.&lt;br /&gt;
*# Enter review.openstack.org.&lt;br /&gt;
*# in Project menu, click Branches. After the project setup opens, enter a new branch name and click Create branch button. Note, that 'Initial revision' field can be left blank.&lt;br /&gt;
[[File:Plugin-create-branch-1.png]].&lt;br /&gt;
&lt;br /&gt;
===== Deleting branches =====&lt;br /&gt;
&lt;br /&gt;
If you would like to delete a branch, you have 2 different ways to do that:&lt;br /&gt;
# Contact openstack-infra core team via mailing list. See the [http://lists.openstack.org/pipermail/openstack-infra/2015-July/002921.html example request] here.&lt;br /&gt;
# Report a bug in Fuel project in Launchpad and assign it to Fuel DevOps team. The flow is similar to the one described [[Fuel/Plugins#How_to_create_a_project|here]]&lt;br /&gt;
# Request in  #openstack-infra IRC channel on freenode.net. You can contact the following core members there: fungi, clarkb, jeblair, pleia2.&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
Note, that there is no way to delete a branch manually.&lt;br /&gt;
&lt;br /&gt;
==== CI ====&lt;br /&gt;
&lt;br /&gt;
It's recommended to set up CI for your Fuel plugin. The section below provides summary instructions on CI components and their roles.&lt;br /&gt;
&lt;br /&gt;
===== Tools =====&lt;br /&gt;
&lt;br /&gt;
Here is the list of key issues, used in terms of Fuel Plugins CI:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| CI || [http://en.wikipedia.org/wiki/Continuous_integration Continuous Integration]&lt;br /&gt;
|-&lt;br /&gt;
| CD || [http://en.wikipedia.org/wiki/Continuous_delivery Continuous Delivery]&lt;br /&gt;
|-&lt;br /&gt;
| OSTF || [http://docs.mirantis.com/fuel-dev/develop/ostf_contributors_guide.html OpenStack Testing Framework]&lt;br /&gt;
|-&lt;br /&gt;
| BVT ||  Build Verification Tests&lt;br /&gt;
|-&lt;br /&gt;
| JJB || [http://ci.openstack.org/jenkins-job-builder/ Jenkins Job Builder]&lt;br /&gt;
|-&lt;br /&gt;
| VM || virtual machine&lt;br /&gt;
|-&lt;br /&gt;
| Fuel || [[Fuel]]&lt;br /&gt;
|-&lt;br /&gt;
| Fuel CI || [https://ci.fuel-infra.org/ Fuel CI]&lt;br /&gt;
|-&lt;br /&gt;
| GitHub || [https://github.com GitHub Server]&lt;br /&gt;
|-&lt;br /&gt;
| Openstack || [https://github.com/openstack Openstack]&lt;br /&gt;
|-&lt;br /&gt;
| Gerrit || [http://docs.openstack.org/infra/manual/developers.html OpenStack review tool]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Easy way to build own CI https://github.com/openstack/fuel-plugin-ci&lt;br /&gt;
&lt;br /&gt;
As to the tools, the following ones are used:&lt;br /&gt;
&lt;br /&gt;
* GitHub repository with Gerrit code-review tool&lt;br /&gt;
* Jenkins CI-server  - provides full information about jobs status, scheduler, test results, etc.&lt;br /&gt;
* Jenkins Job Builder - tool for easy adding and managing Jenkins jobs. It provides functionality to store jobs’ configuration in a human-readable .yaml markup language and convert them to Jenkins-specific .xml.&lt;br /&gt;
&lt;br /&gt;
===== Steps to configure Gerrit integration =====&lt;br /&gt;
# [http://docs.openstack.org/infra/system-config/third_party.html Create and configure] launchpad user for voting as third-party developer&lt;br /&gt;
# Add credentials (username, public key) for gerrit plugin configuration in Jenkins&lt;br /&gt;
# Send an email to the '''openstack-dev''' mailing list nominating your system for voting permissions&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===== Steps to prepare development &amp;amp; testing environments (mandatory) =====&lt;br /&gt;
# OpenStack and/or Gerrit repository should be created. See [[#Repo|Repo]] section for more details.&lt;br /&gt;
# Preferable quantity of test labs should be allocated (plugin-specific).&lt;br /&gt;
# Specific Hardware resources should be installed and configured (plugin-specific).&lt;br /&gt;
# Test labs should be configured for setup environments and test running. See [https://docs.mirantis.com/fuel-dev/devops.html Fuel development documentation]&lt;br /&gt;
&lt;br /&gt;
===== Steps to configure CI server (optional) =====&lt;br /&gt;
# We recommend for all plugin developers to have their own CI server. It provides better versioning, collecting test-results, deduplicating the same jobs, easier configuration and managing.&lt;br /&gt;
# We recommend using Jenkins with [http://ci.openstack.org/jenkins-job-builder/ Jenkins Job Builder plugin] which provides easy jobs management and their configuration storage.&lt;br /&gt;
# We recommend to install JJB from git and take example jobs from [[Fuel/Plugins#Example_jobs|the section below]].You may find the main job helpful: this should be plugins.yaml and dependent builders: docs/builders/.sh.&lt;br /&gt;
# We recommend creating a pre-commit-hook to check your code:&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# Save this script to &amp;lt;PROJECT&amp;gt;/.git/hooks/pre-review and make it executable&lt;br /&gt;
set -e&lt;br /&gt;
set -o pipefail&lt;br /&gt;
&lt;br /&gt;
find . -name '*.pp' | xargs -P1 -L1 puppet parser validate --verbose&lt;br /&gt;
find . -name '*.pp' | xargs -P1 -L1 puppet-lint \&lt;br /&gt;
          --fail-on-warnings \&lt;br /&gt;
          --with-context \&lt;br /&gt;
          --with-filename \&lt;br /&gt;
          --no-80chars-check \&lt;br /&gt;
          --no-variable_scope-check \&lt;br /&gt;
          --no-nested_classes_or_defines-check \&lt;br /&gt;
          --no-autoloader_layout-check \&lt;br /&gt;
          --no-class_inherits_from_params_class-check \&lt;br /&gt;
          --no-documentation-check \&lt;br /&gt;
          --no-arrow_alignment-check\&lt;br /&gt;
          --no-case_without_default-check&lt;br /&gt;
find . -name '*.erb' | xargs -P1 -L1 -I '%' erb -P -x -T '-' % | ruby -c&lt;br /&gt;
fpb --check  ./&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Example jobs =====&lt;br /&gt;
&lt;br /&gt;
* deploy-plugin.sh:&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
set -ex&lt;br /&gt;
&lt;br /&gt;
export SYSTEM_TESTS=&amp;quot;${WORKSPACE}/utils/jenkins/system_tests.sh&amp;quot;&lt;br /&gt;
export LOGS_DIR=${WORKSPACE}/logs/${BUILD_NUMBER}&lt;br /&gt;
export VENV_PATH='/home/jenkins/venv-nailgun-tests-2.9'&lt;br /&gt;
YOUR_PLUGIN_PATH=&amp;quot;$(ls ./*rpm)&amp;quot; #Change this to appropriate fuel-qa variable for your plugin&lt;br /&gt;
export YOUR_PLUGIN_PATH         #&lt;br /&gt;
&lt;br /&gt;
sh -x &amp;quot;${SYSTEM_TESTS}&amp;quot; -w &amp;quot;${WORKSPACE}&amp;quot; -V &amp;quot;${VENV_PATH}&amp;quot; -i &amp;quot;${ISO_PATH}&amp;quot; -t test -o --group=&amp;quot;${TEST_GROUP}&amp;quot;&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* prepare_env.sh:&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
&lt;br /&gt;
set -ex&lt;br /&gt;
&lt;br /&gt;
export VENV_PATH=&amp;quot;/home/jenkins/venv-nailgun-tests-2.9&amp;quot;&lt;br /&gt;
&lt;br /&gt;
rm -rf &amp;quot;${VENV_PATH}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
REQS_PATH=&amp;quot;${WORKSPACE}/fuel-qa/fuelweb_test/requirements.txt&amp;quot;&lt;br /&gt;
&lt;br /&gt;
virtualenv --system-site-packages &amp;quot;${VENV_PATH}&amp;quot;&lt;br /&gt;
source &amp;quot;${VENV_PATH}/bin/activate&amp;quot;&lt;br /&gt;
pip install -r &amp;quot;${REQS_PATH}&amp;quot; --upgrade&lt;br /&gt;
django-admin.py syncdb --settings=devops.settings --noinput&lt;br /&gt;
django-admin.py migrate devops --settings=devops.settings --noinput&lt;br /&gt;
deactivate&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* syntax-build-plugin.sh&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
set -ex&lt;br /&gt;
&lt;br /&gt;
find . -name '*.erb' -print 0 | xargs -0 -P1 -I '%' erb -P -x -T '-' % | ruby -c&lt;br /&gt;
find . -name '*.pp' -print 0| xargs -0 -P1 puppet parser validate --verbose&lt;br /&gt;
find . -name '*.pp' -print 0| xargs -0 -P1 puppet-lint \&lt;br /&gt;
          --fail-on-warnings \&lt;br /&gt;
          --with-context \&lt;br /&gt;
          --with-filename \&lt;br /&gt;
          --no-80chars-check \&lt;br /&gt;
          --no-variable_scope-check \&lt;br /&gt;
          --no-nested_classes_or_defines-check \&lt;br /&gt;
          --no-autoloader_layout-check \&lt;br /&gt;
          --no-class_inherits_from_params_class-check \&lt;br /&gt;
          --no-documentation-check \&lt;br /&gt;
          --no-arrow_alignment-check&lt;br /&gt;
&lt;br /&gt;
fpb --check  ./&lt;br /&gt;
fpb --build  ./&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* plugins.yaml:&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;&lt;br /&gt;
- project:&lt;br /&gt;
    name: plugin_name #Your plugin mame&lt;br /&gt;
    path_to_fuel_iso: $PWD #Path to FuelISO&lt;br /&gt;
    plugin_repo: plugin_repo #Your plugin repo name at stackforge&lt;br /&gt;
    email_to: emails_list #List of emails separated by comma&lt;br /&gt;
    test_group: test_group #Test group in fuel-qa for deployment tests of your plugin&lt;br /&gt;
    jobs:&lt;br /&gt;
      - 'prepare_env'&lt;br /&gt;
      - '{name}.build'&lt;br /&gt;
      - '{name}.{dist}.deploy':&lt;br /&gt;
          dist: 'centos'&lt;br /&gt;
      - '{name}.{dist}.deploy':&lt;br /&gt;
          dist: 'ubuntu'&lt;br /&gt;
&lt;br /&gt;
- job-template:&lt;br /&gt;
    name: 'prepare_env'&lt;br /&gt;
    builders:&lt;br /&gt;
      - shell:&lt;br /&gt;
          !include-raw-escape './builders/prepare_env.sh'&lt;br /&gt;
    description: 'Prepare environment to testing'&lt;br /&gt;
    logrotate:&lt;br /&gt;
      numToKeep: 10&lt;br /&gt;
    parameters:&lt;br /&gt;
      - string:&lt;br /&gt;
          name: 'GERRIT_REFSPEC'&lt;br /&gt;
          default: 'refs/heads/master'&lt;br /&gt;
    scm:&lt;br /&gt;
      - git:&lt;br /&gt;
          branches:&lt;br /&gt;
            - $GERRIT_BRANCH&lt;br /&gt;
          refspec: $GERRIT_REFSPEC&lt;br /&gt;
          url: 'https://review.openstack.org/stackforge/fuel-qa'&lt;br /&gt;
          choosing-strategy: gerrit&lt;br /&gt;
          clean:&lt;br /&gt;
            before: true&lt;br /&gt;
    publishers:&lt;br /&gt;
      - email:&lt;br /&gt;
          notify-every-unstable-build: true&lt;br /&gt;
          recipients: '{email_to}'&lt;br /&gt;
&lt;br /&gt;
- job-template:&lt;br /&gt;
    name: '{name}.build'&lt;br /&gt;
    builders:&lt;br /&gt;
      - shell:&lt;br /&gt;
          !include-raw-escape './builders/syntax-build-plugin.sh'&lt;br /&gt;
    description: '&amp;lt;a href=https://github.com/stackforge/{plugin_repo}&amp;gt;Build {name} plugin from fuel-plugins project&amp;lt;/a&amp;gt;'&lt;br /&gt;
    logrotate:&lt;br /&gt;
      numToKeep: 10&lt;br /&gt;
    parameters:&lt;br /&gt;
      - string:&lt;br /&gt;
          name: 'GERRIT_REFSPEC'&lt;br /&gt;
          default: 'refs/heads/master'&lt;br /&gt;
    scm:&lt;br /&gt;
      - git:&lt;br /&gt;
          branches:&lt;br /&gt;
            - $GERRIT_BRANCH&lt;br /&gt;
          name: ''&lt;br /&gt;
          refspec: $GERRIT_REFSPEC&lt;br /&gt;
          url: 'https://review.openstack.org/stackforge/{plugin_repo}'&lt;br /&gt;
          choosing-strategy: gerrit&lt;br /&gt;
          clean:&lt;br /&gt;
            before: true&lt;br /&gt;
    triggers:&lt;br /&gt;
      - gerrit:&lt;br /&gt;
          trigger-on:&lt;br /&gt;
            - patchset-created-event #Trigger plugin build for every gerrit patchset&lt;br /&gt;
          projects:&lt;br /&gt;
            - project-compare-type: 'PLAIN'&lt;br /&gt;
              project-pattern: '{plugin_repo}'&lt;br /&gt;
              branches:&lt;br /&gt;
                - branch-compare-type: 'ANT'&lt;br /&gt;
                  branch-pattern: '**'&lt;br /&gt;
          silent: true&lt;br /&gt;
          server-name: 'review.openstack.org'&lt;br /&gt;
    publishers:&lt;br /&gt;
      - archive:&lt;br /&gt;
          artifacts: '*.rpm'&lt;br /&gt;
      - email:&lt;br /&gt;
          notify-every-unstable-build: true&lt;br /&gt;
          recipients: '{email_to}'&lt;br /&gt;
&lt;br /&gt;
- job-template:&lt;br /&gt;
    name: '{name}.{dist}.deploy'&lt;br /&gt;
    builders:&lt;br /&gt;
      - copyartifact:&lt;br /&gt;
          project: '{name}.build'&lt;br /&gt;
          which-build: last-successful&lt;br /&gt;
      - inject:&lt;br /&gt;
          properties-content: |&lt;br /&gt;
            OPENSTACK_RELEASE={dist}&lt;br /&gt;
            TEST_GROUP={test_group}&lt;br /&gt;
            ISO_PATH={path_to_fuel_iso}&lt;br /&gt;
      - shell:&lt;br /&gt;
          !include-raw-escape './builders/deploy-plugin.sh'&lt;br /&gt;
    description: 'fuel-qa system test for {name}'&lt;br /&gt;
    logrotate:&lt;br /&gt;
      numToKeep: 10&lt;br /&gt;
    parameters:&lt;br /&gt;
      - string:&lt;br /&gt;
          name: 'GERRIT_REFSPEC'&lt;br /&gt;
          default: 'refs/heads/master'&lt;br /&gt;
    scm:&lt;br /&gt;
      - git:&lt;br /&gt;
          branches:&lt;br /&gt;
            - $GERRIT_BRANCH&lt;br /&gt;
          refspec: $GERRIT_REFSPEC&lt;br /&gt;
          url: 'https://review.openstack.org/stackforge/fuel-qa'&lt;br /&gt;
          choosing-strategy: gerrit&lt;br /&gt;
          clean:&lt;br /&gt;
            before: true&lt;br /&gt;
          wipe-workspace: false&lt;br /&gt;
    publishers:&lt;br /&gt;
      - archive:&lt;br /&gt;
          artifacts: 'logs/$BUILD_NUMBER/*'&lt;br /&gt;
      - email:&lt;br /&gt;
          notify-every-unstable-build: true&lt;br /&gt;
          recipients: '{email_to}'&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== CI/CD Workflow =====&lt;br /&gt;
&lt;br /&gt;
[[File:cicdwf.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
In terms of a specific plugin, we recommend to go through the following CI pipeline:&lt;br /&gt;
&lt;br /&gt;
# Prepare labs and start or update the lab (when a new Fuel ISO has been built):&lt;br /&gt;
#* a) Download current ISO from the [https://ci.fuel-infra.org/ Fuel CI]. Depending on Fuel version specified in plugin’s requirements, Jenkins downloads released ISO(s) and/or currently developed and passed BVT test on core CI. (for now, this should be done manually; in future, API should be provided to inform external CIs about a new stable ISO). You can also implement an internal storage with ability to download the latest stable ISO once it's out.&lt;br /&gt;
#* b) Deploy this ISO and prepare the required amount of labs for testing using '''fuel-dev''' and '''fuel-qa''' repositories and running it in console: &amp;lt;code&amp;gt;$ fuel-main/utils/jenkins/system_tests -t test -j dis_fuelweb_test -i (path to downloaded Fuel-ISO) -o --group=setup -V ${VIRTUAL_ENV} -k&amp;lt;/code&amp;gt;  You can find all the information about script installation and usage in [https://docs.mirantis.com/fuel-dev/devops.html Fuel development documentation]: &lt;br /&gt;
#* c) Create/restore the required quantity of empty VMs from snapshots. &amp;lt;br&amp;gt;The script from the previous list item uses ''dos.py'' utility for managing VMs and their snapshots (it was configured and installed on the previous step). You can find all information about dos.py just running &amp;lt;code&amp;gt;dos.py -h&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Gerrit review job will start to build plugin. See [http://docs.openstack.org/infra/manual/developers.html Gerrit workflow] for more details.&lt;br /&gt;
#* a) use preconfigured [https://wiki.jenkins-ci.org/display/JENKINS/Gerrit+Trigger Gerrit Trigger] to start your job after new Gerrit Patch arrives&lt;br /&gt;
#* b) run code syntax checker and unit tests according to the instructions from [[Testing]]&lt;br /&gt;
#* c) run puppet linter (see [[Puppet-openstack/Development|Puppet OpenStack]] page for more details)&lt;br /&gt;
#* d) build plugin (plugin should pass Fuel Plugin Builder requirements)&lt;br /&gt;
#* e) trigger plugin testing&lt;br /&gt;
# Vote on Gerrit patch’s page and add review result in comment using [[GerritJenkinsGit|Gerrit Trigger]]. (optional)&lt;br /&gt;
# Plugin testing (all three steps are part of system_tests.sh runner from [https://review.openstack.org/#/admin/projects/stackforge/fuel-qa fuel-qa] repository) :&lt;br /&gt;
#* a) install a plugin&lt;br /&gt;
#* b) configure an environment&lt;br /&gt;
#* c) deploy environment with inactive plugin&lt;br /&gt;
#* d) run OSTF tests.&lt;br /&gt;
# Run plugin-specific functional tests to check that current plugin version provides expected functionality.&lt;br /&gt;
# Publish resulting aggregated logs to the log storage. You can do it with archiving logs.&lt;br /&gt;
&lt;br /&gt;
=====  &amp;lt;big&amp;gt;Automation test cases and test framework&amp;lt;/big&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
You should follow this recommendation on how to write automation tests and configure test framework. Follow the links below for more information:&lt;br /&gt;
* [https://github.com/stackforge/fuel-qa tests] for 6.1 Fuel release&lt;br /&gt;
* [https://github.com/stackforge/fuel-qa/blob/master/fuelweb_test/tests/plugins/plugin_example/test_fuel_plugin_example.py example of writing plugin test cases]&lt;br /&gt;
* [http://docs.mirantis.com/fuel-dev/devops.html instructions on configuring an environment]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''First of all, you should prepare environment and download Fuel ISO.'''&lt;br /&gt;
 &lt;br /&gt;
1. Clone GIT repository:&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;&lt;br /&gt;
git clone https://github.com/stackforge/fuel-qa&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
2. Activate virtual env with running:&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;&lt;br /&gt;
source ~/venv-nailgun-tests-2.9/bin/activate&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
3. Export Fuel ISO path with running:&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;&lt;br /&gt;
export ISO_PATH=path-to-iso&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
4. Enter this folder:&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;&lt;br /&gt;
cd fuel-qa/&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
Start tests by running this command:&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;&lt;br /&gt;
./utils/jenkins/system_tests.sh -t test -w $(pwd) -j fuelweb_test -i $ISO_PATH -o --group=setup&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
Alternatively you can install empty setup with 1, 3, 5 or 9 slaves for the manual testing:&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt; &lt;br /&gt;
fuel-qa$ ./utils/jenkins/system_tests.sh -t test -w $(pwd) -j fuelweb_test -i $ISO_PATH -o --group=prepare_slaves_5&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
system_tests file is used as a runner for tests from fuel-qa repository.&lt;br /&gt;
&lt;br /&gt;
5. For more information on how tests work and additional options for test run, read the usage information with running:&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;&lt;br /&gt;
./utils/jenkins/system_tests.sh -h&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''In the section below, you can find information about main files and modules:'''&lt;br /&gt;
* system_tests.sh - a file where tests start execution. This file processes parameters specified from command line and invokes run_tests.py&lt;br /&gt;
* run_tests.py - used to import your test files inside this file to run your test then.&lt;br /&gt;
* settings.py -  contains environment variables used for environment customization. With this file, you can set such variables like path to ISO, nodes quantity, etc.&lt;br /&gt;
&lt;br /&gt;
Models folder with files provides the main logic of the project:&lt;br /&gt;
* environment.py -  contains methods for environment deploying, virtual machines creation and networking for them, installing Fuel on the Fuel Master node, etc.&lt;br /&gt;
Environment creation process uses devops manager fuel-devops/devops/manager.py. Devops manager is used for virtual machines creation and uses lower level libvirt driver. Also environment model contains methods for ssh interaction.&lt;br /&gt;
* nailgun_client.py -  contains functionality for nailgun handlers, methods and API that are supported by the nailgun client can be found [https://docs.mirantis.com/fuel-dev/develop/nailgun/development/api_doc.html  here]. Nailgun client uses http client that is located in helpers folder. Nailgun client is used in fuel web client. &lt;br /&gt;
&lt;br /&gt;
Fuel web client contains such methods as:cluster creation, OSTF tests launch, adding nodes to the cluster, etc.&lt;br /&gt;
&lt;br /&gt;
Helpers folder contains the following files:&lt;br /&gt;
* checkers.py - has methods for ssh client to verify nodes access and other.&lt;br /&gt;
* common.py - has methods for OpenStack API access, instances creation, etc.&lt;br /&gt;
* decorators.py - has different decorators, the most usable is ‘’log_snapshot_on_error’’; it's recommended to use this decorator for all tests, in case of any error diagnostic and environment snapshots will be created.&lt;br /&gt;
* os_actions.py - has methods to work with OpenStack.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''When writing your first test case, please mind the following:'''&lt;br /&gt;
* for writing your first test case, you can use ‘’test_fuel_plugin_example.py’’. &lt;br /&gt;
* when creating your own test class, you have to inherit this test class from TestBasic class located in ‘’base_test_case.py’’ where fuel web client initialization is performed.&lt;br /&gt;
* each test class and method have to be decorated with ‘’@test’’. &lt;br /&gt;
* each class in test group has groups to run all test cases together and each test case has groups to separate run. &lt;br /&gt;
* test cases have depends_on method or test and it means that this test case does not run until depends_on method or test will be done.&lt;br /&gt;
&lt;br /&gt;
'''Test execution order:'''&lt;br /&gt;
# Base test cases are executed: these are the tests that set up environment and install the Fuel Master node.&lt;br /&gt;
# After these tests are passed, snapshots are created which will be used by tests for creating clusters.&lt;br /&gt;
# Revert to previously created snapshots.&lt;br /&gt;
# Set up cluster and deploy it.&lt;br /&gt;
# Run Health check test (OSTF).&lt;br /&gt;
&lt;br /&gt;
For test execution debugging you can use dos.py &lt;br /&gt;
You can create snapshot with the following command:&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;&lt;br /&gt;
dos.py snapshot &amp;lt;myenv&amp;gt; --snapshot-name=&amp;lt;snapshot_name&amp;gt;&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
You can revert snapshot with:&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;&lt;br /&gt;
dos.py revert &amp;lt;myenv&amp;gt; --snapshot-name=&amp;lt;snapshot_name&amp;gt;&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Fuel-qa and Fuel Plugins ====&lt;br /&gt;
Currently, the system tests for Fuel are kept in [https://github.com/stackforge/fuel-qa fuel-qa] repo.&lt;br /&gt;
Note that for implementing Fuel Plugin CI, the fuel-qa can be used as the baseline framework.&lt;br /&gt;
This means, you can use the framework without committing any tests directly to fuel-qa repo.&lt;br /&gt;
&lt;br /&gt;
=== Preparing an environment for plugin development ===&lt;br /&gt;
&lt;br /&gt;
Prepare your environment for plugin development in three easy steps:&lt;br /&gt;
&lt;br /&gt;
1. Install the standard Linux development tools.&lt;br /&gt;
&lt;br /&gt;
*  For Ubuntu 14.04 LTS, run:&lt;br /&gt;
    ''sudo apt-get install createrepo rpm dpkg-dev''&lt;br /&gt;
&lt;br /&gt;
* For Centos 6.5, run:&lt;br /&gt;
    ''yum install createrepo rpm rpm-build dpkg-devel''&lt;br /&gt;
&lt;br /&gt;
2. Install the Fuel Plugin Builder. To do that, you should first get pip:&lt;br /&gt;
    ''easy_install pip''&lt;br /&gt;
&lt;br /&gt;
3. Then, install Fuel Plugin Builder (fpb) itself:&lt;br /&gt;
    ''pip install fuel-plugin-builder''&lt;br /&gt;
&lt;br /&gt;
If you need to install the latest version of  the Fuel Plugin Builder, follow the instruction below:&lt;br /&gt;
&lt;br /&gt;
1. Clone the repository:&lt;br /&gt;
    &amp;quot;git clone https://github.com/stackforge/fuel-plugins.git&amp;quot;&lt;br /&gt;
&lt;br /&gt;
2. Go to the 'fuel_plugin_builder' folder:&lt;br /&gt;
    &amp;quot;cd fuel-plugins/fuel_plugin_builder/&amp;quot;&lt;br /&gt;
&lt;br /&gt;
3.  Install the fpb:&lt;br /&gt;
    &amp;quot;sudo python setup.py develop&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== Using Fuel Plugin Builder tool ===&lt;br /&gt;
&lt;br /&gt;
==== Plugin structure ====&lt;br /&gt;
To build your plugin, you should first generate its structure. It looks as follows:&lt;br /&gt;
&lt;br /&gt;
[[File:Untitled drawing-3.png|500px]]&lt;br /&gt;
&lt;br /&gt;
===== Generating the structure and building the plugin =====&lt;br /&gt;
&lt;br /&gt;
So, to generate the plugin structure as given above, you should run the following command:&lt;br /&gt;
&lt;br /&gt;
''fpb --create &amp;lt;fuel_plugin_name&amp;gt;''&lt;br /&gt;
&lt;br /&gt;
As the result, you will only have to build your plugin:&lt;br /&gt;
''fpb --build &amp;lt;fuel_plugin_name&amp;gt;''&lt;br /&gt;
&lt;br /&gt;
After your plugin is built, you can see it in your plugin's directory; for example, ''fuel_plugin_name/fuel_plugin_name-1.0.0.noarch.rpm&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== How to use files from plugin structure ===&lt;br /&gt;
&lt;br /&gt;
==== deployment_tasks.yaml====&lt;br /&gt;
&lt;br /&gt;
New &amp;quot;deployment_tasks.yaml&amp;quot; file was introduced to replace the &amp;quot;tasks.yaml&amp;quot;. The new file can specify tasks dependencies using new parameters &amp;quot;required for&amp;quot; and &amp;quot;requires&amp;quot;.&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;&lt;br /&gt;
type: puppet&lt;br /&gt;
 groups: [primary-controller]&lt;br /&gt;
 required_for: [keystone]&lt;br /&gt;
 requires: [database]&lt;br /&gt;
 parameters:&lt;br /&gt;
    puppet_manifest: /etc/puppet/modules/osnailyfacter/modular/keystone/db.pp&lt;br /&gt;
    puppet_modules: /etc/puppet/modules&lt;br /&gt;
    timeout: 1800&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The list of parameters for &amp;quot;deployment_tasks.yaml&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
==== role ====&lt;br /&gt;
The parameter describes a role of a node where tasks will be executed. Usually, the role parameter is used for pre/post deployment tasks or for declaring a group for main deployment.&lt;br /&gt;
&lt;br /&gt;
==== groups  ====&lt;br /&gt;
The parameter describes a group of nodes with the specified role where tasks will be executed and should be explicitly declared for the main deployment. &lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;&lt;br /&gt;
- id: controller &lt;br /&gt;
type: group&lt;br /&gt;
role: [controller]&lt;br /&gt;
requires: [primary-controller]&lt;br /&gt;
required_for: [deploy_end]&lt;br /&gt;
parameters:&lt;br /&gt;
strategy: &lt;br /&gt;
type: parallel&lt;br /&gt;
amount: 6&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The “groups” parameter is usually used for the main deployment. It conflicts with the &amp;quot;role&amp;quot; parameter. The task must have either a “role” or “group” parameter, but not both of them at the same time. &lt;br /&gt;
&lt;br /&gt;
==== requires ====&lt;br /&gt;
The parameter specifies the list of tasks needed by the current one. The list of tasks can be obtained by running the command:&lt;br /&gt;
&amp;lt;code&amp;gt;fuel graph --env 1 --download&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== required_for ====&lt;br /&gt;
The parameter specifies the list of tasks for which the current one is needed.&lt;br /&gt;
&lt;br /&gt;
==== timeout ====&lt;br /&gt;
You can also specify execution timeout in seconds. Once specified, the deployment will fail if timeout expires. By default, timeout is set to 300 seconds.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Previously, when plugin developer set timeout for operation, this timeout worked differently for specific operations. For example:&lt;br /&gt;
&lt;br /&gt;
* shell task type timeout =  timeout * retries (Mcollective retries, 2 by default)&lt;br /&gt;
* puppet task type timeout = global timeout (the one set by plugin developer).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Now it works properly in both cases: shell and puppet task types have global timeout.&lt;br /&gt;
&lt;br /&gt;
==== type: shell parameter ====&lt;br /&gt;
The parameter runs the specified shell command, the second applies Puppet manifests.&lt;br /&gt;
&lt;br /&gt;
Here is the example of a &amp;quot;shell&amp;quot; task:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;&lt;br /&gt;
# This tasks will be applied on controller nodes,&lt;br /&gt;
# here you can also specify several roles, for example&lt;br /&gt;
# ['cinder', 'compute'] will be applied only on&lt;br /&gt;
# cinder and compute nodes&lt;br /&gt;
- id: task-shell-deploy&lt;br /&gt;
  role: ['controller']&lt;br /&gt;
  type: shell&lt;br /&gt;
  parameters:&lt;br /&gt;
    cmd: bash deploy.sh&lt;br /&gt;
    timeout: 42&lt;br /&gt;
&lt;br /&gt;
- id: task-shell-deploy&lt;br /&gt;
  role: ['cinder','compute'']&lt;br /&gt;
  type: shell&lt;br /&gt;
  parameters:&lt;br /&gt;
    cmd: bash deploy.sh&lt;br /&gt;
    timeout: 42&lt;br /&gt;
&lt;br /&gt;
# Task is applied for all roles&lt;br /&gt;
- id: task-shell-pluginlog&lt;br /&gt;
  role: '*'&lt;br /&gt;
  type: shell&lt;br /&gt;
  parameters:&lt;br /&gt;
    cmd: echo all &amp;gt; /tmp/plugin.all&lt;br /&gt;
    timeout: 42&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== type: puppet  ====&lt;br /&gt;
Puppet task type allows you to apply your own Puppet manifests on OpenStack nodes. For more information, see Puppet in Fuel section.&lt;br /&gt;
&lt;br /&gt;
To enable this task type, add your ''site.pp'' file in ''deployment_scripts/puppet/manifests/'' directory.&lt;br /&gt;
Then put all required modules in ''deployment_scripts/puppet/modules'' directory.&lt;br /&gt;
&lt;br /&gt;
* puppet_manifest - specify directory path for your manifest relative to deployment_scripts.&lt;br /&gt;
* puppet_modules - specify directory path for your modules relative to deployment_scripts.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;&lt;br /&gt;
# Deployment will be applied on controllers only&lt;br /&gt;
- role: ['controller']&lt;br /&gt;
  type: puppet&lt;br /&gt;
  parameters:&lt;br /&gt;
    puppet_manifest: puppet/manifests/site.pp&lt;br /&gt;
    puppet_modules: puppet/modules&lt;br /&gt;
    timeout: 360&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== type: reboot ====&lt;br /&gt;
Beginning with Fuel 6.1 release for plugins with '''package_version: 2.0.0''', reboot task type allows you to reboot your node with specifying the timeout. This can be useful to apply numerous changes at the node.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;&lt;br /&gt;
- role: '*'&lt;br /&gt;
  type: reboot&lt;br /&gt;
  parameters:&lt;br /&gt;
    timeout: 300&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== type: group ====&lt;br /&gt;
A group task consists of the list of tasks to be executed on the specified nodes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;&lt;br /&gt;
- id: standalone-keystone &lt;br /&gt;
  type: group &lt;br /&gt;
  role: [standalone-keystone] &lt;br /&gt;
  requires: [deploy_start, primary-standalone-keystone] &lt;br /&gt;
  required_for: [deploy_end] &lt;br /&gt;
  tasks: [fuel_pkgs, hiera, globals, tools, logging, netconfig, hosts, firewall, deploy_start, cluster, keystone-vip, cluster-haproxy, memcached, openstack-haproxy-stats, task-keystone] &lt;br /&gt;
  parameters: &lt;br /&gt;
     strategy: &lt;br /&gt;
        type: parallel&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When you set up a group of tasks you can also specify how they will be executed: in “parallel” or “one-by-one”. &lt;br /&gt;
&lt;br /&gt;
==== strategy: type ====&lt;br /&gt;
&lt;br /&gt;
 * &amp;quot;parallel&amp;quot; - tasks will be executed in parallel&lt;br /&gt;
 * &amp;quot;one-by-one&amp;quot; - tasks will be executed one-by-one&lt;br /&gt;
&lt;br /&gt;
Once you choose “parallel” you can specify the maximal number of tasks that can be run in parallel using the “amount” parameter.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;&lt;br /&gt;
- id: controller&lt;br /&gt;
 type: group&lt;br /&gt;
 role: [controller]&lt;br /&gt;
 requires: [primary-controller]&lt;br /&gt;
 required_for: [deploy_end]&lt;br /&gt;
 parameters:&lt;br /&gt;
   strategy:&lt;br /&gt;
     type: parallel&lt;br /&gt;
     amount: 6&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== environment_config.yaml ====&lt;br /&gt;
&lt;br /&gt;
This file describes additional attributes that will appear on the Settings tab of the Fuel web UI.&lt;br /&gt;
When the environment is deployed, these attributes are passed to the task executor so that the data is available in the /etc/astute.yaml file&lt;br /&gt;
on each target node and can be accessed from your bash or puppet scripts.&lt;br /&gt;
&lt;br /&gt;
By default, your environment_config.yaml file adds text field on Fuel web UI:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;&lt;br /&gt;
attributes:&lt;br /&gt;
  fuel_plugin_name_text:&lt;br /&gt;
    value: 'Set default value'&lt;br /&gt;
    label: 'Text field'&lt;br /&gt;
    description: 'Description for text field'&lt;br /&gt;
    weight: 25&lt;br /&gt;
    type: &amp;quot;text&amp;quot;&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For more information on Fuel web UI elements for a plugin, see Fuel plugin UI elements.&lt;br /&gt;
&lt;br /&gt;
==== metadata.yaml ====&lt;br /&gt;
&lt;br /&gt;
This file contains the description of your plugin:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;&lt;br /&gt;
# Plugin name&lt;br /&gt;
name: fuel_plugin_name&lt;br /&gt;
# Human-readable name for your plugin, it will be shown on UI&lt;br /&gt;
# as a name of plugin group&lt;br /&gt;
title: Title for fuel_plugin_name plugin&lt;br /&gt;
# Plugin version&lt;br /&gt;
version: 1.0.0&lt;br /&gt;
# Description&lt;br /&gt;
description: Enable to use plugin X&lt;br /&gt;
# Required fuel version&lt;br /&gt;
fuel_version: ['6.0']&lt;br /&gt;
# The plugin is compatible with releases in the list&lt;br /&gt;
releases:&lt;br /&gt;
  - os: ubuntu&lt;br /&gt;
    version: 2014.2-6.0&lt;br /&gt;
    mode: ['ha', 'multinode']&lt;br /&gt;
    deployment_scripts_path: deployment_scripts/&lt;br /&gt;
    repository_path: repositories/ubuntu&lt;br /&gt;
  - os: centos&lt;br /&gt;
    version: 2014.2-6.0&lt;br /&gt;
    mode: ['ha', 'multinode']&lt;br /&gt;
    deployment_scripts_path: deployment_scripts/&lt;br /&gt;
    repository_path: repositories/centos&lt;br /&gt;
# Version of plugin package&lt;br /&gt;
package_version: '1.0.0'&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Parameter !! Usage !! Comments/Example&lt;br /&gt;
|-&lt;br /&gt;
| name || Internal name for your plugin. ||Name can consist of lowercase letters, '-' and '_' symbols.&lt;br /&gt;
|-&lt;br /&gt;
| title || Human-readable name for the plugin that will appear on the Fuel web UI. ||&lt;br /&gt;
|-&lt;br /&gt;
| description || Description of your plugin. || For example: Enables X functionality for nodes with Controller role.&lt;br /&gt;
|-&lt;br /&gt;
| version || Plugin version. || For the guidelines, see [http://semver.org/ Semantic Versioning 2.0.0.]&lt;br /&gt;
|-&lt;br /&gt;
| fuel_version || A list of plugin-compatible versions of Fuel. || For example, 2014.2-6.0.&lt;br /&gt;
|-&lt;br /&gt;
| package_version || version of plugin; Fuel uses this version to choose the way a plugin should be installed. || Example&lt;br /&gt;
|-&lt;br /&gt;
| is_hotpluggable || Set this parameter to 'true' to enable installation of a plugin on top of already deployed environment. Use this parameter only with application level plugins that have no core functionality. Also, the plugin must define a role that Fuel can apply to a new node, which has not already been provisioned. This role can be co-located with another role as long as they are being provisioned onto a new node but not the one that was previously provisioned or deployed. || See the [https://github.com/openstack/fuel-plugins/blob/master/examples/fuel_plugin_example_v4/metadata.yaml#L22 template] with the parameter set to 'false' by default.&lt;br /&gt;
|-&lt;br /&gt;
| releases || a list of OpenStack releases compatible with the plugin. || For example, 2014.2-6.0.&lt;br /&gt;
|-&lt;br /&gt;
| os ||  a name of supported Linux distribution ||  For example, Ubuntu or CentOSe&lt;br /&gt;
|-&lt;br /&gt;
| version || A version of OpenStack release || &lt;br /&gt;
|-&lt;br /&gt;
| mode || A list plugin-compatible modes. || 'ha' is used if plugin supports High Availability;’'multinode' - if it does not.&lt;br /&gt;
|-&lt;br /&gt;
| deployment_scripts_path  || A path in your plugin directory where all deployment scripts for the release are located relative to the top of the plugin directory. || &lt;br /&gt;
|-&lt;br /&gt;
| repository_path  || A path in your plugin directory where all packages for the release are located relative to the top of the plugin directory. || Example&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===  Plugins deployment order ===&lt;br /&gt;
&lt;br /&gt;
Beginning with Fuel 6.1 release,  you can specify the order in which plugins are deployed.&lt;br /&gt;
This is especially useful if several plugins should be enabled in one environment.&lt;br /&gt;
For example, plugins for network configuration should be run before plugins installing software services.&lt;br /&gt;
For each stage name plugin developer adds a postfix, which defines the stage of&lt;br /&gt;
specific execution order of the task.&lt;br /&gt;
Let's have a look at the following sample:&lt;br /&gt;
&lt;br /&gt;
The ''tasks.yam''l file of Fuel plugin '''A''':&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;&lt;br /&gt;
role: ['primary-controller', 'controller']&lt;br /&gt;
stage: post_deployment/100&lt;br /&gt;
type: shell&lt;br /&gt;
parameters:&lt;br /&gt;
    cmd: bash deploy.sh&lt;br /&gt;
    timeout: 42&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The ''tasks.yaml'' file of Fuel plugin '''B''':&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;&lt;br /&gt;
role: ['primary-controller', 'controller']&lt;br /&gt;
stage: post_deployment/50&lt;br /&gt;
type: shell&lt;br /&gt;
parameters:&lt;br /&gt;
    cmd: bash deploy.sh&lt;br /&gt;
    timeout: 42&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
During post_deployment stage execution, the task of plugin '''B'''&lt;br /&gt;
will be run before plugin post task of plugin '''A''', because&lt;br /&gt;
''post_deployment/50'' is lower than ''post_deployment/100''.&lt;br /&gt;
Nevertheless, in some cases plugins do not know about each other so the best&lt;br /&gt;
way to solve the problem is to define the convention of ranges which&lt;br /&gt;
plugin developers will be able to use:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| 0 - 999  || hardware configuration, for example drivers configuration&lt;br /&gt;
|-&lt;br /&gt;
| 1000 - 1999 || reserved for future uses&lt;br /&gt;
|-&lt;br /&gt;
| 2000 - 2999 || disks partitioning and volumes configuration&lt;br /&gt;
|-&lt;br /&gt;
| 3000 - 3999 || reserved for future uses&lt;br /&gt;
|-&lt;br /&gt;
| 4000 - 4999 || network configuration&lt;br /&gt;
|-&lt;br /&gt;
| 5000 - 5999 || reserved for future uses&lt;br /&gt;
|-&lt;br /&gt;
| 6000 - 6999 || software deployment&lt;br /&gt;
|-&lt;br /&gt;
| 7000 - 7999 || reserved for future uses&lt;br /&gt;
|-&lt;br /&gt;
| 8000 - 8999 || monitoring services deployment&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== How the deployment order works in specific cases ====&lt;br /&gt;
&lt;br /&gt;
* If one network plugin defines stage: ''post_deployment/100''&lt;br /&gt;
and another one has stage: ''post_deployment/2000'', they will be&lt;br /&gt;
installed in the right order without knowing about each other.&lt;br /&gt;
* If there are two plugins which implement monitoring, plugin developers&lt;br /&gt;
can figure out which plugin should be installed first and tune postfixes&lt;br /&gt;
accordingly.&lt;br /&gt;
* If two tasks have the same priority, they should be sorted in alphabetical&lt;br /&gt;
order by name and the first in the list should be deployed first.&lt;br /&gt;
* If several tasks with the same postfix priority are present in a single plugin,&lt;br /&gt;
then they should be deployed in the same order in which they specified in the&lt;br /&gt;
file.&lt;br /&gt;
* Postfix can be negative or positive, floating or integer number.&lt;br /&gt;
&lt;br /&gt;
==== Additional stages ====&lt;br /&gt;
&lt;br /&gt;
Additional plugin-specific stages can be defined:&lt;br /&gt;
* hw_configuration&lt;br /&gt;
* disk_partitioning&lt;br /&gt;
* network_configuration&lt;br /&gt;
* software_installation&lt;br /&gt;
&lt;br /&gt;
With the already existing stages:&lt;br /&gt;
* pre_deployment&lt;br /&gt;
* post_deployment&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
And, finally, a new stage:&lt;br /&gt;
* monitoring&lt;br /&gt;
&lt;br /&gt;
In this case, plugin developer will be able to work with a single entity&lt;br /&gt;
without some additional postfixes.&lt;br /&gt;
&lt;br /&gt;
===  How to display plugin restrictions to users  ===&lt;br /&gt;
&lt;br /&gt;
Sometimes you might need to provide restrictions for your plugin&lt;br /&gt;
in the Fuel UI. That means, all incompatible options (e.g. Networking Setup)&lt;br /&gt;
should be somehow grayed out.&lt;br /&gt;
&lt;br /&gt;
==== What are restrictions? ====&lt;br /&gt;
&lt;br /&gt;
Restrictions define when settings and setting groups should be available.&lt;br /&gt;
Each restriction is defined as a condition with optional action and message:&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;&lt;br /&gt;
restrictions:&lt;br /&gt;
  - condition: &amp;quot;settings:common.libvirt_type.value != 'kvm'&amp;quot;&lt;br /&gt;
    message: &amp;quot;KVM only is supported&amp;quot;&lt;br /&gt;
  - condition: &amp;quot;not ('experimental' in version:feature_groups)&amp;quot;&lt;br /&gt;
    action: hide&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* condition is an expression written in  [https://github.com/stackforge/fuel-web/blob/master/docs/develop/nailgun/customization/settings.rst#expression-dsl Expression DSL]. If returned value is true, then action is performed and message is shown (if specified).&amp;lt;br/&amp;gt;&lt;br /&gt;
* action defines what to do if condition is satisfied. Supported values are ''&amp;quot;disable&amp;quot;'', ''&amp;quot;hide&amp;quot;'' and ''&amp;quot;none&amp;quot;''. The ''&amp;quot;none&amp;quot;'' value can be used just to display message. This field is optional (the default value is ''&amp;quot;disable&amp;quot;''): &amp;lt;br/&amp;gt;&lt;br /&gt;
** disable - plugin checkbox (placed into the ''Settings'' tab of the Fuel web UI) turns inactive and has a yellow triangle with a pop-up warning (when hovering a mouse).&lt;br /&gt;
** hide - when incorrect parameters are selected, the plugin checkbox will not appear in the ''Settings'' tab of the Fuel web UI at all.&lt;br /&gt;
** none - plugin checkbox stays active and has a yellow triangle with a warning (when hovering a mouse).&lt;br /&gt;
* message is a message that is displayed if the condition is satisfied. This field is optional.&amp;lt;br/&amp;gt;&lt;br /&gt;
* strict is a boolean flag which specifies how to handle non-existent keys in expressions. If it is set to true (default value), exception is thrown in case of non-existent key. Otherwise values of such keys have null value. Setting this flag to false is useful for conditions which rely on settings provided by plugins:&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;&lt;br /&gt;
restrictions:&lt;br /&gt;
  - condition: &amp;quot;settings:other_plugin == null or settings:other_plugin.metadata.enabled != true&amp;quot;&lt;br /&gt;
    strict: false&lt;br /&gt;
    message: &amp;quot;Other plugin must be installed and enabled&amp;quot;&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are also short forms of restrictions:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;&lt;br /&gt;
restrictions:&lt;br /&gt;
  - &amp;quot;settings:common.libvirt_type.value != 'kvm'&amp;quot;: &amp;quot;KVM only is supported&amp;quot;&lt;br /&gt;
  - &amp;quot;settings:storage.volumes_ceph.value == true&amp;quot;&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== How to add restrictions to plugin-related fields and checkbox =====&lt;br /&gt;
&lt;br /&gt;
Note, that you can not only add restrictions to the checkbox, but also to the plugin-related fields.&lt;br /&gt;
Here is the [https://github.com/stackforge/fuel-plugin-contrail/blob/master/environment_config.yaml#L3 example implementation]:&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;&lt;br /&gt;
attributes:&lt;br /&gt;
  # Show contrail only in supported network config&lt;br /&gt;
  metadata:&lt;br /&gt;
    restrictions:&lt;br /&gt;
      - condition: &amp;quot;not (cluster:net_provider == 'neutron' and networking_parameters:segmentation_type == 'vlan')&amp;quot;&lt;br /&gt;
        message: &amp;quot;Please use Neutron with VLAN segmentation, the only network type supported with Contrail plugin.&amp;quot;&lt;br /&gt;
  contrail_asnum:&lt;br /&gt;
    value: '64512'&lt;br /&gt;
    label: 'AS Number'&lt;br /&gt;
    description: 'AS number for BGP communication'&lt;br /&gt;
    weight: 10&lt;br /&gt;
    type: &amp;quot;text&amp;quot;&lt;br /&gt;
    regex:&lt;br /&gt;
      source: '^(?:(6553[0-5])|(655[0-2]\d)|(65[0-4]\d{2})|(6[0-4]\d{3})|([1-5]\d{4})|([1-9]\d{1,3})|([1-9]))$'&lt;br /&gt;
      error: &amp;quot;Invalid AS number&amp;quot;&lt;br /&gt;
  contrail_private_cidr:&lt;br /&gt;
    value: '10.109.3.0/24'&lt;br /&gt;
    label: 'Private network CIDR'&lt;br /&gt;
    description: 'CIDR for private network used in Contrail inter-node communication'&lt;br /&gt;
    weight: 20&lt;br /&gt;
    type: &amp;quot;text&amp;quot;&lt;br /&gt;
    regex:&lt;br /&gt;
      source: '^(?:\d|1?\d\d|2[0-4]\d|25[0-5])(?:\.(?:\d|1?\d\d|2[0-4]\d|25[0-5])){3}(?:\/(?:[1-2]\d|[8-9]))$'&lt;br /&gt;
      error: &amp;quot;Invalid network CIDR&amp;quot;&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
Such a restriction will be then displayed in the Fuel web UI as follows:&lt;br /&gt;
[[File:Plugin-restriction.png]]&lt;br /&gt;
&lt;br /&gt;
==== Example implementation ====&lt;br /&gt;
&lt;br /&gt;
Here is the [https://github.com/stackforge/fuel-web/blob/master/nailgun/nailgun/fixtures/openstack.yaml#L511-L525 example implementation] of the restriction:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;&lt;br /&gt;
              - data: &amp;quot;disabled&amp;quot;&lt;br /&gt;
                label: &amp;quot;Mellanox drivers and plugins disabled&amp;quot;&lt;br /&gt;
                description: &amp;quot;If selected, Mellanox drivers, Neutron and Cinder plugin will not be installed.&amp;quot;&lt;br /&gt;
                restrictions:&lt;br /&gt;
                  - &amp;quot;settings:storage.iser.value == true&amp;quot;&lt;br /&gt;
              - data: &amp;quot;drivers_only&amp;quot;&lt;br /&gt;
                label: &amp;quot;Install only Mellanox drivers&amp;quot;&lt;br /&gt;
                description: &amp;quot;If selected, Mellanox Ethernet drivers will be installed to support networking over Mellanox NIC. Mellanox Neutron plugin will not be installed.&amp;quot;&lt;br /&gt;
                restrictions:&lt;br /&gt;
                  - &amp;quot;settings:common.libvirt_type.value != 'kvm'&amp;quot;&lt;br /&gt;
              - data: &amp;quot;ethernet&amp;quot;&lt;br /&gt;
                label: &amp;quot;Install Mellanox drivers and SR-IOV plugin&amp;quot;&lt;br /&gt;
                description: &amp;quot;If selected, both Mellanox Ethernet drivers and Mellanox network acceleration (Neutron) plugin will be installed.&amp;quot;&lt;br /&gt;
                restrictions:&lt;br /&gt;
                  - &amp;quot;settings:common.libvirt_type.value != 'kvm' or not (cluster:net_provider == 'neutron' and networking_parameters:segmentation_type == 'vlan')&amp;quot;&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== How to migrate plugins from 1.0.0 to 2.0.0 package version ==&lt;br /&gt;
&lt;br /&gt;
Beginning with Fuel 6.1, new plugins format is supported. Note, that new format is not compatible with Fuel 6.0.&lt;br /&gt;
&lt;br /&gt;
For new plugins, Fuel Plugin Builder builds RPM packages instead of fuel plugin archives.&lt;br /&gt;
&lt;br /&gt;
In order to migrate from old format to new, follow these steps:&lt;br /&gt;
* Get the latest fuel plugin builder version, 2.0.0 or higher.&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;&lt;br /&gt;
pip install fuel-plugin-builder&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Change the value of '''package_version''' parameter in '''metadata.yaml''' file from '''1.0.0''' to '''2.0.0'''.&lt;br /&gt;
* Run the following command:&lt;br /&gt;
 &amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;fpb --check plugin_path&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
and fix the errors one by one or follow the instructions below.&lt;br /&gt;
&lt;br /&gt;
=== Updates ===&lt;br /&gt;
&lt;br /&gt;
If your plugin uses &amp;quot;controller&amp;quot; role in '''tasks.yaml''' file, make sure that you have also specified the &amp;quot;primary-controller&amp;quot;. &lt;br /&gt;
In new plugins, &amp;quot;controller&amp;quot; and &amp;quot;primary-controller&amp;quot; should be defined explicitly. In previous version, you could indicate  &amp;quot;controller&amp;quot;, and then the &amp;quot;primary-controller&amp;quot; was added at the backend automatically.&lt;br /&gt;
&lt;br /&gt;
=== Brand new features ===&lt;br /&gt;
&lt;br /&gt;
Several obligatory fields are added to '''metadata.yaml''' file:&lt;br /&gt;
* '''groups''' field is used to specify group which your plugin belongs to. Either of the options is available:&lt;br /&gt;
** network&lt;br /&gt;
** storage&lt;br /&gt;
** storage::cinder&lt;br /&gt;
** storage::glance&lt;br /&gt;
** hypervisor&lt;br /&gt;
** monitoring.&lt;br /&gt;
If your plugin does not belong to any of these options, set an empty list as a value for &amp;quot;groups&amp;quot; parameter.&lt;br /&gt;
* '''authors''' field provides the list of authors. Here you should specify your or your company's name.&lt;br /&gt;
  '''Note:''' No commas should be used in '''authors''' field&lt;br /&gt;
        don't: &lt;br /&gt;
        authors: ['Vyacheslav Struk, Mirantis', 'Oleksandr Martsyniuk, Mirantis']&lt;br /&gt;
        do: &lt;br /&gt;
        authors: ['Vyacheslav Struk', 'Oleksandr Martsyniuk']&lt;br /&gt;
* '''licenses''' field contains the list of licenses.&lt;br /&gt;
* '''homepage''' field sets a link to plugin's project.&lt;br /&gt;
&amp;lt;br/&amp;gt;See the [https://github.com/stackforge/fuel-plugin-contrail/blob/master/metadata.yaml#L25 Contrail plugin] ''metadata.yaml'' file for example.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
One more task type is introduced: the '''reboot''' task is useful if you perform node configuration which requires reboot; for example, in case of linux kernel parameters configuration.&lt;br /&gt;
For information about reboot task type, see [[Fuel/Plugins#type:_reboot_parameter|the Plugins wiki]].&lt;br /&gt;
&lt;br /&gt;
== Plugin versioning system ==&lt;br /&gt;
&lt;br /&gt;
When new functionality, minor updates or security fixes should be delivered, plugin developer creates a new version of the plugin; this can be major or minor one:&lt;br /&gt;
* major - changes in API, functionality, major OpenStack release introduced.&lt;br /&gt;
* minor - security fixes only.&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
In 6.0, plugins had .fp format only. It’s deprecated now.&lt;br /&gt;
In 6.1 and higher, only RPM plugins are used. Their versioning is performed as follows:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!  !! Plugin file format !! fuel-plugin value !! metadata.yaml !! major !! minor&lt;br /&gt;
|-&lt;br /&gt;
| RPM || fuel-plugin-1.0-1.0.0 || 1.0 || 1.0.0 || 1.0.0 || 1.0.1&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Here is the example:&lt;br /&gt;
Let's suppose that a plugin has 1.0.1 version in the metadata.yaml file.&lt;br /&gt;
The plugin file should then have a different format: plugin-1.0-1.0.1.rpm.&lt;br /&gt;
&lt;br /&gt;
=== Update procedure ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!  !! Update !! Limitations&lt;br /&gt;
|-&lt;br /&gt;
| fp || NO || &lt;br /&gt;
|-&lt;br /&gt;
| RPM || YES || Can be updated to minor version only with  &amp;lt;code&amp;gt;fuel plugins --update &amp;lt;fuel-plugin-file&amp;gt;&amp;lt;/code&amp;gt;  command. To get a major one, user has to download it from Fuel Plugins Catalog and create a new environment from scratch.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Versioning scheme ===&lt;br /&gt;
* for .fp plugins versioning is not supported at all. That means, user has to download&amp;amp;install the plugin from scratch.&lt;br /&gt;
* for RPM plugins, it looks as follows:&lt;br /&gt;
[[File:Rpm plugin versioning.png]]&lt;br /&gt;
&lt;br /&gt;
=== Important note ===&lt;br /&gt;
Please, consider changing the versioning scheme for customized packages&lt;br /&gt;
to have clear indicator which package is installed - the ones that enter Mirantis OpenStack or customized ones.&lt;br /&gt;
&lt;br /&gt;
Otherwise, there is need to check python files to understand which package is actually installed.&lt;br /&gt;
&lt;br /&gt;
== How it works from the inside ==&lt;br /&gt;
&lt;br /&gt;
=== Installation ===&lt;br /&gt;
&lt;br /&gt;
Installation procedure consists of the following steps:&lt;br /&gt;
&lt;br /&gt;
# User copies fuel_plugin_name-1.0-1.0.0-1.noarch.rpm file on the Fuel Master node with secure copy.&lt;br /&gt;
# Then, after it’s copied to the Fuel Master node, the user runs the following command:&amp;lt;br&amp;gt;&amp;lt;code&amp;gt;fuel plugins --install fuel_plugin_name-1.0-1.0.0-1.noarch.rpm&amp;lt;/code&amp;gt;&lt;br /&gt;
# Fuel client installs the contents of the fuel_plugin_name-1.0-1.0.0-1.noarch.rpm package to the ''/var/www/nailgun/plugins/fuel_plugin_name-1.0''.&lt;br /&gt;
# Fuel client registers the plugin using REST API Service (Nailgun); it sends a POST request with the contents of metadata.yaml file to /api/v1/plugins url.&lt;br /&gt;
&lt;br /&gt;
=== Configuration ===&lt;br /&gt;
&lt;br /&gt;
Configuration procedure consists of the following steps:&lt;br /&gt;
&lt;br /&gt;
# When a new environment is created, Nailgun tries to find plugins which are compatible with the environment.&lt;br /&gt;
# Nailgun merges the contents of the environment_config.yaml files with the basic attributes of the environment and generates a separate group and the checkbox on the Fuel web UI for each plugin.&lt;br /&gt;
# The plugin is disabled until the user enables it. After user selected the plugin checkbox, the Fuel web UI sends the data to Nailgun. Nailgun parses the request and creates relations between Plugin and Cluster models.&lt;br /&gt;
&lt;br /&gt;
====Prioritization of Repositories====&lt;br /&gt;
&lt;br /&gt;
You can use priorities to configure plugin’s repositories instead of shutting them down completely, which may lead to the failed deployment.&lt;br /&gt;
You can specify the priorities for plugin's repositories in Nailgun’s [https://github.com/stackforge/fuel-web/blob/master/nailgun/nailgun/settings.yaml#L88-L95 settings.yaml]. &lt;br /&gt;
Default priorities for Plugins' repos look like:&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;&lt;br /&gt;
REPO_PRIORITIES: &lt;br /&gt;
  plugins: &lt;br /&gt;
    centos: 10 &lt;br /&gt;
    ubuntu: 1100&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These priorities should be higher than OS/Fuel one, because a user may want to override some package from OS/Fuel.&lt;br /&gt;
&lt;br /&gt;
====Virtual IP reservation via Fuel Plugin's metadata====&lt;br /&gt;
&lt;br /&gt;
Some plugins require an additional VIP to enable proper configuration. Previously, VIP reservation was based on network metadata. Now, it is based on the network roles' description. This enables a plugin developer to create extra VIPs to be used in developer's deployment scripts.&lt;br /&gt;
&lt;br /&gt;
First, a user should define VIPs in the plugin metadata. Then, install a plugin before creating an environment. In upcoming releases, the requirement to install a plugin prior to environment creation will be removed.&lt;br /&gt;
&lt;br /&gt;
For example, Zabbix can be configured in a way that it receives SNMP traffic on a dedicated VIP. In that case, a plugin developer can define extra VIPs in a plugin configuration file, and use it as a puppet resource.&lt;br /&gt;
&lt;br /&gt;
VIP reservation is possible only via plugin metadata. This is done by adding a new file ‘network_roles.yaml’, which looks like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;&lt;br /&gt;
- id: &amp;quot;name_of_network_role&amp;quot;&lt;br /&gt;
  default_mapping: &amp;quot;public&amp;quot;&lt;br /&gt;
  properties:&lt;br /&gt;
    subnet: true&lt;br /&gt;
    gateway: false&lt;br /&gt;
    vip:&lt;br /&gt;
      - name: &amp;quot;test_a&amp;quot;&lt;br /&gt;
        alias: &amp;quot;alias_name&amp;quot;&lt;br /&gt;
	namespace: &amp;quot;haproxy&amp;quot;&lt;br /&gt;
        node_roles: [&amp;quot;primary-controller&amp;quot;, &amp;quot;controller&amp;quot;]&lt;br /&gt;
      - name: &amp;quot;test_b&amp;quot;&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that 'alias', 'namespace', and 'node_roles' parameters are optional.&lt;br /&gt;
&lt;br /&gt;
* 'default_mapping' - a name of a network to map the network role by default. So, VIP will be allocated on that network by default (that mapping can be changed in the network template). Thus, several network roles should be defined if VIPs should be allocated in different networks.&lt;br /&gt;
&lt;br /&gt;
* 'name' - a string that contains a unique name within the environment used in the Nailgun database and for serialization in the orchestrator. &lt;br /&gt;
  '''Note:''' Names for network interfaces are generated automatically using  first 13 characters of a VIP’s name. Therefore, if several VIPs are introduced by the same plugin, their names must differ in first 13 characters. Also, do not use the word ‘vip’ in a VIP’s name, as it will be added automatically where necessary.&lt;br /&gt;
&lt;br /&gt;
* 'alias' - a string used to solve a compatibility issue with REST API to run tests within the OpenStack Testing Framework that use the old notation.&lt;br /&gt;
&lt;br /&gt;
* 'namespace' - a string that points to a network namespace to be used for landing of the VIP, null if not defined. &lt;br /&gt;
  '''Note:''' You must specify a namespace for a VIP,  otherwise it still will be put into network_metadata['vips'] in Hiera, where all available VIPs are stored, but not handled by Pacemaker. So, a plugin can use it in its own way.&lt;br /&gt;
&lt;br /&gt;
* 'node_roles' - a list of node roles where VIPs should be set up. If not defined, its value will be set to [&amp;quot;primary-controller&amp;quot;, &amp;quot;controller&amp;quot;].&lt;br /&gt;
  '''Note:''' A node must have Pacemaker installed that automatically allocates resources for all VIPs. In Fuel 6.1, VIPs were processed manually.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Known issue:''' &lt;br /&gt;
It should be mentioned, that only new network roles can be requested in a plugin. Previously defined core network roles cannot be redefined/extended in a plugin.&lt;br /&gt;
For more information, see [https://bugs.launchpad.net/fuel/+bug/1487011 LP1487011].&lt;br /&gt;
&lt;br /&gt;
====Configuration of Fuel Plugins with new roles====&lt;br /&gt;
&lt;br /&gt;
Beginning with Fuel 7.0, after adding and enabling custom plugins a user can define a new role described in the plugins via Web UI as well as via Fuel CLI. In such case, in the '''Settings''' tab you can select a ''plugin'' role from a ''roles'' list in the '''Nodes''' tab and attach it to specific nodes. And vice versa, it should not be displayed in the roles list when the plugin is disabled for the cluster (environment).&lt;br /&gt;
&lt;br /&gt;
If you want to disable a plugin, but there are nodes with this plugin’s role in a cluster, then follow the existing mechanism: in the '''Nodes''' tab remove the plugin’s role from all the nodes and then disable the plugin in the '''Settings''' tab.&lt;br /&gt;
&lt;br /&gt;
'''NOTE:'''&lt;br /&gt;
When a cluster is deployed, you cannot disable a plugin and, as a result, remove plugin’s role(s) from nodes.&lt;br /&gt;
&lt;br /&gt;
New node’s roles with a volume’s partition and tasks info can be described in config yaml files that will be integrated in Nailgun. The Fuel plugin builder should automatically create a new node role based on a plugin name in a yaml file. &lt;br /&gt;
&lt;br /&gt;
The basic skeleton describing a node’s role in the ‘node_roles’ yaml file:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;&lt;br /&gt;
role_name:&lt;br /&gt;
  name: &amp;quot;Some plugin role&amp;quot;&lt;br /&gt;
  description: &amp;quot;Some description&amp;quot;&lt;br /&gt;
  conflicts:&lt;br /&gt;
    - some_not_compatible_role&lt;br /&gt;
  limits:&lt;br /&gt;
    min: 1&lt;br /&gt;
  restrictions:&lt;br /&gt;
    - condition: &amp;quot;some logic condition&amp;quot;&lt;br /&gt;
      message: &amp;quot;Some message for restriction warning&amp;quot;&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Description of the volumes’ partition in ‘volumes’ yaml file:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;&lt;br /&gt;
volumes:&lt;br /&gt;
  - id: &amp;quot;role_volume_name&amp;quot;&lt;br /&gt;
    type: &amp;quot;vg&amp;quot;&lt;br /&gt;
    min_size: {generator: &amp;quot;calc_min_os_size&amp;quot;}&lt;br /&gt;
    label: &amp;quot;Role specific volume&amp;quot;&lt;br /&gt;
    items:&lt;br /&gt;
      - mount: &amp;quot;/&amp;quot;&lt;br /&gt;
        type: &amp;quot;lv&amp;quot;&lt;br /&gt;
        name: &amp;quot;root&amp;quot;&lt;br /&gt;
        size: {generator: &amp;quot;calc_total_root_vg&amp;quot;}&lt;br /&gt;
        file_system: &amp;quot;ext4&amp;quot;&lt;br /&gt;
      - mount: &amp;quot;swap&amp;quot;&lt;br /&gt;
        type: &amp;quot;lv&amp;quot;&lt;br /&gt;
        name: &amp;quot;swap&amp;quot;&lt;br /&gt;
        size: {generator: &amp;quot;calc_swap_size&amp;quot;}&lt;br /&gt;
        file_system: &amp;quot;swap&amp;quot;&lt;br /&gt;
volumes_roles_mapping:&lt;br /&gt;
  role_name:&lt;br /&gt;
    - {allocate_size: &amp;quot;min&amp;quot;, id: &amp;quot;os&amp;quot;}&lt;br /&gt;
    - {allocate_size: &amp;quot;all&amp;quot;, id: &amp;quot;role_volume_name&amp;quot;}&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Previously, pre/post deployment tasks were kept only in tasks.yaml, which does not allow specification of tasks' dependencies. Now, we have a possibility to describe deployment tasks with tasks dependencies in the deployment_tasks.yaml file. The old tasks.yaml is still supported, however it is recommended to use the new deployment_tasks.yaml.&lt;br /&gt;
&lt;br /&gt;
Description of a new group in ‘deployment_tasks.yaml’:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;&lt;br /&gt;
- id: role-name&lt;br /&gt;
  type: group&lt;br /&gt;
  role: [role-name]&lt;br /&gt;
  requires: [controller]&lt;br /&gt;
  required_for: [deploy_end]&lt;br /&gt;
  parameters:&lt;br /&gt;
    strategy:&lt;br /&gt;
      type: parallel&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In metadata for a plugin’s role a developer can describe conflicts with other roles such as already present in ‘openstack.yaml’. Each plugin should describe the list of provided roles for proper name referencing.&lt;br /&gt;
&lt;br /&gt;
User can declare several new node roles in one plugin. It can be useful for tasks order and provide granular way for a plugin developer to build their own plugins on top of others.&lt;br /&gt;
&lt;br /&gt;
'''NOTE:'''&lt;br /&gt;
Plugins with old format also will be supported.&lt;br /&gt;
&lt;br /&gt;
'''NOTE:'''&lt;br /&gt;
The role '*' is supported for deployment tasks. Also a list of tasks' names can be specified in a role's field.&lt;br /&gt;
&lt;br /&gt;
=== Deployment ===&lt;br /&gt;
&lt;br /&gt;
After environment is created and configured, user starts a deployment. &lt;br /&gt;
Meanwhile, Nailgun gets the list of enabled plugins from the database. For each plugin from the list, Nailgun parses tasks.yaml file:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;&lt;br /&gt;
- role: ['controller']&lt;br /&gt;
  stage: post_deployment&lt;br /&gt;
  type: shell&lt;br /&gt;
  parameters:&lt;br /&gt;
    cmd: bash deploy.sh&lt;br /&gt;
    timeout: 42&lt;br /&gt;
- role: '*'&lt;br /&gt;
  stage: pre_deployment&lt;br /&gt;
  type: shell&lt;br /&gt;
  parameters:&lt;br /&gt;
    cmd: echo all &amp;gt; /tmp/plugin.all&lt;br /&gt;
    timeout: 42&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For example, we have a two-node environment deployed. A node has a Controller role with UID 7 and Compute role with UID 8. In this case, the task executor generates the following tasks:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;pre_deployment&amp;quot;: [&lt;br /&gt;
        {&lt;br /&gt;
            &amp;quot;uids&amp;quot;: [&amp;quot;8&amp;quot;, &amp;quot;7&amp;quot;],&lt;br /&gt;
            &amp;quot;parameters&amp;quot;: {&lt;br /&gt;
                &amp;quot;path&amp;quot;: &amp;quot;/etc/apt/sources.list.d/fuel_plugin_name-1.0.0.list&amp;quot;,&lt;br /&gt;
                &amp;quot;data&amp;quot;: &amp;quot;deb http://10.20.0.2:8080/plugins/&lt;br /&gt;
                fuel_plugin_name-1.0.0/repositories/ubuntu /&amp;quot;&lt;br /&gt;
            },&lt;br /&gt;
            &amp;quot;priority&amp;quot;: 100,&lt;br /&gt;
            &amp;quot;fail_on_error&amp;quot;: true,&lt;br /&gt;
            &amp;quot;type&amp;quot;: &amp;quot;upload_file&amp;quot;,&lt;br /&gt;
            &amp;quot;diagnostic_name&amp;quot;: &amp;quot;fuel_plugin_name-1.0.0&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        {&lt;br /&gt;
            &amp;quot;uids&amp;quot;: [&amp;quot;8&amp;quot;, &amp;quot;7&amp;quot;],&lt;br /&gt;
            &amp;quot;parameters&amp;quot;: {&lt;br /&gt;
                &amp;quot;src&amp;quot;: &amp;quot;rsync://10.20.0.2:/plugins/fuel_plugin_name-1.0.0/deployment_scripts/&amp;quot;,&lt;br /&gt;
                &amp;quot;dst&amp;quot;: &amp;quot;/etc/fuel/plugins/fuel_plugin_name-1.0.0/&amp;quot;&lt;br /&gt;
            },&lt;br /&gt;
            &amp;quot;priority&amp;quot;: 200,&lt;br /&gt;
            &amp;quot;fail_on_error&amp;quot;: true,&lt;br /&gt;
            &amp;quot;type&amp;quot;: &amp;quot;sync&amp;quot;,&lt;br /&gt;
            &amp;quot;diagnostic_name&amp;quot;: &amp;quot;fuel_plugin_name-1.0.0&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        {&lt;br /&gt;
            &amp;quot;uids&amp;quot;: [&amp;quot;8&amp;quot;, &amp;quot;7&amp;quot;],&lt;br /&gt;
            &amp;quot;parameters&amp;quot;: {&lt;br /&gt;
                &amp;quot;cmd&amp;quot;: &amp;quot;echo all &amp;gt; /tmp/plugin.all&amp;quot;,&lt;br /&gt;
                &amp;quot;cwd&amp;quot;: &amp;quot;/etc/fuel/plugins/fuel_plugin_name-1.0.0/&amp;quot;,&lt;br /&gt;
                &amp;quot;timeout&amp;quot;: 42&lt;br /&gt;
            },&lt;br /&gt;
            &amp;quot;priority&amp;quot;: 300,&lt;br /&gt;
            &amp;quot;fail_on_error&amp;quot;: true,&lt;br /&gt;
            &amp;quot;type&amp;quot;: &amp;quot;shell&amp;quot;,&lt;br /&gt;
            &amp;quot;diagnostic_name&amp;quot;: &amp;quot;fuel_plugin_name-1.0.0&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
    ],&lt;br /&gt;
    &amp;quot;post_deployment&amp;quot;: [&lt;br /&gt;
        {&lt;br /&gt;
            &amp;quot;uids&amp;quot;: [&amp;quot;7&amp;quot;],&lt;br /&gt;
            &amp;quot;parameters&amp;quot;: {&lt;br /&gt;
                &amp;quot;cmd&amp;quot;: &amp;quot;bash deploy.sh&amp;quot;,&lt;br /&gt;
                &amp;quot;cwd&amp;quot;: &amp;quot;/etc/fuel/plugins/fuel_plugin_name-1.0.0/&amp;quot;,&lt;br /&gt;
                &amp;quot;timeout&amp;quot;: 42&lt;br /&gt;
            },&lt;br /&gt;
            &amp;quot;priority&amp;quot;: 100,&lt;br /&gt;
            &amp;quot;fail_on_error&amp;quot;: true,&lt;br /&gt;
            &amp;quot;type&amp;quot;: &amp;quot;shell&amp;quot;,&lt;br /&gt;
            &amp;quot;diagnostic_name&amp;quot;: &amp;quot;fuel_plugin_name-1.0.0&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
    ],&lt;br /&gt;
    &amp;quot;deployment_info&amp;quot;: &amp;quot;&amp;lt;Here is regular deployment info&amp;gt;&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Task !! Comment&lt;br /&gt;
|-&lt;br /&gt;
| pre_deployment || 1st subtask: Generated automatically by Nailgun. Adds a new repository for the node. Repository's path is built according to the following template: &amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;http://{{master_ip}}:8080/plugins/{{plugin_name}}-{{plugin_version}}/{{repository_path}}&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt; Where:&lt;br /&gt;
* master_ip is an IP address of the Fuel Master node&lt;br /&gt;
* plugin_name is a plugin name&lt;br /&gt;
* plugin_version is the plugin version&lt;br /&gt;
* repository_path is a path for a specific release in metadata.yaml file. &lt;br /&gt;
&lt;br /&gt;
2nd subtask: Generated automatically by Nailgun.Using rsync, copies plugin deployment scripts on the target nodes. Path to these files is pretty similar to the repository path. The only difference is that the deployment scripts path is taken from deployment_scripts_path that is placed into metadata.yaml file. 3rd subtask: Initiated by user and taken from tasks.yaml file, converted to task executor format.&lt;br /&gt;
|-&lt;br /&gt;
| post_deployment ||Has only one task which is taken from tasks.yaml file; uids field contains a list of nodes on which user should run a particular task. In this example, tasks.yaml file has &amp;quot;role: ['controller']&amp;quot; and this role is assigned to controller&lt;br /&gt;
|-&lt;br /&gt;
| deployment_info || Contains configuration information, required for deployment and not related to plugins.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Bugs ==&lt;br /&gt;
&lt;br /&gt;
Once you have encountered a bug in a specific plugin, plugin development team should quickly learn about&lt;br /&gt;
that and start creating a fix or workaround.&lt;br /&gt;
&lt;br /&gt;
The Fuel Plugins Launchpad project uses a widely spread bug triage workflow.&lt;br /&gt;
It is based on reporting bugs, providing information for bug reports and working out the fix.&lt;br /&gt;
In terms of the triage process, we use '''Importance''' and '''Status''' to reflect progress on bug fixing.&lt;br /&gt;
&lt;br /&gt;
=== Importance criteria ===&lt;br /&gt;
&lt;br /&gt;
==== Development bugs ====&lt;br /&gt;
&lt;br /&gt;
* Critical = can't deploy anything and there's no trivial workaround; data loss; or security vulnerability&lt;br /&gt;
* High = specific hardware, configurations, or components are unusable and there's no workaround; or everything is broken but there's a workaround&lt;br /&gt;
* Medium = specific hardware, configurations, or components are working incorrectly; or is completely unusable but there's a workaround&lt;br /&gt;
* Low = minor feature is broken and can be fixed with a trivial workaround; or a cosmetic defect&lt;br /&gt;
* Wishlist = Not really a bug, but a suggested improvement&lt;br /&gt;
&lt;br /&gt;
==== Documentation bugs ====&lt;br /&gt;
* Critical = following the instructions from documentation can cause outage or data loss&lt;br /&gt;
* High = documentation includes information that is not true, or instructions that do not yield the advertised outcome&lt;br /&gt;
* Medium =  important information is missing from documentation (e.g. new feature description)&lt;br /&gt;
* Low = additional information would improve reader's understanding of a feature&lt;br /&gt;
* Wishlist = cosmetic formatting and grammar issues&lt;br /&gt;
&lt;br /&gt;
=== Status ===&lt;br /&gt;
&lt;br /&gt;
All bugs, both development and documentation can have the following statuses:&lt;br /&gt;
* '''New'''. When you find a bug, you should file it into [https://launchpad.net/fuel-plugins Fuel Plugins project] in Launchpad.&lt;br /&gt;
New is the default state assigned to the bug automatically when it was reported.&lt;br /&gt;
Make sure there is no bug already filed for the same issue (use advanced search  &lt;br /&gt;
filters at LaunchPad), then enter the details of your report. &lt;br /&gt;
&lt;br /&gt;
* '''Incomplete'''. The bug report is incomplete and needs more information before it can be triaged. &lt;br /&gt;
If you lack information to properly reproduce or assess the importance of the&lt;br /&gt;
bug, you should ask the original reporter for more information.&lt;br /&gt;
&lt;br /&gt;
* '''Confirmed'''. Someone besides the original reporter believes that this report describes a genuine&lt;br /&gt;
bug in enough detail that a developer could start to work on a fix.&lt;br /&gt;
The person must make sure that milestone, importance and assignee are &lt;br /&gt;
present and set properly. Still the bug could not be reproducible or confirmed as genuine.&lt;br /&gt;
&lt;br /&gt;
* '''Triaged (optional).''' The bug supervisor believes the bug report contains all information a developer &lt;br /&gt;
needs to start work on a fix. It is clear how to fix the bug and solution can be posted&lt;br /&gt;
in the comments. Sometimes the implementation of the fix will be straightforward and &lt;br /&gt;
you would jump directly to bugfixing, but in some other cases, you would just post your&lt;br /&gt;
complete debugging analysis and give someone else the opportunity of fixing the bug.&lt;br /&gt;
&lt;br /&gt;
* '''In progress'''. At this stage, a developer starts working on the fix. During that time, in order to avoid&lt;br /&gt;
duplicating the work, this status should be set immediately when developer starts the work on the issue. Note, that when the commit is created (with sending the first patch&lt;br /&gt;
set out to review) and Closes-Bug tag is put into the commit message, this status is&lt;br /&gt;
assigned to the bug automatically. If the developer was not specified manually, then&lt;br /&gt;
his/her name will appear in the bug report after sending out the first patch set for&lt;br /&gt;
review.&lt;br /&gt;
&lt;br /&gt;
* '''Fix committed'''. Once the change is reviewed, accepted, approved by Core Reviewer (with the&lt;br /&gt;
subsequent merge to the master branch), it will automatically move to Fix committed&lt;br /&gt;
status.&lt;br /&gt;
&lt;br /&gt;
* '''Fix released'''. Someone besides the assignee has verified that the issue does not manifest after the fix is applied.&lt;br /&gt;
The status is left for QA to mark bugs as verified after fix is merged to the master&lt;br /&gt;
branch.&lt;br /&gt;
&lt;br /&gt;
=== How to report a bug ===&lt;br /&gt;
&lt;br /&gt;
# Make sure you're registered at LaunchPad. If not, see the official [http://docs.openstack.org/infra/manual/developers.html OpenStack Developer's Guide].&lt;br /&gt;
# Report a bug in Launchpad in the Fuel Plugins project: enter https://launchpad.net/fuel-plugins.&lt;br /&gt;
# Click '''Report a bug''' link: &amp;lt;br/&amp;gt; [[File:Report-a-bug-lp.png]]&lt;br /&gt;
# Fill in Summary field for a bug. It is going to be the headline. The headline must cointain plugin name (for example, EMC Plugin) in square brackets. Please be descriptive but short and to the point:&lt;br /&gt;
#* Bad - &amp;quot;&amp;lt;plugin-name&amp;gt; doesn’t install&amp;quot;&lt;br /&gt;
#* Good - &amp;quot;&amp;lt;plugin name&amp;gt; fails to install in HA mode when “Neutron with VLANs” network is selected&amp;quot;&lt;br /&gt;
# Enter “Further information”. This is a bug description. Let's focus on every issue it has:&lt;br /&gt;
# Description of the environment. Provide enough relevant information:&lt;br /&gt;
#* Output of http://fuel-master-node:8000/api/version/&lt;br /&gt;
#* Operating System&lt;br /&gt;
#* Reference Architecture (HA / non-HA)&lt;br /&gt;
#* Network model (Nova-network, Neutron+VLAN, Neutron+GRE, etc.)&lt;br /&gt;
#* Related Projects installed (Savanna, Murano, Ceilometer)&lt;br /&gt;
# Steps to reproduce:&lt;br /&gt;
#* Bad: Run the deployment in HA configuration&lt;br /&gt;
#* Good:Install the Fuel Master node. Copy the plugin to the Fuel Master node and install it. Create a new cluster.&lt;br /&gt;
# Expected result:&lt;br /&gt;
#* Good: The plugin is deployed, up and running.&lt;br /&gt;
# Actual result:&lt;br /&gt;
#* Bad: Plugin fails to install.&lt;br /&gt;
#* Good: Plugin installation fails with the error message “xxx”. Please see the attached screenshot which shows the errors on “Logs” tab.&lt;br /&gt;
# Workaround:&lt;br /&gt;
#* Bad: Don’t use “Neutron with VLANs”&lt;br /&gt;
#* Good: Apply patch/Change configuration from x to y.&lt;br /&gt;
# Impact:&lt;br /&gt;
#* Bad: Needs to be fixed.&lt;br /&gt;
#* Good: Deployment cannot be completed, because customer requires us to implement a use case for Savanna and “Neutron with VLANs”. Changing configuration to “Neutron with GRE” is not as acceptable option here so this has to be addressed as soon as possible.&lt;br /&gt;
# Select visibility for the bug under “This bug contains information that is” field. Either leave it as “Public” by default.&lt;br /&gt;
# Add attachments under “Extra Options” section&lt;br /&gt;
# Logs&lt;br /&gt;
# Diagnostic snapshot&lt;br /&gt;
# Screenshots&lt;br /&gt;
# Add &amp;lt;plugin-name&amp;gt; tag.&lt;br /&gt;
# After everything is entered, select the “Submit bug report” button.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;'''Important note:'''&lt;br /&gt;
please, keep private bugs in internal bugtrackers.&lt;br /&gt;
Do not report any of those at LaunchPad.&lt;br /&gt;
&lt;br /&gt;
=== Common recommendations for bug triage workflow ===&lt;br /&gt;
&lt;br /&gt;
When triaging bugs, please take into consideration the following:&lt;br /&gt;
* Review all New bugs. Plugin development team is responsible for the review. To create a plugin’s team, follow [[Fuel/Plugins#How_to_create_plugin_development_team_in_Launchpad|How to create plugin development team in Launchpad]].&lt;br /&gt;
* Target each '''New''' bug to the release milestone under development and set the corresponding bug status.&lt;br /&gt;
* Consider changing the bug title to be more specific: replace generic statements like &amp;quot;deployment timeout exceeded&amp;quot; with description of the root cause (if identified) or symptoms that are unique for that bug. Feel free to use tags in the bug title and the report with creating new tags manually when required.&lt;br /&gt;
* Assuming all bugs reported in Fuel Plugins project are public, request the missing information, and set the bug status to Incomplete. Add a comment using the following template: ''We didn't receive required details in order to correctly troubleshoot the problem, so we are setting this bug into Incomplete state. Please provide the requested information and we will investigate this issue further.'' If you think it was set to Incomplete by mistake, please comment in the bug.&lt;br /&gt;
* If there is sufficient information on how to reproduce the bug and milestone, importance and assignee are properly set, set the status to '''Confirmed'''.&lt;br /&gt;
* If there is sufficient information to start implementing a fix, set the status to '''Triaged.'''&lt;br /&gt;
* If the root cause of the bug is identified, include it in the bug description.&lt;br /&gt;
* Review all '''Incomplete''' bugs.&lt;br /&gt;
* If an I'''ncomplete''' bug has new updates, use the same steps as described above for '''New''' bugs.&lt;br /&gt;
* If an '''Incomplete''' bug did not have any updates for 4 weeks, close it as '''Invalid'''. Add a comment using the following template: ''This bug was incomplete for more than 4 weeks. We cannot investigate it further so we are setting the status to Invalid. If you think it is not correct, please feel free to provide more information and reopen the bug, and we will look into it further''.&lt;br /&gt;
* During new release scoping, review all bugs targeted at that release milestone, make sure it is updated daily by the assignee (or bug reporter if the bug is not assigned to a person).&lt;br /&gt;
* Every status change of a bug should be accompanied by a comment explaining the reason why the change was made.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Bug report tags ====&lt;br /&gt;
&lt;br /&gt;
For tracking bugs better, please, use different tags:&lt;br /&gt;
* every plugin should have its own tag that has &amp;lt;plugin name&amp;gt;  format.&lt;br /&gt;
* every documentation issue should be marged as ''docs''.&lt;br /&gt;
&lt;br /&gt;
=== How to create plugin development team in Launchpad ===&lt;br /&gt;
&lt;br /&gt;
To make the bug tracking process for plugins as simple as possible, plugin developers should&lt;br /&gt;
create their own teams in Launchpad. Here are the step-by-step instructions:&lt;br /&gt;
&lt;br /&gt;
# Enter [https://launchpad.net Launchpad] site.&lt;br /&gt;
# Click '''Register a team''' link: &amp;lt;br/&amp;gt; [[File:Registerteam.png]]&lt;br /&gt;
# Fill in the fields. You should also provide the following links to the plugin repo, README.md file and Fuel Plugins Catalog: &amp;lt;br/&amp;gt; [[File:Fillin.png]]&lt;br /&gt;
# Select Membership policy: &amp;lt;br/&amp;gt; [[File:Membership-pol.png]]&lt;br /&gt;
# Click '''Create Team''' button to finish.&lt;br /&gt;
&lt;br /&gt;
For information on adding members and running your team, see the official [https://help.launchpad.net/Teams Launchpad] guidelines.&lt;br /&gt;
&lt;br /&gt;
== Tutorials ==&lt;br /&gt;
&lt;br /&gt;
=== How To: Build and install a plugin from source ===&lt;br /&gt;
&lt;br /&gt;
These instructions explain how to build a plugin package from the source repository. This is useful when you want to install a plugin's version that isn't available on the [https://software.mirantis.com/download-mirantis-openstack-fuel-plug-ins/ Fuel plugins catalog] yet.&lt;br /&gt;
&lt;br /&gt;
1. [[Fuel/Plugins#Preparing_an_environment_for_plugin_development|Install]] the ''fuel-plugin-builder'' script.&lt;br /&gt;
&lt;br /&gt;
2. Clone the plugin's repository.&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;git clone https://git.openstack.org/stackforge/fuel-plugin-neutron-fwaas&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
3. Go to the plugin's directory and switch to the desired Git branch or tag (optional).&lt;br /&gt;
&lt;br /&gt;
4. Build the plugin's package.&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;fpb --build ./fuel-plugin-neutron-fwaas&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
5. The resulting RPM package should be available in the current directory. Follow the rest of the installation procedure as described in the README.md file of the plugin.&lt;br /&gt;
&lt;br /&gt;
=== How To: Debug UI ===&lt;br /&gt;
&lt;br /&gt;
UI elements are described in environment_config.yaml file.&lt;br /&gt;
To check how your built plugin looks on the Fuel web UI, install and create an environment:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
1. Enter plugin directory&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;cd fuel_plugin_name&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2. Edit environment_config.yaml file&lt;br /&gt;
&lt;br /&gt;
3. Build a plugin&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;fpb --build &amp;lt;plugin_name&amp;gt;&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
4. Install plugin, use &amp;quot;--force&amp;quot; parameter to replace the plugin if you have it installed:&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;fuel plugins --install fuel_plugin_name-1.0.0.fp --force&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
5. Create new environment&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;fuel env --create --release 1 --name test&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
6. Check that UI correctly shows elements from environment_config.yaml file&lt;br /&gt;
&lt;br /&gt;
=== How To: Debug deployment ===&lt;br /&gt;
&lt;br /&gt;
To show how it works, let's create a simple plugin with an error in the deployment script.&lt;br /&gt;
&lt;br /&gt;
1. Create a plugin:&lt;br /&gt;
   &amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;fpb --create fuel_plugin_name&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2. Add an error in the default deployment script (fuel_plugin_name/deployment_scripts/deploy.sh):&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# It's a script which deploys your plugin&lt;br /&gt;
echo fuel_plugin_name &amp;gt; /tmp/fuel_plugin_name&lt;br /&gt;
# Non-zero exit code means, that a script executed with error&lt;br /&gt;
exit 1&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
3. If you do not want to run plugin build, but you want to check that plugin format is correct, you can use --check parameter with the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;fpb --check fuel_plugin_name&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
4. Build and install the plugin:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;fpb --build fuel_plugin_name/&lt;br /&gt;
fuel plugins --install fuel_plugin_name/fuel_plugin_name-1.0.0.fp&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
5. Use the Fuel web UI or CLI to create an environment:&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;fuel env create --name test --rel 1 --mode multinode --network-mode nova&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
6. Enable the plugin on Fuel web UI Settings tab and then add several nodes. The first node has Controller role, the second node has Cinder and Computes roles.&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;&lt;br /&gt;
fuel node set --node 1 --env 1 --role controller&lt;br /&gt;
fuel node set --node 2 --env 1 --role compute,cinder&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
7. Check that Nailgun generates correct configuration data that a user can set on Fuel web UI:&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;&lt;br /&gt;
fuel deployment --default --env 1&lt;br /&gt;
 cat deployment_1/controller_1.yaml&lt;br /&gt;
 ...&lt;br /&gt;
 fuel_plugin_name:&lt;br /&gt;
   fuel_plugin_name_text: Set default value&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
8. Now can see that the file for target node contains plugin data.&lt;br /&gt;
&lt;br /&gt;
'''NOTE:'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;&lt;br /&gt;
The command mentioned above is useful when you do not know how your configuration data from Fuel web UI Settings tab will look like in /etc/astute.yaml file on target nodes.&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
9. Perform provisioning without deployment for two nodes:&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;fuel --env 1 node --provision --node 1,2&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''NOTE:'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;&lt;br /&gt;
To reduce the time required for testing, make a snapshot after nodes are provisioned. Note that if you use virtual machines, make snapshots of your target nodes.&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
10. Now you can run deployment:&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;fuel --env 1 node --deploy --node 1,2&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
11. The deployment fails with the following message:&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;Deployment has failed. Method deploy. Failed to deploy plugin fuel_plugin_name-1.0.0 &amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
12. You can see an error in /var/log/docker-logs/astute/astute.log task executor logs:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;&lt;br /&gt;
[394] Shell command failed. Check debug output for details&lt;br /&gt;
[394] 13edd324-6a11-4342-bc04-66c659e75e35: cmd: bash deploy.sh&lt;br /&gt;
cwd: /etc/fuel/plugins/fuel_plugin_name-1.0.0/&lt;br /&gt;
stdout:&lt;br /&gt;
stderr:&lt;br /&gt;
exit code: 1&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
13. It fails due to the changes in deploy.sh script that you made in step 2. Let's assume that we do not know what happened and try to debug the problem:&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;&lt;br /&gt;
# Go to the first node&lt;br /&gt;
ssh node-1&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
14. All plugin deployment scripts are copied to the separate directory on the target node; in this case, it is /etc/fuel/plugins/fuel_plugin_name-1.0.0/:&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;&lt;br /&gt;
cd /etc/fuel/plugins/fuel_plugin_name-1.0.0/&lt;br /&gt;
# The directory contains our deploy.sh script, lets run it&lt;br /&gt;
bash deploy.sh&lt;br /&gt;
# And check exit code&lt;br /&gt;
echo $? # Returns 1&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''NOTE:'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;&lt;br /&gt;
If you use puppet for your plugin deployment, run the following command on the target node to check if your puppet manifests work correctly:&lt;br /&gt;
&lt;br /&gt;
puppet apply --debug --modulepath=/etc/fuel/plugins/fuel_plugin_name-1.0.0/puppet/modules:/etc/puppet/modules /etc/fuel/plugins/fuel_plugin_name-1.0.0/puppet/manifests/site.pp&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
15. Now we can see that deployment fails due to non-zero exit code error. To fix the problem and check that the proposed solution works, edit the /var/www/nailgun/plugins/fuel_plugin_name-1.0.0/deployment_scripts/deploy.sh script on the Fuel Master node. Note that there is no need to rebuild and reinstall a plugin:&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
&lt;br /&gt;
# It's a script which deploys your plugin&lt;br /&gt;
echo fuel_plugin_name &amp;gt; /tmp/fuel_plugin_name&lt;br /&gt;
&lt;br /&gt;
# Now our deployment script returns 0 instead of 1&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
16. If you run the deployment again, it goes successfully:&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;&lt;br /&gt;
fuel --env 1 node --deploy --node 1,2&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''WARNING:''' &lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;&lt;br /&gt;
During the testing of your deployment scripts, make sure that your scripts are idempotent: they should work correctly when applied several times. Run environment deployment at least twice and check that your plugin works properly. The reason for this workflow is the following: Fuel can run deployment of your plugin several times in case the first deployment try failed. Also, your deployment scripts can be executed during OpenStack patching.&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
17. To make sure that plugin works without errors, revert snapshots which you made in step 6, and run deployment again:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;&lt;br /&gt;
fuel --env 1 node --deploy --node 1,2&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
18. In the same way with no plugin reinstallation, you can edit /var/www/nailgun/plugins/&amp;lt;fuel_plugin_name&amp;gt;-1.0.0/tasks.yaml file. Note that in this case to make sure that your tasks have a valid format, you should at least run the following command:&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;&lt;br /&gt;
fpb --check /var/www/nailgun/plugins/fuel_plugin_name-1.0.0/&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Plugin elements in the Fuel web UI ==&lt;br /&gt;
&lt;br /&gt;
Here is an example of the environment_config.yaml file that contains all possible Fuel web UI elements:&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;&lt;br /&gt;
attributes:&lt;br /&gt;
&lt;br /&gt;
  # Text field&lt;br /&gt;
  fuel_plugin_name_text:&lt;br /&gt;
    type: &amp;quot;text&amp;quot;&lt;br /&gt;
    weight: 10&lt;br /&gt;
    value: &amp;quot;Default text&amp;quot;&lt;br /&gt;
    label: &amp;quot;Text field label&amp;quot;&lt;br /&gt;
    description: &amp;quot;Field description&amp;quot;&lt;br /&gt;
    regex:&lt;br /&gt;
      source: '\S'&lt;br /&gt;
      error: &amp;quot;Error field cannot be empty&amp;quot;&lt;br /&gt;
&lt;br /&gt;
 # Select&lt;br /&gt;
  fuel_plugin_name_select:&lt;br /&gt;
    type: &amp;quot;select&amp;quot;&lt;br /&gt;
    weight: 20&lt;br /&gt;
    value: &amp;quot;value2&amp;quot;&lt;br /&gt;
    label: &amp;quot;Select label&amp;quot;&lt;br /&gt;
    description: &amp;quot;Select description&amp;quot;&lt;br /&gt;
    values:&lt;br /&gt;
      - data: &amp;quot;value1&amp;quot;&lt;br /&gt;
        label: &amp;quot;Value 1 label&amp;quot;&lt;br /&gt;
      - data: &amp;quot;value2&amp;quot;&lt;br /&gt;
        label: &amp;quot;Value 2 label&amp;quot;&lt;br /&gt;
      - data: &amp;quot;value3&amp;quot;&lt;br /&gt;
        label: &amp;quot;Value 3 label&amp;quot;&lt;br /&gt;
&lt;br /&gt;
  # Checkbox&lt;br /&gt;
  fuel_plugin_name_checkbox:&lt;br /&gt;
    type: &amp;quot;checkbox&amp;quot;&lt;br /&gt;
    weight: 30&lt;br /&gt;
    value: false&lt;br /&gt;
    label: &amp;quot;Checkbox label&amp;quot;&lt;br /&gt;
    description: &amp;quot;Checkbox description&amp;quot;&lt;br /&gt;
&lt;br /&gt;
  # Radio button&lt;br /&gt;
  fuel_plugin_name_radio:&lt;br /&gt;
    type: &amp;quot;radio&amp;quot;&lt;br /&gt;
    weight: 40&lt;br /&gt;
    value: &amp;quot;disabled&amp;quot;&lt;br /&gt;
    label: &amp;quot;Radio buttons label&amp;quot;&lt;br /&gt;
    values:&lt;br /&gt;
      - data: &amp;quot;data1&amp;quot;&lt;br /&gt;
        label: &amp;quot;Label data1&amp;quot;&lt;br /&gt;
        description: &amp;quot;Description data1&amp;quot;&lt;br /&gt;
      - data: &amp;quot;data2&amp;quot;&lt;br /&gt;
        label: &amp;quot;Label data2&amp;quot;&lt;br /&gt;
        description: &amp;quot;Description data2&amp;quot;&lt;br /&gt;
      - data: &amp;quot;data3&amp;quot;&lt;br /&gt;
        label: &amp;quot;Label data3&amp;quot;&lt;br /&gt;
        description: &amp;quot;Description data3&amp;quot;&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After plugin is installed, additional elements will appear on the Settings tab of the Fuel web UI.&lt;br /&gt;
Here are UI elemens for Elasticsearch-Kibana plugin:&lt;br /&gt;
&lt;br /&gt;
[[File: Ui-elements.png]]&lt;br /&gt;
&lt;br /&gt;
== Puppet in Fuel ==&lt;br /&gt;
&lt;br /&gt;
Fuel does not use [https://docs.puppetlabs.com/learning/agent_master_basic.html#what-do-agents-do-and-what-do-masters-do master Puppet]. Task executor copies manifest from the Fuel Master node and runs puppet apply command on each target node.&lt;br /&gt;
It is recommended that you use puppet tasks in your plugin instead of running puppet in shell tasks.&lt;br /&gt;
Task executor has [https://github.com/stackforge/fuel-astute/blob/122cdaab/mcagents/puppetd.rb code with special logic] which handles errors, if puppet apply command returns zero/non-zero exit code. Note that it does not mean that command is succeed or failed. That means, it returns '2' if there were changes during the execution: task executor parses /var/lib/puppet/state/last_run_summary.yaml file to determine the status of puppet run.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== How to separate services from Controller with a plugin ==&lt;br /&gt;
&lt;br /&gt;
Starting with Fuel 7.0, you can create and implement a plugin that allows any role or task to be broken up into sections and deployed on a custom role. This includes the high availability feature enabling as well.&lt;br /&gt;
&lt;br /&gt;
Fuel includes a granular deployment framework that relies on a task based-deployment schema defining how each node role is deployed. To modify the granular deployment framework, you can create a plugin that inserts, overrides, or skips any given task. In addition, you can add any custom role that fulfils a task normally tied to the Controller role. Generally speaking, all Controller services are deployed on the Controller nodes directly.&lt;br /&gt;
&lt;br /&gt;
: '''Note:''' In the granular deployment, all dependencies are preserved when skipping a task. A custom role must deploy either before or after the Controller role. For example, you cannot deploy tasks A, B, C, and D on the Controller, pause it, deploy the custom ''MyRole'' role, then finish tasks E through Z on the Controller role. For this reason, it is best to deploy your plugin in a self-sufficient way that does not rely on controller services.&lt;br /&gt;
&lt;br /&gt;
If you want to change the deployment configuration, override the default setting using the '''Hiera''' tool.&lt;br /&gt;
&lt;br /&gt;
=== Hiera overview ===&lt;br /&gt;
&lt;br /&gt;
In spite of Puppet is static in configuration, it can customize deployment based on the metadata fed in from an external data source. In this case, Fuel uses Hiera to define node configuration. &lt;br /&gt;
&lt;br /&gt;
[http://docs.puppetlabs.com/hiera/ Hiera] is a key/value lookup tool for configuration data, but you can configure it to define the priority of the data sources.&lt;br /&gt;
&lt;br /&gt;
Configuration items are stored in 3 different data structures:&lt;br /&gt;
&lt;br /&gt;
* simple key/value,&lt;br /&gt;
* arrays,&lt;br /&gt;
* hashes.&lt;br /&gt;
&lt;br /&gt;
'''Examples:'''&lt;br /&gt;
&lt;br /&gt;
 Key/value&lt;br /&gt;
 role: “controller”&lt;br /&gt;
 primary_controller: true&amp;lt;br /&amp;gt;&lt;br /&gt;
 Array:&lt;br /&gt;
 amqp_hosts: [“192.168.0.3:5673”,”192.168.0.4:5673”,”192.168.0.5:5673”]&amp;lt;br /&amp;gt;&lt;br /&gt;
 Hash:&lt;br /&gt;
 mysql:&lt;br /&gt;
  root_password: “OvEuZFyt”&lt;br /&gt;
  wsrep_password: “Secr3t”&lt;br /&gt;
&lt;br /&gt;
Hiera also offers a hierarchy of configuration data. It has several layers of precedence in its hierarchy by default. The default ''/etc/hiera.yaml'' looks as follows:&lt;br /&gt;
&lt;br /&gt;
 ---&lt;br /&gt;
 :backends:&lt;br /&gt;
  - yaml&amp;lt;br /&amp;gt;&lt;br /&gt;
 :hierarchy:&lt;br /&gt;
  - override/node/%{::fqdn}&lt;br /&gt;
  - override/class/%{calling_class}&lt;br /&gt;
  - override/module/%{calling_module}&lt;br /&gt;
  - override/plugins&lt;br /&gt;
  - override/common&lt;br /&gt;
  - class/%{calling_class}&lt;br /&gt;
  - module/%{calling_module}&lt;br /&gt;
  - nodes&lt;br /&gt;
  - globals&lt;br /&gt;
  - astute&amp;lt;br /&amp;gt;&lt;br /&gt;
 :yaml:&lt;br /&gt;
  :datadir: /etc/hiera&lt;br /&gt;
 :merge_behavior: deeper&lt;br /&gt;
 :logger: noop&lt;br /&gt;
&lt;br /&gt;
Any values defined in ''/etc/hiera/globals.yaml'' takes precedence over values defined in ''/etc/hiera/astute.yaml''. The same is true for any value defined higher up. If a plugin defines a new YAML file and inserts itself in the hierarchy, it can override a given value as well.&lt;br /&gt;
&lt;br /&gt;
Queries to hiera come in three forms:&lt;br /&gt;
&lt;br /&gt;
* priority,&lt;br /&gt;
* array merge,&lt;br /&gt;
* hash merge.&lt;br /&gt;
&lt;br /&gt;
The defined values can either override or be merged with other values. As an example, you can either merge the array of ''memcache_roles'' from ''astute.yaml'' and a custom plugin YAML or take the highest priority. The difference is in how puppet calls it:&lt;br /&gt;
 Merged lookup:&lt;br /&gt;
     hiera_array(‘memcache_roles’)&lt;br /&gt;
 Priority lookup:&lt;br /&gt;
     hiera(‘memcache_roles’)&lt;br /&gt;
&lt;br /&gt;
In most cases, array lookups should be done with a priority lookup. In contrast, hash lookups in Hiera should always be done using the &amp;lt;code&amp;gt;hiera_hash&amp;lt;/code&amp;gt; function.&lt;br /&gt;
&lt;br /&gt;
'''Example:'''&lt;br /&gt;
&lt;br /&gt;
 astute.yaml contains:&lt;br /&gt;
 mysql:&lt;br /&gt;
  root_password: “OvEuZFyt”&lt;br /&gt;
  wsrep_password: “Secr3t”&lt;br /&gt;
 plugins.yaml contains:&lt;br /&gt;
     mysql:&lt;br /&gt;
       enabled: false&lt;br /&gt;
&lt;br /&gt;
The results are vastly different if you do a priority lookup versus a hash lookup:&lt;br /&gt;
&lt;br /&gt;
 Priority lookup:&lt;br /&gt;
     $ hiera mysql&lt;br /&gt;
     {“enabled”=&amp;gt;false}&lt;br /&gt;
 Hash lookup:&lt;br /&gt;
     $ hiera -h mysql&lt;br /&gt;
     {“enabled”=&amp;gt;false,“root_password”=&amp;gt;“OvEuZFyt”,”wsrep_password”=&amp;gt;“Secr3t”}&lt;br /&gt;
&lt;br /&gt;
Hash merging in Hiera allows a plugin developer to tweak an individual setting in the configuration without duplicating all of the other values in a hash. &lt;br /&gt;
&lt;br /&gt;
==== How a plugin can use Hiera ====&lt;br /&gt;
&lt;br /&gt;
A plugin can modify any Hiera configuration data for a deployment to inform existing tasks how to deploy. For example, if you want to run ''memcached'' on a separate ''my-role'' role , you can override the ''memcache_roles'' array to say ''my-role'' instead of ''primary-controller, controller''.&lt;br /&gt;
&lt;br /&gt;
=== Deploying services into separate nodes ===&lt;br /&gt;
&lt;br /&gt;
Rabbit and MySQL can be easily turned off on the Controller role by overriding the metadata in Hiera, as described above. This can be accomplished by disabling a service inside its respective service hash, indicated by a value ''enabled: false''. However, some services such as Keystone is not so simple and require more configuration. For the specific details proceed with the sections below. &lt;br /&gt;
&lt;br /&gt;
==== Defining a custom role in a plugin ====&lt;br /&gt;
&lt;br /&gt;
If you want to deploy separate services on a different node from the Controller, you need to define a custom role first. &lt;br /&gt;
&lt;br /&gt;
To define custom node roles in a plugin, fill out the ''node_roles.yaml'' file in your plugin’s base directory. A custom role that replaces an existing task must contain some particular fields to achieve this objective.&lt;br /&gt;
&lt;br /&gt;
In addition to the default attributes, you need to include the following attributes in the plugin:&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;code&amp;gt;update_required&amp;lt;/code&amp;gt;&lt;br /&gt;
: Corosync hosts, memcached hosts, and AMQP hosts are enumerated explicitly in configuration. All existing nodes for the specified roles will be refreshed before adding/removing a given node. This list should include all consumers of the service you are deploying.&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;code&amp;gt;public_ip_required&amp;lt;/code&amp;gt;&lt;br /&gt;
: Internal-only services (like RabbitMQ) should not have a public IP.&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;code&amp;gt;has_primary&amp;lt;/code&amp;gt;&lt;br /&gt;
: Required for any deployment that includes corosync.&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;code&amp;gt;conflicts&amp;lt;/code&amp;gt;&lt;br /&gt;
: Roles containing sensitive data should not be combined with Compute. In our example, we also conflict with the Controller role because it could break if there is not a 1:1 mapping of controller and ''custom_role'' roles to all other nodes.&lt;br /&gt;
&lt;br /&gt;
'''See Also:'''&lt;br /&gt;
&lt;br /&gt;
* [https://wiki.openstack.org/wiki/Fuel/Plugins#Configuration_of_Fuel_Plugins_with_new_roles custom node roles details]&lt;br /&gt;
* [https://github.com/stackforge/fuel-plugin-detach-database/blob/master/node_roles.yaml node_roles.yaml example]&lt;br /&gt;
&lt;br /&gt;
==== Configuring Hiera ====&lt;br /&gt;
&lt;br /&gt;
===== Database separation =====&lt;br /&gt;
&lt;br /&gt;
Database separation is intended to be as flexible as possible for various deployment configurations including remote database creation, user creation, and different database servers for different services.&lt;br /&gt;
&lt;br /&gt;
The list of the parameters configurable for MySQL and its metadata is as follows:&lt;br /&gt;
* MySQL root password (default is auto-generated)&lt;br /&gt;
* db_host or Database VIP&lt;br /&gt;
* db_create (defaults to true)&lt;br /&gt;
* db_user (defaults to service name)&lt;br /&gt;
* db_password (defaults to auto-generated value)&lt;br /&gt;
&lt;br /&gt;
Additionally, for the MySQL hash on the Controller roles, you need to set mysql to ''enabled: false''.&lt;br /&gt;
&lt;br /&gt;
===== Adding in HA =====&lt;br /&gt;
&lt;br /&gt;
High availability is key to any production deployment. Each service has HA configured through corosync or haproxy.&lt;br /&gt;
&lt;br /&gt;
The following services are managed by corosync:&lt;br /&gt;
&lt;br /&gt;
* Virtual IP addresses&lt;br /&gt;
* haproxy&lt;br /&gt;
* MySQL/Galera&lt;br /&gt;
* RabbitMQ&lt;br /&gt;
* Heat&lt;br /&gt;
* Neutron agents&lt;br /&gt;
&lt;br /&gt;
This means that you need to include one or more of the following tasks in your custom role:&lt;br /&gt;
&lt;br /&gt;
* cluster&lt;br /&gt;
* cluster-haproxy&lt;br /&gt;
* virtual_ips&lt;br /&gt;
* openstack-haproxy-SERVICENAME&lt;br /&gt;
&lt;br /&gt;
: '''Note:''' Since RabbitMQ only requires corosync and not haproxy or a virtual IP, it only requires the cluster task for high availability. On the other hand, MySQL and Keystone would require all four of these.&lt;br /&gt;
&lt;br /&gt;
The metadata requirements for corosync and haproxy are prepared to accept custom values through Hiera. For corosync itself, you need one key value that is ''corosync_roles''. This is necessary because UDP configuration of Corosync requires all nodes to explicitly allow communication with each other. The value should equal the role name for your plugin as follows:&lt;br /&gt;
&lt;br /&gt;
 corosync_roles:&lt;br /&gt;
   - primary-standalone-keystone&lt;br /&gt;
   - standalone-keystone&lt;br /&gt;
&lt;br /&gt;
: '''Note:''' This should only apply when evaluating your custom role. Refer to the [https://github.com/stackforge/fuel-plugin-detach-keystone/blob/master/deployment_scripts/hiera-override.pp#L54-L65 detach-keystone plugin] as an example.&lt;br /&gt;
&lt;br /&gt;
If the service you want to detach requires HAProxy, include the following arrays to your plugin:&lt;br /&gt;
* servicename_nodes&lt;br /&gt;
* servicename_ipaddresses&lt;br /&gt;
* servicename_nodes_names&lt;br /&gt;
&lt;br /&gt;
See [https://github.com/stackforge/fuel-plugin-detach-keystone/blob/master/deployment_scripts/hiera-override.pp#L45-L52 detach-keystone plugin] as an example.&lt;br /&gt;
&lt;br /&gt;
If the service being separated requires memcached, specify ''memcache_roles'' in your override hiera YAML. This is necessary if your role is evaluated before the Controller role. However, in case your role is deployed after the Controller role, you can use memcached from the Controller role leaving this value unchanged.&lt;br /&gt;
&lt;br /&gt;
===== RabbitMQ separation =====&lt;br /&gt;
&lt;br /&gt;
Configure Hiera as follows:&lt;br /&gt;
&lt;br /&gt;
# Set the ''amqp_hosts'' array on all nodes. Since the original list of hosts is generated in the globals task of the granular deployment, you need to override this value without merging. As there is no virtual IP to manage, it is the only value to control.&lt;br /&gt;
# Set ''rabbit_hash'' to ''enabled: false'' for the Controller roles.&lt;br /&gt;
&lt;br /&gt;
===== Keystone separation =====&lt;br /&gt;
&lt;br /&gt;
To meet a specific use case, decoupling the Keystone service from the Controller role, proceed with the following steps:&lt;br /&gt;
&lt;br /&gt;
: 1. On the Controller node, view the task list for a created environment:&lt;br /&gt;
&lt;br /&gt;
 fuel graph --env 1 --download&lt;br /&gt;
&lt;br /&gt;
The tasks we are concerned with for keystone are:&lt;br /&gt;
&lt;br /&gt;
; ''keystone''&lt;br /&gt;
: creates the keystone service&lt;br /&gt;
&lt;br /&gt;
; ''keystone-db''&lt;br /&gt;
: prepares the DB for keystone&lt;br /&gt;
&lt;br /&gt;
; ''openstack-haproxy-keystone''&lt;br /&gt;
: enables haproxy for keystone&lt;br /&gt;
&lt;br /&gt;
; ''disable_keystone_service_token''&lt;br /&gt;
: cleanup task for ''admin_token''&lt;br /&gt;
&lt;br /&gt;
: 2. Shift the tasks listed above to a custom keystone role (it is the “standalone-keystone” role in our example):&lt;br /&gt;
&lt;br /&gt;
* Disable original keystone tasks creating a YAML file called ''deployment_tasks.yaml'' and defining new tasks with the type &amp;lt;code&amp;gt;skipped&amp;lt;/code&amp;gt; preventing these tasks from running on the Controller role:&lt;br /&gt;
&lt;br /&gt;
 id: original_task_name&lt;br /&gt;
 type: skipped&lt;br /&gt;
&lt;br /&gt;
* Create a new task that reproduces the original one, but replace the requirements and role for the original task:&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Original task'''&lt;br /&gt;
&lt;br /&gt;
 - id: keystone-db&lt;br /&gt;
  type: puppet&lt;br /&gt;
  groups: [primary-controller]&lt;br /&gt;
  required_for: [keystone]&lt;br /&gt;
  requires: [database]&lt;br /&gt;
  parameters:&lt;br /&gt;
     puppet_manifest: /etc/puppet/modules/osnailyfacter/modular/keystone/db.pp&lt;br /&gt;
     puppet_modules: /etc/puppet/modules&lt;br /&gt;
     timeout: 1800&lt;br /&gt;
&lt;br /&gt;
'''New tasks'''&lt;br /&gt;
&lt;br /&gt;
 - id: keystone-db&lt;br /&gt;
  type: skipped&amp;lt;br /&amp;gt;&lt;br /&gt;
 - id: task-keystone-db&lt;br /&gt;
  type: puppet&lt;br /&gt;
  role: [primary-standalone-keystone, standalone-keystone]&lt;br /&gt;
  required_for: [task-keystone]&lt;br /&gt;
  requires: [deploy_start, keystone-hiera-override, netconfig]&lt;br /&gt;
  parameters:&lt;br /&gt;
     puppet_manifest: /etc/puppet/modules/osnailyfacter/modular/keystone/db.pp&lt;br /&gt;
     puppet_modules: /etc/puppet/modules&lt;br /&gt;
     timeout: 1800&lt;br /&gt;
&lt;br /&gt;
: 3. Ensure all new tasks depend on each other.&lt;br /&gt;
&lt;br /&gt;
For each new task you create, ensure its dependencies line up with the tasks you marked as skipped. In the example above, ''task-keystone-db'' is a dependent task for ''task-keystone'', which is another custom task that performs the same function.&lt;br /&gt;
&lt;br /&gt;
'''See also:'''&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/stackforge/fuel-plugin-detach-keystone/blob/master/deployment_tasks.yaml#L60 deployment_tasks.yaml sample]&lt;br /&gt;
&lt;br /&gt;
==== Verifying changes ====&lt;br /&gt;
&lt;br /&gt;
# Create an environment to test your task graph with 1 Controller node and 1 node with your custom role.&lt;br /&gt;
# Run &amp;lt;code&amp;gt;fuel plugins --sync&amp;lt;/code&amp;gt;&lt;br /&gt;
# Run  &amp;lt;code&amp;gt;fuel graph --env 1 --download&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If successful, these should run without errors.&lt;br /&gt;
If there is a syntax mistake, it returns a 500 error. For the proper YAML syntax, see the [https://github.com/stackforge/fuel-plugins example plugins].&lt;br /&gt;
&lt;br /&gt;
=== Procedures and limitations ===&lt;br /&gt;
&lt;br /&gt;
==== Procedure for RabbitMQ ====&lt;br /&gt;
&lt;br /&gt;
# Create a new custom role.&lt;br /&gt;
# Enable corosync (for HA).&lt;br /&gt;
# Override the ''amqp_hosts'' array on all hosts that consume AMQP.&lt;br /&gt;
# Disable rabbitmq on the Controller role.&lt;br /&gt;
&lt;br /&gt;
==== Procedure for Galera ==== &lt;br /&gt;
&lt;br /&gt;
# Create a new custom role.&lt;br /&gt;
# Enable corosync (for HA).&lt;br /&gt;
# Override mysql hash: enable it for the custom role, disable it for the Controller role.&lt;br /&gt;
# Provide ''database_vip'' and ''haproxy'' for your role.&lt;br /&gt;
&lt;br /&gt;
==== Procedure for Keystone ====&lt;br /&gt;
&lt;br /&gt;
# Disable Keystone base task, haproxy task, and DB task on the Controller node.&lt;br /&gt;
# Create a new custom role.&lt;br /&gt;
# Add ''service_endpoint'' and ''public_service_endpoint'' VIPs in the custom role.&lt;br /&gt;
# Enable corosync (for the VIP, but keystone itself is stateless).&lt;br /&gt;
# Enable memcached.&lt;br /&gt;
# Enable dependency on database plugin.&lt;br /&gt;
# For SSL deployments, enable haproxy for Keystone on public VIP&lt;br /&gt;
&lt;br /&gt;
====  Limitations for Keystone separation ====&lt;br /&gt;
&lt;br /&gt;
* Keystone cannot run without MySQL and memcached.&lt;br /&gt;
* The Controller role provides these roles, but you cannot do a partial Controller deployment, stop, deploy keystone, and continue.&lt;br /&gt;
* Keystone public SSL is limited to one hostname.&lt;br /&gt;
&lt;br /&gt;
=== Useful links ===&lt;br /&gt;
&lt;br /&gt;
* Examples of plugins:&lt;br /&gt;
** [https://github.com/stackforge/fuel-plugin-detach-database detach-database plugin]&lt;br /&gt;
** [https://github.com/stackforge/fuel-plugin-detach-rabbitmq detach-rabbitmq plugin]&lt;br /&gt;
** [https://github.com/stackforge/fuel-plugin-detach-keystone detach-keystone plugin]&lt;br /&gt;
&lt;br /&gt;
* [http://docs.puppetlabs.com/hiera/1/ Hiera]&lt;br /&gt;
&lt;br /&gt;
* [https://wiki.openstack.org/wiki/Fuel/Plugins#Virtual_IP_reservation_via_Fuel_Plugin.27s_metadata VIP reservation in plugin]&lt;br /&gt;
&lt;br /&gt;
* [https://wiki.openstack.org/wiki/Fuel/Plugins#Configuration_of_Fuel_Plugins_with_new_roles Role definition in plugin]&lt;br /&gt;
&lt;br /&gt;
== Creating documentation for Fuel Plugins ==&lt;br /&gt;
&lt;br /&gt;
Fuel Plugins can provide brand different functionality, that's why you should not only develop a plugin itself,&lt;br /&gt;
but also write documentation clear to end users.&lt;br /&gt;
&lt;br /&gt;
=== Documentation package ===&lt;br /&gt;
&lt;br /&gt;
To give all users the understanding of what you plugins does and how it was tested,&lt;br /&gt;
you need to have the following files in the plugin's repo '''under /doc folder''':&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
* Test Plan - contains information on planned testing activities&lt;br /&gt;
* Test Report - contains information obtained during testing&lt;br /&gt;
* Plugin Guide - contains installation, configuration and usage instructions.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
Please, note that your plugin's repo should also contain:&lt;br /&gt;
* LICENSE file with license specified correctly.&lt;br /&gt;
* copyright for specific repo files added at the file header. For details, see [[Fuel/Plugins#License_and_copyright|the corresponding section]].&lt;br /&gt;
* README file with instructions on how to build your plugin, see [https://github.com/stackforge/fuel-plugin-contrail/blob/master/README.md the examples here].&lt;br /&gt;
* developer's specification - contains design and implementation details and explains which problem can be solved with the plugin. It is put into '''/specs''' folder.&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
When writing, please take [[Fuel/Plugins#Style_recommendations|style recommendations]] into consideration.&lt;br /&gt;
&lt;br /&gt;
=== Following Gerrit workflow ===&lt;br /&gt;
&lt;br /&gt;
[http://docs.openstack.org/infra/manual/developers.html Gerrit workflow] provides the following advantages for Fuel Plugin documentation:&lt;br /&gt;
* aligns development and documentation writing cycles.&lt;br /&gt;
* provides shipping both specific plugin and related documentation at once.&lt;br /&gt;
* provides writing in RST (as already works for the specs).&lt;br /&gt;
* enables flexible updates for developers.&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Documentation files structure and Sphinx usage ====&lt;br /&gt;
&lt;br /&gt;
To simplify the build procedure, you can use Sphinx.&lt;br /&gt;
&lt;br /&gt;
To enable it in your plugin's repo, follow these steps:&lt;br /&gt;
# Make sure you've got a '''/doc''' folder in your repo (according to diagram below).&lt;br /&gt;
# Consider splitting your Plugin Guide into smaller RST pieces. Sample can be found [https://github.com/openstack/fuel-plugin-openbook/tree/7.0/doc here].&lt;br /&gt;
# Check if you have '''index''' file in place. It will serve as the source to build the document. It also needs to be edited to include the RST pieces (check the sample).&lt;br /&gt;
# Add a Makefile using the sample. Makefiles are usually left as-is to enable PDF and html build (check the [https://github.com/openstack/fuel-plugin-openbook/blob/7.0/doc/source/conf.py sample]).&lt;br /&gt;
# Edit [https://github.com/openstack/fuel-plugin-openbook/blob/7.0/doc/source/conf.py '''conf.py'''] file. This file is in charge of the document's appearance and you can modify it according to your own needs:&lt;br /&gt;
#* [https://github.com/openstack/fuel-plugin-openbook/blob/7.0/doc/source/conf.py#L267 Enable page numbering] in a proper manner.&lt;br /&gt;
#* [https://github.com/openstack/fuel-plugin-openbook/blob/7.0/doc/source/conf.py#L226 Get rid of blank pages] before and after contents page.&lt;br /&gt;
# Commit your change.&lt;br /&gt;
# Try getting into '''/doc''' folder and running 'make latexpdf' out of it.&lt;br /&gt;
As the deliverable of this exercise, you should get a PDF version of your document in the /build folder.&lt;br /&gt;
&lt;br /&gt;
Please, see the recommended file structure for Plugin Guide (as sample):&lt;br /&gt;
[[File: Doc-scheme-repo.png]]&lt;br /&gt;
&lt;br /&gt;
=== Style recommendations ===&lt;br /&gt;
&lt;br /&gt;
# Spell out acronyms and abbreviations when they are first used and avoid using abbreviations that are ambiguous. For example, &amp;quot;OS&amp;quot; could mean either &amp;quot;Operating System&amp;quot; or &amp;quot;OpenStack&amp;quot;.&lt;br /&gt;
# Do not add many links to external resources in main sections. It is recommended that you put them into Appendix section.&lt;br /&gt;
# Each link should have a brief description.Be sure to define any complex concepts and terms that are required to install/use/test the plugin.&lt;br /&gt;
# Use step-by-step instructions, structured with an introductory sentence followed by a numbered list of steps to take.&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Acceptance criteria ===&lt;br /&gt;
&lt;br /&gt;
Plugin-related documentation (Test Plan, Test Report, Plugin Guide, specification) should meet the following acceptance criteria:&amp;lt;br&amp;gt;&lt;br /&gt;
* the documentation is written in RST and put into the plugin's repo&lt;br /&gt;
* the plugin version is specified correctly;it must resemble the one reflected in the plugin's metadata.yaml file&lt;br /&gt;
* all links to external documentation/resources should be present and put into Appendix&lt;br /&gt;
* all complex concepts are explained in a detailed and clear manner&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
Please, mind some specific recommendations for the following documentation:&lt;br /&gt;
# '''Plugin Guide''' should contain 2 main sections for installation and usage.&lt;br /&gt;
#* The former should focus on 1) how/where to download a plugin 2) how to install a plugin 3) any additional prerequisite procedures (e.g. backend configuration).&lt;br /&gt;
#* The latter should cover 1) how to use the plugin (e.g. a set of commands) with an example (commands usage with specific values is strongly required) 2) links to external documentation.&lt;br /&gt;
#* If plugin has its own UI or supposes some actions to take in Horizon, the Plugin Guide must have screenshots with clearly seen UI elements.&lt;br /&gt;
# '''Test Plan and Test Report''' must have clearly specified prerequisites to make the plugin up and running.&lt;br /&gt;
# '''Plugin's specification''' must cover design and implementation peculiarities. See the [https://github.com/stackforge/fuel-specs/blob/master/specs/template.rst template].&lt;br /&gt;
&lt;br /&gt;
==== Checklist ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Issue !! Tick if done&lt;br /&gt;
|-&lt;br /&gt;
| Plugin version is the one specified in the plugin's metadata.yaml file (see [https://github.com/stackforge/fuel-plugin-neutron-vpnaas/blob/master/metadata.yaml#L6 the example]). || &lt;br /&gt;
|-&lt;br /&gt;
| All key terms/acronyms/abbreviations are put into the corresponding table and clearly explained or at least refer to other resources with detailed description. || &lt;br /&gt;
|-&lt;br /&gt;
| Plugin name doesn't somehow change within the document (like VPNaaS and vpnaas). Stick to one variant and use it along the text.|| &lt;br /&gt;
|-&lt;br /&gt;
| If configuration of specific components (if any) is not covered within the document, then there must be a link pointing to the detailed step-by-step instructions.|| &lt;br /&gt;
|-&lt;br /&gt;
| All UI elements are properly seen in the screenshots and or even highlighted to point at a specific action/element. || &lt;br /&gt;
|-&lt;br /&gt;
| All instructions are put into numbered lists to track the task accomplishment and navigate along the document. || &lt;br /&gt;
|-&lt;br /&gt;
| All instructions concerning Fuel UI wizard or Fuel web UI refer to the official documentation. || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Add your plugin to DriverLog ==&lt;br /&gt;
&lt;br /&gt;
Once you plugin is ready, you can add it to DriverLog, following instructions from [[DriverLog#How_To:_Add_a_new_Fuel_Plugin_to_DriverLog|DriverLog wiki page]].&lt;br /&gt;
Before adding, please make sure that:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Issue !! Example !! Tick if done&lt;br /&gt;
|-&lt;br /&gt;
| [[Fuel/Plugins#Acceptance_criteria|Plugin's documentation is added to /doc folder.]] || [https://github.com/stackforge/fuel-plugin-midonet/tree/master/doc Midonet plugin]  || &lt;br /&gt;
|-&lt;br /&gt;
| [[Fuel/Plugins#Documentation_files_structure|Plugin's specification is added to /specs folder]]. || [https://github.com/stackforge/fuel-plugin-solidfire-cinder/blob/master/specs/solidfire-plugin-specs.rst Solidfire plugin]  ||&lt;br /&gt;
|-&lt;br /&gt;
| [[Fuel/Plugins#Creating_documentation_for_Fuel_Plugins|Plugin's README file contains instructions on how to build the plugin.]] || [https://github.com/stackforge/fuel-plugin-contrail/blob/master/README.md Contrail plugin] ||&lt;br /&gt;
|-&lt;br /&gt;
| [[Fuel/Plugins#License_and_copyright|Plugin's LICENSE file contains the relevant license.]] || [https://github.com/stackforge/fuel-plugin-swiftstack/blob/master/LICENSE Swiftstack plugin] ||&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== License and copyright ==&lt;br /&gt;
&lt;br /&gt;
Fuel Plugins are licensed under [https://www.apache.org/licenses/LICENSE-2.0 Apache 2.0].&lt;br /&gt;
&amp;lt;br/&amp;gt;The plugin's repo should contain the following:&lt;br /&gt;
* the license as a separate file (LICENSE) - please, use [http://www.apache.org/licenses/LICENSE-2.0 the official license text].&lt;br /&gt;
* all files in the repository (except for configuration files and README) must have a copyright, see [https://github.com/stackforge/fuel-library/blob/e64d5408c0274950fd88e37bfbd94991941bbe4d/deployment/puppet/cobbler/manifests/profile/centos63_x86_64.pp#L1 fuel-library repo].&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
Note, that configuration files can have the following format:&amp;lt;br/&amp;gt;&lt;br /&gt;
* yaml (see [https://github.com/stackforge/fuel-plugin-contrail/blob/master/metadata.yaml the example]).&lt;br /&gt;
* erb (see [https://github.com/stackforge/fuel-plugin-contrail/blob/master/deployment_scripts/puppet/modules/contrail/templates/094-web_for_contrail.cfg.erb the example]).&lt;br /&gt;
* lua  (see [https://github.com/stackforge/fuel-plugin-lma-collector/blob/master/deployment_scripts/puppet/modules/lma_collector/files/plugins/common/patterns.lua the example]).&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
The Fuel Plugins can have extra components included.&lt;br /&gt;
To provide users with this information, make sure that the Plugin Guide has a separate section with the following table:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Component !! License&lt;br /&gt;
|-&lt;br /&gt;
| Component1 || License1&lt;br /&gt;
|-&lt;br /&gt;
| Component2|| License2&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== FAQ ==&lt;br /&gt;
&lt;br /&gt;
'''''Where can I find Fuel Plugin Builder source code?'''''&lt;br /&gt;
&lt;br /&gt;
fuel-plugin-builder is located in fuel-plugins repository.&lt;br /&gt;
&lt;br /&gt;
'''''Are there any plugins examples?'''''&lt;br /&gt;
&lt;br /&gt;
All plugins for Fuel now have their own repos under Stackforge project.&lt;br /&gt;
&lt;br /&gt;
'''''How can I reuse Puppet modules from Fuel?'''''&lt;br /&gt;
According to the design, every plugin should have all necessary components to be then deployed. This means, every plugin should have its own copy of Fuel Puppet modules. If you do not want to keep copy of Fuel library manifests in your repository, you can use pre_build_hook to download the required modules during the plugin build. To do that, add the following code into your hook:&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
set -eux&lt;br /&gt;
ROOT=&amp;quot;$(dirname `readlink -f $0`)&amp;quot;&lt;br /&gt;
MODULES=&amp;quot;${ROOT}&amp;quot;/deployment_scripts/puppet/modules&lt;br /&gt;
mkdir -p &amp;quot;${MODULES}&amp;quot;&lt;br /&gt;
REPO_PATH='https://github.com/stackforge/fuel-library/tarball/f43d885914d74fbd062096763222f350f47480e1'&lt;br /&gt;
RPM_REPO=&amp;quot;${ROOT}&amp;quot;/repositories/centos/&lt;br /&gt;
DEB_REPO=&amp;quot;${ROOT}&amp;quot;/repositories/ubuntu/&lt;br /&gt;
&lt;br /&gt;
wget -qO- &amp;quot;${REPO_PATH}&amp;quot; | \&lt;br /&gt;
    tar -C &amp;quot;${MODULES}&amp;quot; --strip-components=3 -zxvf - \&lt;br /&gt;
    stackforge-fuel-library-f43d885/deployment/puppet/{inifile,stdlib}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The code then copies inifile and stdlib modules from fuel-library repository.&lt;br /&gt;
&lt;br /&gt;
'''WARNING'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;&lt;br /&gt;
To reuse existing Puppet manifests you can also specify several Puppet modules in your task with colon separator: for example, puppet_modules: &amp;quot;puppet/modules:/etc/puppet/modules&amp;quot;. Note that we do not recommend using this approach, because Fuel puppet modules can be changed during OpenStack update procedure; this can lead to compatibility failures.&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''''How can I download the packages which are required for a plugin?'''''&lt;br /&gt;
Use wget in your pre_build_hook script to download packages in the required directories:&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
set -eux&lt;br /&gt;
&lt;br /&gt;
ROOT=&amp;quot;$(dirname `readlink -f $0`)&amp;quot;&lt;br /&gt;
RPM_REPO=&amp;quot;${ROOT}&amp;quot;/repositories/centos/&lt;br /&gt;
DEB_REPO=&amp;quot;${ROOT}&amp;quot;/repositories/ubuntu/&lt;br /&gt;
&lt;br /&gt;
wget -P &amp;quot;${RPM_REPO}&amp;quot; http://mirror.fuel-infra.org/fuel-plugins/6.0/centos/glusterfs-3.5.2-1.mira2.x86_64.rpm&lt;br /&gt;
wget -P &amp;quot;${DEB_REPO}&amp;quot; http://mirror.fuel-infra.org/fuel-plugins/6.0/ubuntu/glusterfs-client_3.5.2-4_amd64.deb&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It downloads two packages in your plugin's directories before Fuel Plugin Builder starts building repositories.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''''Why is there no /etc/astute.yaml file, when I run pre_deployment task?'''''&lt;br /&gt;
If you have task with &amp;quot;stage: pre_deployment&amp;quot; parameter set, you will not find /etc/astute.yaml file on the target node during the task execution. The file /etc/astute.yaml is a symlink that is created before Fuel deploys a role.&lt;br /&gt;
Target node can have several roles and each role contains its own file with deployment data.&lt;br /&gt;
Here is the example of a node with ID 2 and two roles, Controller and Cinder:&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;&lt;br /&gt;
root@node-2:~# ls -l /etc/ | grep yaml&lt;br /&gt;
-rw------- 1 root     root      8712 Nov 19 12:48 controller.yaml&lt;br /&gt;
-rw------- 1 root     root      8700 Nov 19 12:48 cinder.yaml&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
Let's assume that we need deployment data file for Controller role.&lt;br /&gt;
We can use '/etc/controller.yaml' file directly in deployment script.&lt;br /&gt;
&lt;br /&gt;
'''''What is the user context that fuel plugin hooks are invoked as: root or fuel user?'''''&lt;br /&gt;
Plugins hooks are executed under the root.&lt;br /&gt;
&lt;br /&gt;
'''''Are the keystone IP addresses and user name or password available to the fuel plugin post_deployment hook?'''''&lt;br /&gt;
Keystone admin_token, admin_password are in /etc/astute.yaml and can be used in the post_deployment hook. For connection to keystone we should use management_vip:5000. management_vip is also in the astute.yaml. Also keystone url can be fetched from /root/openrc (OS_AUTH_URL), but this is hackish way.&lt;br /&gt;
&lt;br /&gt;
'''''Do multiple openstack controller nodes mean multiple neutron­server nodes?Neutron server is installed on each controller node.&lt;br /&gt;
Are all the controller nodes' private IP (not VIP) available and accessible to the post­deployment hook?(because we want to run the avi­controller, network etconly once, but we have to run the plugin install on all neutron­server nodes)? Since there are multiple controller nodes, then fuel infrastructure automatically runs the plugin post­deployment hook on each of them.'''''&lt;br /&gt;
&lt;br /&gt;
The private IP is referred to the IP of VM, or what we call management IP - all people in OpenStack name it differently. On the post_deployment step all networks, controllers, e.t.c. are configured and run.&lt;br /&gt;
&lt;br /&gt;
'''''In pre-deployment, the astute.yaml is a symlink to the role specific yaml (controller, cinder etc) before the role is deployed, but in post-deployment how is astute.yaml organized - merged from all role yamls?'''''&lt;br /&gt;
The astute.yaml files are not merged during deployment process. Result file just astute.yaml for last deployed role. Specific astute.yaml can be found by role name.&lt;br /&gt;
&lt;br /&gt;
'''''How can I add a custom role?'''''&lt;br /&gt;
Current Plugin Architecture does not provide a way to define role. Starting with Fuel 6.1 you can use the Operating System role as a workaround.&lt;br /&gt;
&lt;br /&gt;
In the tasks.yaml file use the base-os string to specify which task should be used for the role deployment.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;&lt;br /&gt;
- role: ['base-os']&lt;br /&gt;
  stage: post_deployment&lt;br /&gt;
  type: shell&lt;br /&gt;
  parameters:&lt;br /&gt;
    cmd: bash deploy.sh&lt;br /&gt;
    timeout: 42&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When creating documentation for your plugin, ask the user to assign the Operating System role on the required node and specify the name to give this node, such as zabbix-01.&lt;br /&gt;
In the deployment script you can query the user_node_name variable and decide if the script should deploy Zabbix related packages on the node.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
user_node_name: zabbix-01&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Channels of communication ==&lt;br /&gt;
&lt;br /&gt;
If you have some questions left, feel free to use the '''openstack-dev''' mailing list (use ''[fuel][plugin]'' prefix). For instructions on mailing list usage, see [http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev openstack-dev] &lt;br /&gt;
mailing list instructions.&lt;/div&gt;</summary>
		<author><name>Adidenko</name></author>	</entry>

	<entry>
		<id>https://wiki.openstack.org/w/index.php?title=Fuel/How_to_contribute&amp;diff=84800</id>
		<title>Fuel/How to contribute</title>
		<link rel="alternate" type="text/html" href="https://wiki.openstack.org/w/index.php?title=Fuel/How_to_contribute&amp;diff=84800"/>
				<updated>2015-06-30T11:25:06Z</updated>
		
		<summary type="html">&lt;p&gt;Adidenko: /* Test and report bugs */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Join the Fuel team=&lt;br /&gt;
=== First steps ===&lt;br /&gt;
Read the [http://docs.openstack.org/infra/manual/developers.html Developer's Guide] and learn how to setup the accounts and git.&lt;br /&gt;
&lt;br /&gt;
Clone the repositories:&lt;br /&gt;
* git clone git://github.com/stackforge/fuel-main.git&lt;br /&gt;
* git clone git://github.com/stackforge/fuel-web.git&lt;br /&gt;
* git clone git://github.com/stackforge/fuel-astute.git&lt;br /&gt;
* git clone git://github.com/stackforge/fuel-ostf.git&lt;br /&gt;
* git clone git://github.com/stackforge/fuel-library.git&lt;br /&gt;
* git clone git://github.com/stackforge/fuel-docs.git&lt;br /&gt;
&lt;br /&gt;
You can [https://review.openstack.org/#/q/project:%255Estackforge/fuel-.*,n,z search gerrit for all reviews related to Fuel], or use the [https://review.openstack.org/#/dashboard/?foreach=%28project%3A^stackforge%2Ffuel-.*%29+status%3Aopen+NOT+label%3AWorkflow%3C%3D-1+NOT+label%3ACode-Review%3C%3D-2&amp;amp;title=Fuel+Inbox&amp;amp;My+Patches+Requiring+Attention=owner%3Aself+%28label%3AVerified-1+OR+label%3ACode-Review-1+OR+label%3AWorkflow%3C%3D-1%29&amp;amp;Fuel+Specs=NOT+label%3AWorkflow%3E%3D1+NOT+owner%3Aself+project%3Astackforge%2Ffuel-specs&amp;amp;Needs+Approval=NOT+label%3AWorkflow%3E%3D1+NOT+label%3AWorkflow%3C%3D-1+NOT+label%3AVerified%3C%3D-1+NOT+owner%3Aself+label%3ACode-Review%3E%3D2+NOT+label%3ACode-Review-1&amp;amp;5+Days+Without+Feedback=NOT+label%3AWorkflow%3E%3D1+NOT+label%3AWorkflow%3C%3D-1+NOT+label%3AVerified%3C%3D-1+NOT+owner%3Aself+NOT+project%3Astackforge%2Ffuel-specs+NOT+label%3ACode-Review%3C%3D2+age%3A5d&amp;amp;No+Negative+Feedback=NOT+label%3AWorkflow%3E%3D1+NOT+label%3AWorkflow%3C%3D-1+NOT+label%3AVerified%3C%3D-1+NOT+owner%3Aself+NOT+project%3Astackforge%2Ffuel-specs+NOT+label%3ACode-Review%3C%3D-1+NOT+label%3ACode-Review%3E%3D2+limit%3A50&amp;amp;Other=NOT+label%3AVerified%3C%3D-1+NOT+owner%3Aself+NOT+project%3Astackforge%2Ffuel-specs+label%3ACode-Review-1+limit%3A20 gerrit dashboard for Fuel] for a prioritized list of open reviews (this URL was generated using [https://github.com/stackforge/gerrit-dash-creator/blob/master/dashboards/fuel.dash Gerrit dashboard generator], you need to be logged into Gerrit for it to work).&lt;br /&gt;
&lt;br /&gt;
Please note that OpenStack Infra uses strict checks on your git commit messages. The most important rules are:&lt;br /&gt;
* Keep your commit title short (&amp;lt;80 symbols). It must not end with dot.&lt;br /&gt;
* Body of commit message should be separated from title by one empty line&lt;br /&gt;
* If patch closes bug, then it must have in a body &amp;quot;Closes-Bug: #12345&amp;quot;, where 12345 is your LP bug number&lt;br /&gt;
* If patch relates to bug, but doesn't completely solve an issue, then you must use &amp;quot;Related-Bug: #12345&amp;quot;&lt;br /&gt;
See the [[GitCommitMessages|Git commit messages]] wiki page for more details.&lt;br /&gt;
&lt;br /&gt;
=How and where to get help=&lt;br /&gt;
=== Subscribe to mailing lists ===&lt;br /&gt;
* [http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev OpenStack developers mailing list]. If you are hacking on Fuel, or have technical question about Fuel internals, you are very welcome in this ML with subject containing &amp;quot;[Fuel]&amp;quot;.&lt;br /&gt;
* [http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack OpenStack users mailing list]. Fuel traffic is there with subject containing &amp;quot;[Fuel]&amp;quot;. You are welcome to ask questions related to Fuel usage, including errors, etc.&lt;br /&gt;
* [http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-announce OpenStack announcements mailing list]. Announcements about the OpenStack project like product release information, security advisories, important discussions. This is a low-traffic, read-only list.&lt;br /&gt;
* There are even more mailing lists out there, visit [[MailingLists]] to see the other OpenStack related lists.&lt;br /&gt;
&lt;br /&gt;
=== IRC at freenode.net ===&lt;br /&gt;
* The general Fuel channel is called &amp;quot;#fuel&amp;quot;, and it is logged [http://irclog.perlgeek.de/fuel/ here].&lt;br /&gt;
* The Fuel development channel is called &amp;quot;#fuel-dev&amp;quot;, and it is logged [http://irclog.perlgeek.de/fuel-dev/ here].&lt;br /&gt;
&lt;br /&gt;
=== Quick reference dev links ===&lt;br /&gt;
* Development environment [http://docs.mirantis.com/fuel-dev/develop/env.html http://docs.mirantis.com/fuel-dev/develop/env.html]&lt;br /&gt;
* How to build your Fuel ISO [http://docs.mirantis.com/fuel-dev/develop/env.html#building-the-fuel-iso http://docs.mirantis.com/fuel-dev/develop/env.html#building-the-fuel-iso]&lt;br /&gt;
* Nailgun development [http://docs.mirantis.com/fuel-dev/develop/nailgun.html http://docs.mirantis.com/fuel-dev/develop/nailgun.html]&lt;br /&gt;
* Health Check (OSTF) contributors guide [http://docs.mirantis.com/fuel-dev/develop/ostf_contributors_guide.html http://docs.mirantis.com/fuel-dev/develop/ostf_contributors_guide.html]&lt;br /&gt;
* Contributing to Fuel Library (puppet modules) [http://docs.mirantis.com/fuel-dev/develop/module_structure.html http://docs.mirantis.com/fuel-dev/develop/module_structure.html]&lt;br /&gt;
* Devops framework - distributed testing of Fuel envs [http://docs.mirantis.com/fuel-dev/devops.html http://docs.mirantis.com/fuel-dev/devops.html]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Contributing=&lt;br /&gt;
Fuel is large project within which Programming, Linux and Networking intersect. It is written in Python, Ruby and JavaScript. It also has a number of build scripts in bash &amp;amp; make. Documentation is written in Sphinx. New contributors are always welcome.&lt;br /&gt;
&lt;br /&gt;
==Fuel library for puppet manifests==&lt;br /&gt;
===Adding new puppet modules to fuel-library===&lt;br /&gt;
'''Case A. Pulling in changes from an existing module'''&lt;br /&gt;
&lt;br /&gt;
If you are pulling in changes to an existing fork from a module that is the work of another project and is already tracked in separate repo then:&lt;br /&gt;
1. Create a review request with a unmodified copy of the upstream module from whichever point you are working from and no other related modifications.&lt;br /&gt;
* This review should also contain the commit hash from the upstream repo in the commit message.&lt;br /&gt;
* The review should be evaluated to determine its suitability and either rejected (for licensing, code quality, outdated version requested) or accepted without requiring modifications.&lt;br /&gt;
* The review should not include code that calls this new module.&lt;br /&gt;
2. Any changes necessary to make it work with Fuel should then be proposed as a dependent change(s).&lt;br /&gt;
&lt;br /&gt;
'''Case B. Adding a new module'''&lt;br /&gt;
&lt;br /&gt;
If you are adding a new module that is a work purely for Fuel and will not be tracked in a separate repo then submit incremental reviews that consist of working implementation of features for your module.&lt;br /&gt;
If you have features that are necessary, but do not work fully yet, then prevent them from running during the deployment. Once your feature is complete, submit a review to activate the module during deployment.&lt;br /&gt;
&lt;br /&gt;
If you are going to add a new fork of upstream module - please don't do. Instead, follow the upstream module's contribution rules and provide this module as an additional plug-able component for Fuel. This can be done as a part of [[Fuel/Plugins|plug-able architecture]] and distributed as a package. Note, if upstream module doesn't fit your requirements, you should first adapt the module for your needs upstream or,  for emergency cases, provide custom patch-sets as a part of module as a Fuel plugin distribution.&lt;br /&gt;
&lt;br /&gt;
Modules with licenses incompatible with Apache 2.0 (GPL, etc.) will not be accepted. *Please pay attention to the license information.*&lt;br /&gt;
&lt;br /&gt;
===Contributing to existing fuel-library modules===&lt;br /&gt;
As developers of Puppet modules, we tend to collaborate with the Puppet OpenStack community. As a result, we contribute to upstream modules all of the improvements, fixes and customizations we make to improve Fuel as well. That implies that every contributor must follow Puppet DSL basics, [[Puppet-openstack#Developer_documentation|puppet-openstack dev docs]] and [[Puppet-openstack#Rspec_puppet_tests|Puppet rspec tests requirements]].&lt;br /&gt;
&lt;br /&gt;
The most common and general rule is that upstream modules should be modified only when bugfixes and improvements could benefit everyone in the community. And appropriate patch should be proposed to the upstream project prior to Fuel project.&lt;br /&gt;
&lt;br /&gt;
In other cases (like applying some very specific custom logic or settings) contributor should submit patches to openstack::* classes&lt;br /&gt;
&lt;br /&gt;
Fuel library includes custom modules as well as ones forked from upstream sources. Note that Modulefile (or metadata.json), if any exists, should be used in order to recognize either given module is forked upstream one or not. In case there is no Modulefile in module’s directory, the contributor may submit a patch directly to this module in Fuel library. Otherwise, he or she should submit patch to upstream module first, and once merged or +2 recieved from a core reviewer, the patch should be backported to Fuel library as well. Note that the patch submitted for Fuel library should contain in commit message the upstream commit SHA or link to github pull-request (if the module is not on stackforge) or Change-Id of gerrit patch.&lt;br /&gt;
&lt;br /&gt;
=Fuel development environments=&lt;br /&gt;
===VirtualBox===&lt;br /&gt;
The quickest way to get started with Fuel is to set up an environment under VirtualBox. This is a great way start testing, for instance by using the nightly builds to try to verify, confirm or triage bugs. A quick-start script and instructions can be found at https://software.mirantis.com/quick-start/.&lt;br /&gt;
&lt;br /&gt;
===Fuel ISO-build and development environment===&lt;br /&gt;
Setting up an environment to build the Fuel ISO will allow you to easily build against specific commits in order to do more complicated bug test/confirm/triage/fix work, or augmenting Fuel with new features. In addition to preparing the environment for ISO building, the steps necessary to prepare a dev environment for the other Fuel components (nailgun, astute and doc building) can be found there. Instructions for preparing the environment can be found at http://docs.mirantis.com/fuel-dev/develop/env.html.&lt;br /&gt;
&lt;br /&gt;
===Fuel DevOps environment===&lt;br /&gt;
Setting up a Linux machine as a Fuel DevOps environment will allow you to automate the build/verify/test process, in addition to building the ISO and doing other Fuel-related development. Using libvirt, the devops environment is able to deploy multiple complete OpenStack environments on VMs. Instructions for preparing a devops environment can be found at http://docs.mirantis.com/fuel-dev/devops.html.&lt;br /&gt;
&lt;br /&gt;
=Documentation=&lt;br /&gt;
There are two types of documentation in Fuel: [http://docs.mirantis.com/fuel-dev/ development] and [http://docs.mirantis.com/ user]. Source code of the development documentation can be found at [https://github.com/stackforge/fuel-web/tree/master/docs fuel-web repository]; users, at [https://github.com/stackforge/fuel-docs fuel-docs repository]. Both repositories use the [http://sphinx-doc.org/rest.html reStructuredText format]. Documentation is treated as source code, we use the same [[Fuel/How_to_contribute#First_steps|development process]] for updating documentation as we do for Fuel code.&lt;br /&gt;
&lt;br /&gt;
=== Writing documentation ===&lt;br /&gt;
Keeping the Documentation up to date is hard and it is a critical part in every project. Fuel developers use the OpenStack [https://wiki.openstack.org/wiki/Documentation/DocImpact DocImpact] process to highlight code changes that need to be reflected in documentation. When a patchset should be documented or requires documentation changes, the reviewer should ask the commiter to add 'DocImpact' tag to their commit message, and makes sure the commit message provides enough information about the impact of the code change. When a commit with a DocImpact tag is merged, a new bug will be automatically created and assigned to the Fuel Documentation team. Technical writers then work with the commiter to reflect the commit in the documentation.&lt;br /&gt;
&lt;br /&gt;
A bug generated from a DocImpact commit should be assigned to fuel-docs team until a technical writer picks it up. Technical writer collects information from the original commit author, and adds it to the right documentation areas. It's commit author's responsibility to provide an informative commit message in the first place, to answer technical writer's questions, and to review documentation commits that address that DocImpact bug.&lt;br /&gt;
&lt;br /&gt;
=== Update and expand current documentation ===&lt;br /&gt;
Feel free to file bug if you find a problem with the documentation, and provide with a fix for it via same code contribution policy and procedures. There is [http://docs.mirantis.com/fuel-dev/develop/env.html#building-documentation building documentation page] to help with an environment setup for development documentation.&lt;br /&gt;
&lt;br /&gt;
=== Writing release notes ===&lt;br /&gt;
==== New features ====&lt;br /&gt;
For every blueprint listed on the milestone page in Launchpad (e.g. https://launchpad.net/fuel/+milestone/5.1), find answers to the following questions:&lt;br /&gt;
* What is the visible impact of the change for a user?&lt;br /&gt;
* Was this previously documented as a Known Issue?&lt;br /&gt;
&lt;br /&gt;
If it is a user visible improvement, add a New Features entry about it. Explain when this feature is important, how it can be enabled, and what are the current expectations and limitations.&lt;br /&gt;
&lt;br /&gt;
If it was a Known Issue before, add a Resolved Issues entry.&lt;br /&gt;
&lt;br /&gt;
==== Known and Resolved issues ====&lt;br /&gt;
Scan the release milestone page (e.g. [https://launchpad.net/fuel/+milestone/6.0 fuel 6.0]). Review all bugs targeted for the current milestone that satisfy one of the following conditions:&lt;br /&gt;
* &amp;quot;release-notes&amp;quot; tag&lt;br /&gt;
* Critical priority&lt;br /&gt;
* High priority and &amp;quot;customer-found&amp;quot; tag.&lt;br /&gt;
&lt;br /&gt;
Sort the bugs table on the milestone page by Number from highest to lowest, so that you can see when you've reached the bugs that you have already reviewed. If bug status for the current milestone is Fix Committed or Fix Released, consider it for Resolved Issues list. Find answers to:&lt;br /&gt;
* Was this problem present in the previous GA release? (If it was, it will be targeted for at least one previous release series, with target milestone set to a maintenance release in that series.)&lt;br /&gt;
* How does one confirm if their environment is affected? (Identify specific configurations affected by the bug, include error messages or other symptoms that distinguish this bug from others.)&lt;br /&gt;
* If you're affected, how do you recover?&lt;br /&gt;
* What was the root cause and what had to be changed to resolve the issue?&lt;br /&gt;
&lt;br /&gt;
If bug status for the current milestone is Won't Fix and it meets the criteria above, consider it for the Known Issues list. Questions to answer are:&lt;br /&gt;
* How does one confirm if their environment is affected?&lt;br /&gt;
* Is there a workaround? (How do you prevent this problem from affecting you?)&lt;br /&gt;
* What is the recovery procedure?&lt;br /&gt;
&lt;br /&gt;
==== Reviewing the release notes ====&lt;br /&gt;
Responsibility for every section of release notes is assigned to a technical writer. The writer identifies features and bugs that have to be reflected in their section. For each feature and bug, the writer finds a responsible software engineer: either feature owner, or committer of the most recent bugfix.&lt;br /&gt;
&lt;br /&gt;
If sufficient description (see question lists above) cannot be derived from bug description, blueprint description and specification, and commit messages of related commits, the writer contacts the engineer privately with a request for more information. When a description of a feature or bug is published in a gerrit review, the writer subscribes the engineer to that review, and once again privately sends a request with a link to the documentation review in Gerrit and instructions on how to identify specific documentation files and lines that this engineer must review (e.g. LP bug number, specific RST file, section header or label, etc.)&lt;br /&gt;
&lt;br /&gt;
Fuel engineers must prioritize such information and review requests so that they are able to respond within one week during normal development process, and within one business day during the period between Hard Code Freeze and GA release. Standard escalation process is used when no response to request for information or request for review is received in time. Technical writer is responsible for tracking status of information and review requests and escalations for their section of release notes.&lt;br /&gt;
&lt;br /&gt;
=Bugs=&lt;br /&gt;
===Verify bugs===&lt;br /&gt;
This is very easy to get started, but help here is actually very valuable. Especially when it comes to bugfixes which are relevant to only certain types of hardware. When bugfix is merged, bug is automatically moves to &amp;quot;Fix Committed&amp;quot; status. In Fuel, we set &amp;quot;Fix Released&amp;quot; status for a bug only when it was verified by someone else than a developer. You can simple check out [https://bugs.launchpad.net/fuel/+bugs?field.status%3Alist=FIXCOMMITTED all fix committed bugs] and start verifying them. It is required to be in fuel-bugs LP group to be able to change bug status. However you can leave a comment in bug report, and it will be enough for bug supervisors to change bug status. By your request, you can be included into fuel-bugs team to manage bugs yourself.&lt;br /&gt;
&lt;br /&gt;
=== Test and report bugs ===&lt;br /&gt;
You can always build a developers ISO from master following instructions at http://docs.mirantis.com/fuel-dev/develop/env.html#building-the-fuel-iso. Test different deployment modes, and file bugs. Please do not hesitate to share your findings in IRC for any details you would want to know. Feel free to file bug in a format you want, however it would be great to see a bug in a certain format, with all details in place - to easily reproduce and save a time of developers. You can follow the following simple guidance, which a little bit extend official OpenStack [[Bugs]] page.&lt;br /&gt;
&lt;br /&gt;
The bugs you report for Fuel can be either “Public” or “Private”. Private bugs become visible only for Dev, QA, and Support teams. The guidance is as follows:&lt;br /&gt;
* Normally you would want to report a “Public” bug&lt;br /&gt;
* However, if a bug contains any sensitive information, or security vulnerability information, please report a “Private” bug&lt;br /&gt;
&lt;br /&gt;
Before creating a new bug, it's always a good idea to check if a bug like that already exists in the project, and update an existing bug instead of creating something that will later have to be discarded as a duplicate. However, it is important to make sure that both bugs are really related, dealing with a duplicate is much easier than untangling several unrelated lines of investigation mixed into one bug. Do not ever reopen bugs with generic catch-all titles like &amp;quot;Horizon crashed&amp;quot; or &amp;quot;HA doesn't work&amp;quot; that can cover whole ranges of root causes. Do not create new bugs with such titles, either: be as specific about the nature of the problem as you can.&lt;br /&gt;
&lt;br /&gt;
Here is how you file a bug:&lt;br /&gt;
* Go to https://launchpad.net/fuel&lt;br /&gt;
* Select “Report a bug” on the right&lt;br /&gt;
* Fill in “Summary” field for a bug. It is going to be the headline. Please be descriptive but short and to the point.&lt;br /&gt;
** Bad - &amp;quot;Savanna doesn’t install&amp;quot;&lt;br /&gt;
** Good - &amp;quot;Savanna fails to install in HA mode when “Neutron with VLANs” network is  selected&amp;quot;&lt;br /&gt;
* Enter “Further information”. This is a bug description. It should contain the following sections:&lt;br /&gt;
** Steps to reproduce&lt;br /&gt;
*** Bad: Run the deployment in HA configuration&lt;br /&gt;
*** Good:&lt;br /&gt;
***# Create a new cluster&lt;br /&gt;
***# Select HA mode, “Neutron with VLANs” for network, and choose to install Savanna&lt;br /&gt;
***# Leave defaults the rest of the settings. Run cluster installation&lt;br /&gt;
** Expected result:&lt;br /&gt;
*** Good: Savanna is deployed, up and running.&lt;br /&gt;
** Actual result:&lt;br /&gt;
*** Bad: Savanna fails to install.&lt;br /&gt;
*** Good: Savanna installation fails with the error message “xxx”. Please see the attached screenshot which shows the errors on “Logs” tab.&lt;br /&gt;
** Workaround&lt;br /&gt;
*** Bad: Don’t use “Neutron with VLANs”&lt;br /&gt;
*** Good: Switch network mode to “Neutron with GRE” for the deployment to complete successfully.&lt;br /&gt;
** Impact&lt;br /&gt;
*** Bad: Needs to be fixed.&lt;br /&gt;
*** Good: deployment cannot be completed, because customer requires us to implement a use case for Savanna and “Neutron with VLANs”. Changing configuration to “Neutron with GRE” is not as acceptable option here so this has to be addressed as soon as possible.&lt;br /&gt;
** Description of the environment. Provide enough relevant information:&lt;br /&gt;
*** Output of http://fuel-master-node:8000/api/version/&lt;br /&gt;
*** Operating System&lt;br /&gt;
*** Reference Architecture (HA / non-HA)&lt;br /&gt;
*** Network model (Nova-network, Neutron+VLAN, Neutron+GRE, etc.)&lt;br /&gt;
*** Related Projects installed (Savanna, Murano, Ceilometer)&lt;br /&gt;
* Select visibility for the bug under “This bug contains information that is” field. Either leave it as “Public” (default) or set it to “Private” per the above guidance&lt;br /&gt;
* Add attachments under “Extra Options” section&lt;br /&gt;
** Logs&lt;br /&gt;
** Diagnostic snapshot&lt;br /&gt;
** Screenshots&lt;br /&gt;
* After everything is entered, select the “Submit bug report” button&lt;br /&gt;
&lt;br /&gt;
=== Confirm and triage bugs ===&lt;br /&gt;
Fuel project uses the same bug management practices as in other OpenStack projects. Please follow [[Bugs]] and [[BugTriage]] pages.&lt;br /&gt;
&lt;br /&gt;
When triaging the bugs in the Fuel deployment process (as opposed to bugs in OpenStack components deployed by Fuel), use following additional criteria for bug importance:&lt;br /&gt;
&lt;br /&gt;
* Critical = can't deploy anything and there's no trivial workaround; data loss; or security vulnerability&lt;br /&gt;
* High = specific hardware, configurations, or components are unusable and there's no workaround; or everything is broken but there's a workaround&lt;br /&gt;
* Medium = specific hardware, configurations, or components are working incorrectly; or is completely unusable but there's a workaround&lt;br /&gt;
* Low = minor feature is broken and can be fixed with a trivial workaround; or a cosmetic defect&lt;br /&gt;
* Wishlist = not a bug, either close as Won't Fix, or associate with a blueprint (create new blueprint if no existing blueprint covers the feature requested in the bug)&lt;br /&gt;
&lt;br /&gt;
Additional guidelines for documentation bugs:&lt;br /&gt;
&lt;br /&gt;
* Critical = following the instructions from documentation can cause outage or data loss&lt;br /&gt;
* High = documentation includes information that is not true, or instructions that yield the advertised outcome&lt;br /&gt;
* Medium = important information is missing from documentation (e.g. new feature description)&lt;br /&gt;
* Low = additional information would improve reader's understanding of a feature&lt;br /&gt;
* Wishlist = cosmetic formatting and grammar issues&lt;br /&gt;
&lt;br /&gt;
Also Fuel uses different meaning for two bug states:&lt;br /&gt;
&lt;br /&gt;
* Confirmed = somebody who is not submitter looked into the bug and made sure that it is properly triaged. The person must made sure that milestone, importance and assignee are properly set. Still the bug '''could be not''' reproduced or confirmed as genuine.&lt;br /&gt;
* Fix Released = somebody who is not assignee verified that the issue does not reproduce after it was fixed. The status is left for QA to mark bugs as verified after they are fixed.&lt;br /&gt;
&lt;br /&gt;
When triaging bugs, please use the following routine:&lt;br /&gt;
&lt;br /&gt;
# Review all '''New''' bugs.&lt;br /&gt;
# Assign each New bug to the release series under development (focus of development according to [https://launchpad.net/fuel/+series Fuel project timeline]) and set corresponding bug status and milestone for that release series.&lt;br /&gt;
# Consider changing the bug title to be more specific, replace generic statements like &amp;quot;deployment timeout exceeded&amp;quot; with description of the root cause (if identified) or symptops that are unique for that bug.&lt;br /&gt;
# Consider visibility status of the bug. If it contains sensitive information, set it to '''Private'''. If it describes a security vulnerability, set it to '''Private Security'''.&lt;br /&gt;
# If the bug does not contain sufficient information as described in [[Fuel/How_to_contribute#Test_and_report_bugs]], request the missing information, and set the bug status to '''Incomplete'''. Add a comment using the following template: ''We didn't receive required details in order to correctly troubleshoot the problem, so we are setting this bug into Incomplete state. Please provide reqested information and we will investigate this issue further. If you think it was incorrectly set to Incomplete, please comment in the bug''.&lt;br /&gt;
# If there is sufficient information on how to reproduce the bug and milestone, importance and assignee are properly set, set the status to '''Confirmed'''.&lt;br /&gt;
# If there is sufficient information to start implementing a fix, set the status to '''Triaged'''.&lt;br /&gt;
# If the root cause of the bug is identified, include it in the bug description.&lt;br /&gt;
# Review all '''Incomplete''' bugs&lt;br /&gt;
# If an Incomplete bug has new updates, use the same steps as described above for New bugs.&lt;br /&gt;
# If an Incomplete bug did not have any updates for '''4 weeks''', close it as '''Invalid'''. Add a comment using the following template: ''This bug was incomplete for more than 4 weeks. We cannot investigate it further so we are setting the status to Invalid. If you think it is not correct, please feel free to provide requested information and reopen the bug, and we will look into it further.''&lt;br /&gt;
# During '''Code Freeze''' for a release, review all bugs targeted at that release milestone, make sure it is updated daily by the assignee (or bug reporter if the bug is not assigned to a person).&lt;br /&gt;
# If you know that the bug is related to some blueprints, link this bug to these blueprints. To do this, go to corresponding blueprints page and hit 'Link a bug report' link.&lt;br /&gt;
&lt;br /&gt;
Remember that every status change of a bug should be accompanied by a comment explaining the reason why the change was made.&lt;br /&gt;
&lt;br /&gt;
Useful LaunchPad searches and tools:&lt;br /&gt;
&lt;br /&gt;
* [https://bugs.launchpad.net/fuel/+bugs?field.status=NEW&amp;amp;field.project=FUEL New bugs]&lt;br /&gt;
* [https://bugs.launchpad.net/fuel/+bugs?field.searchtext=&amp;amp;orderby=-importance&amp;amp;field.status%3Alist=INCOMPLETE_WITH_RESPONSE&amp;amp;field.status%3Alist=INCOMPLETE_WITHOUT_RESPONSE&amp;amp;assignee_option=any&amp;amp;field.assignee=&amp;amp;field.bug_reporter=&amp;amp;field.bug_commenter=&amp;amp;field.subscriber=&amp;amp;field.structural_subscriber=&amp;amp;field.tag=&amp;amp;field.tags_combinator=ANY&amp;amp;field.has_cve.used=&amp;amp;field.omit_dupes.used=&amp;amp;field.omit_dupes=on&amp;amp;field.affects_me.used=&amp;amp;field.has_patch.used=&amp;amp;field.has_branches.used=&amp;amp;field.has_branches=on&amp;amp;field.has_no_branches.used=&amp;amp;field.has_no_branches=on&amp;amp;field.has_blueprints.used=&amp;amp;field.has_blueprints=on&amp;amp;field.has_no_blueprints.used=&amp;amp;field.has_no_blueprints=on&amp;amp;search=Search Incomplete bugs]&lt;br /&gt;
* [https://bugs.launchpad.net/fuel/+bugs?field.searchtext=&amp;amp;orderby=-importance&amp;amp;field.status%3Alist=NEW&amp;amp;field.status%3Alist=CONFIRMED&amp;amp;field.status%3Alist=TRIAGED&amp;amp;field.status%3Alist=INPROGRESS&amp;amp;field.status%3Alist=INCOMPLETE_WITH_RESPONSE&amp;amp;field.status%3Alist=INCOMPLETE_WITHOUT_RESPONSE&amp;amp;assignee_option=none&amp;amp;field.assignee=&amp;amp;field.bug_reporter=&amp;amp;field.bug_commenter=&amp;amp;field.subscriber=&amp;amp;field.structural_subscriber=&amp;amp;field.tag=&amp;amp;field.tags_combinator=ANY&amp;amp;field.has_cve.used=&amp;amp;field.omit_dupes.used=&amp;amp;field.omit_dupes=on&amp;amp;field.affects_me.used=&amp;amp;field.has_patch.used=&amp;amp;field.has_branches.used=&amp;amp;field.has_branches=on&amp;amp;field.has_no_branches.used=&amp;amp;field.has_no_branches=on&amp;amp;field.has_blueprints.used=&amp;amp;field.has_blueprints=on&amp;amp;field.has_no_blueprints.used=&amp;amp;field.has_no_blueprints=on&amp;amp;search=Search Unassigned bugs]&lt;br /&gt;
* [https://bugs.launchpad.net/fuel/+bugs?field.searchtext=&amp;amp;field.status%3Alist=NEW&amp;amp;field.status%3Alist=CONFIRMED&amp;amp;field.status%3Alist=TRIAGED&amp;amp;field.status%3Alist=INPROGRESS&amp;amp;field.status%3Alist=INCOMPLETE_WITH_RESPONSE&amp;amp;field.status%3Alist=INCOMPLETE_WITHOUT_RESPONSE&amp;amp;assignee_option=choose&amp;amp;field.assignee=fuel-library&amp;amp;field.bug_reporter=&amp;amp;field.bug_commenter=&amp;amp;field.subscriber=&amp;amp;field.structural_subscriber=&amp;amp;field.tag=&amp;amp;field.tags_combinator=ANY&amp;amp;field.has_cve.used=&amp;amp;field.omit_dupes.used=&amp;amp;field.omit_dupes=on&amp;amp;field.affects_me.used=&amp;amp;field.has_patch.used=&amp;amp;field.has_branches.used=&amp;amp;field.has_branches=on&amp;amp;field.has_no_branches.used=&amp;amp;field.has_no_branches=on&amp;amp;field.has_blueprints.used=&amp;amp;field.has_blueprints=on&amp;amp;field.has_no_blueprints.used=&amp;amp;field.has_no_blueprints=on&amp;amp;search=Search&amp;amp;orderby=milestone_name&amp;amp;start=0 Bugs in fuel-library, sorted by milestone]&lt;br /&gt;
* Launchpad Report Tool with bugs SLA by Mirantis https://launchpad-reports-summary.mirantis.com/project/bugs_lifecycle_report/6.1&lt;br /&gt;
* [https://addons.mozilla.org/en-US/firefox/addon/launchpad-helper/?src=cb-dl-created Launchpad Helper for Firefox]&lt;br /&gt;
* [https://chrome.google.com/webstore/detail/launchpad-helper/kjelakmoldahcakikjnfebiolcliigah?hl=en Launchpad Helper for Chrome]&lt;br /&gt;
&lt;br /&gt;
=== Fix bugs ===&lt;br /&gt;
The most simple and easy way to contribute code into Fuel is to start with bug fixes. First of all, check out [https://bugs.launchpad.net/fuel/+bugs?field.status%3Alist=NEW&amp;amp;field.status%3Alist=CONFIRMED&amp;amp;field.status%3Alist=TRIAGED&amp;amp;field.tag=low-hanging-fruit+&amp;amp;field.tags_combinator=ANY bugs with &amp;quot;low-hanging-fruit&amp;quot; tag]. You can also take any other bug. For easier management of bugs, Fuel uses multiple functional groups, and you will see bugs assigned to fuel-python, fuel-library, fuel-qa and other teams. Feel free to pick any of those. It is assigned to group, so group can get an email notification about a bug. Unless it is reassigned to particular engineer to work on that bug, then it means the bug is not taken by anyone yet, so feel free to take it. Bugs with assignee set to a person are not yet imply that someone works on them (but it should in ideal world). If it is even in &amp;quot;in progress&amp;quot; state, feel free to ping a person and ask if he really works on that bug, and feel free to assign yourself otherwise.&lt;br /&gt;
&lt;br /&gt;
=== Backport bugfixes to stable release series ===&lt;br /&gt;
When you create a new bug with High or Critical priority or upgrade an existing bug, always check if this bug is present in the supported stable release series (at least one most recent stable release). If it is present there, target it to all affected series (even if you don't expect to be able to eventually backport a fix). If it's not present in stable releases, document that on the bug so that other people don't have to re-check.&lt;br /&gt;
&lt;br /&gt;
When you propose a fix for a bug, always start with fixing it in the master branch. If the fix only applies to the stable branch and is not relevant in master, explain that in the commit message. For a bug targeted for stable release series, cherry-pick the fix commit onto the stable/x.x branch for each series it is targeted for, '''after''' the fix was merged to master (creating backports prematurely leads to possible inconsistency between master and stable/x.x versions of the same commit). Use the same Change-Id and topic (git review -t bug/&amp;lt;id&amp;gt;) to make it easier to track down all backports for that bug. You can also use &amp;quot;Cherry Pick To&amp;quot; button in Gerrit if the commit can be applied to the stable branch without conflicts.&lt;br /&gt;
&lt;br /&gt;
When you approve a bugfix commit for master branch, use the information available so far on the bug and in the review request to review and maybe update backporting status of the bug. Is its priority high enough to need a backport? Is it targeted to all affected release series? Are there backport commits already? If yes, are they up to date with the commit that was merged to master?&lt;br /&gt;
* For all series where backport should exist and doesn't, create a backport review request yourself.&lt;br /&gt;
* For all other affected series, change bug status to Won't Fix and explain in bug comments.&lt;br /&gt;
* Do not merge commits into stable branches until it was merged into master, unless commit message explicitly documents why it doesn't apply to master.&lt;br /&gt;
&lt;br /&gt;
When you find a bug in a stable release, do not simply target it to the next release in that maintenance release series. Instead, target it to the release designated as &amp;quot;current focus&amp;quot; on the [https://launchpad.net/fuel/ Fuel home page in Launchpad]. If it's a High or Critical priority bug, additionally target it to the releases series it was originally found in, and, if applicable, all release series in between.&lt;br /&gt;
&lt;br /&gt;
If a bug is present in a maintenance release and not present in current release series, it should have one of the following statuses in the current release series:&lt;br /&gt;
* Incomplete if root cause analysis is not finished&lt;br /&gt;
* Fix Committed if root cause analysis shows that the bug is fixed by changes merged after the maintenance release the bug was found in&lt;br /&gt;
* Invalid if root cause analysis shows that the bug was introduced by a change specific to this maintenance release series&lt;br /&gt;
&lt;br /&gt;
=Enhancements=&lt;br /&gt;
=== Propose enhancements ===&lt;br /&gt;
Enhancements for Fuel are proposed using the mechanism of blueprints. The process is very similar to the bugs:&lt;br /&gt;
* Select &amp;quot;Register a Blueprint&amp;quot;.  Typically, you’ll find this link on the right side of the launchpad page.&lt;br /&gt;
** Enter a Name for the blueprint. If possible, include the name of the sub-component of fuel as the first word of the name (or just fuel for a broader blueprint), then a very short descriptor using dashes between words.  For example, [https://blueprints.launchpad.net/fuel/+spec/ui-declarative-wizard ui-declarative-wizard] or [https://blueprints.launchpad.net/fuel/+spec/fuel-stop-deployment fuel-stop-deployment].&lt;br /&gt;
** Enter a Title for the blueprint.  The title should describe the feature as clearly as possible in up to 70 characters. This title is displayed in every feature list or report.&lt;br /&gt;
* Enter a Summary of the blueprint.&lt;br /&gt;
** Summarize the idea of the blueprint in a user story.  If you have an existing user story in a public document, include the link.&lt;br /&gt;
** If a public document isn’t yet created and the user story is extensive, you can use https://etherpad.openstack.org/ to document the full user story.   You can use the Name that you used for the blueprint as the Pad name.&lt;br /&gt;
* Propose your blueprint by selecting the milestone in which you plan to complete the blueprint.&lt;br /&gt;
* You won’t need to enter any other fields, so now just choose Register Blueprint.&lt;br /&gt;
&lt;br /&gt;
If you’re just entering a new idea without a design, you can leave the specification URL field blank. If you have a design, here is how you get it published and approved:&lt;br /&gt;
* Upload a design specification in the &amp;quot;specs/&amp;lt;release&amp;gt;&amp;quot; folder in fuel-specs&lt;br /&gt;
** e.g. [https://review.openstack.org/96429 access-control-master-node]&lt;br /&gt;
** it should be based on the [http://git.openstack.org/cgit/stackforge/fuel-specs/tree/specs/template.rst template], see the instructions in the template for more details&lt;br /&gt;
** get it reviewed by submitting your patch using Gerrit, in the usual way: [http://docs.openstack.org/infra/manual/developers.html#development-workflow Development Workflow]&lt;br /&gt;
** at the end of each release, non-completed specs will be removed&lt;br /&gt;
** you need to re-submit for the following release, should the blueprint slip&lt;br /&gt;
* Once your design specification has been approved and merged into fuel-specs git repo:&lt;br /&gt;
** Update your blueprint's specification URL to point to the design specification in fuel-specs git&lt;br /&gt;
** Note, this should link to git (as in the template link above), not to the gerrit change&lt;br /&gt;
&lt;br /&gt;
When done, drop an email about the new blueprint to the mailing list to attract attention of Fuel developers, who are likely to provide early feedback and request additional information.&lt;br /&gt;
&lt;br /&gt;
Please read [[Blueprints|OpenStack Blueprints]] page for detailed definition of blueprints and their lifecycle.&lt;br /&gt;
&lt;br /&gt;
=== Implement new features ===&lt;br /&gt;
To implement a new feature, you will need to address the following:&lt;br /&gt;
# File a blueprint, with all required feature details, as described in [[Fuel/Where_to_contribute#Propose_enhancements|Propose enhancements]] section above and on [[Blueprints]] page&lt;br /&gt;
# PTL or core developers of Fuel should approve a blueprint, when all required information is provided.&lt;br /&gt;
# Please no active contribution unless there is an agreement on design. To get an approval, you can discuss a feature in the mailing list.&lt;br /&gt;
# Every new feature must not break other features, and whether work fine with features we had before, or be disabled in combination with features which do not work with the new one. Short list of features to check compatibility with:&lt;br /&gt;
#* All distributions (currently CentOS &amp;amp; Ubuntu)&lt;br /&gt;
#* Networking (nova-network, Neutron)&lt;br /&gt;
#* Combination with other roles on a node. For example, MongoDB role should not be placed with Ceph.&lt;br /&gt;
#* Disk partitioning (will it use existing partition or new one needs to be created?)&lt;br /&gt;
#* Network verification&lt;br /&gt;
# Other requirements for features:&lt;br /&gt;
#* logging of services should be done via rsyslog for Fuel Library contributions&lt;br /&gt;
#* implementation should be scalable, or otherwise limitations should be clearly stated in a design doc. It is unacceptable to degrade scalability and performance of already existing features.&lt;br /&gt;
# Start implementation and propose code changes frequently and by small pieces. This is the only way to successful merge - it is unrealistic to review changesets with 1000+ lines of code.&lt;br /&gt;
# Every feature should have a set of tests:&lt;br /&gt;
#* [https://github.com/stackforge/fuel-web/tree/master/nailgun/ui_tests CasperJS] and [https://github.com/stackforge/fuel-main/tree/master/fuelweb_ui_test Selenium] tests are for Fuel Web UI&lt;br /&gt;
#* [https://github.com/stackforge/fuel-web/tree/master/nailgun/nailgun/test Nailgun uses Python Unit Test framework] for unit and integration tests&lt;br /&gt;
#* [https://github.com/stackforge/fuel-astute/tree/master/spec Astute uses RSpec] for unit and integration tests&lt;br /&gt;
#* Consider extending [http://docs.mirantis.com/fuel-dev/develop/ostf_contributors_guide.html OSTF tests] for implemented feature&lt;br /&gt;
#* [https://github.com/stackforge/fuel-main/tree/master/fuelweb_test System tests], which use [http://docs.mirantis.com/fuel-dev/devops.html Devops framework], are run against an ISO, i.e. when all components are integrated. System tests last for up to 6-8 hours and run every night. As these tests are ran against integrated environment, their result represents a higher interest. Every large feature which has pieces in more than one Fuel component must be covered by system tests.&lt;br /&gt;
#* If feature requires special hardware, or special deployment setup, then existing CI should be extended with such hardware and required changes into devops framework. It should be discussed with the Fuel community in mailing list in order to come up with a joint decision.&lt;br /&gt;
# Documentation. New features must be well documented in both [[Fuel/Where_to_contribute#Documentation|user and development documentation]].&lt;br /&gt;
# Please propose changes for a feature before feature freeze date. Otherwise, changes won't be even reviewed before code freeze, and we will not let changes to land into master before milestone proposed branch is created. This will allow Fuel team to concentrate on stabilization of the current release, and put all the force into squashing bugs. Rules are similar to core OpenStack projects, see [[FeatureFreeze]] and [[ReleaseCycle]].&lt;br /&gt;
&lt;br /&gt;
=Tests=&lt;br /&gt;
=== Unit and integration tests for Nailgun ===&lt;br /&gt;
[https://github.com/stackforge/fuel-web/tree/master/nailgun/nailgun/test Nailgun uses Python Unit Test framework] for unit and integration tests. Help in writing test is highly appreciated - we always want better coverage! Please checkout [http://docs.mirantis.com/fuel-dev/develop/env.html#setup-for-nailgun-unit-tests how to setup development environment for Nailgun tests], and follow [[Fuel/How_to_Test_Your_Code|How to Test Your Code]] guidance.&lt;br /&gt;
&lt;br /&gt;
= Code review rules =&lt;br /&gt;
When contributing code changes to Fuel, please use the [http://docs.openstack.org/infra/manual/developers.html#development-workflow development workflow] and follow [[Fuel/Code_Review_Rules|Fuel specific rules and recommendations]].&lt;/div&gt;</summary>
		<author><name>Adidenko</name></author>	</entry>

	</feed>