The devstack plugin docs mostly referred to in tree plugins, which is
honestly something we don't want people doing. Instead restructure the
whole document to talk about external plugins as the only kinds of
plugins, and focus on a workflow to make that easy for people to work
through.
This also adds a plugin-registry page to start listing known plugins
somewhere centrally. Some sample content was added, hopefully people
will submit patches to include their plugins.
This does drop the section on hypervisor plugins. That's not currently
something that we expect a ton of people to work on, so diving into
the code for this should be fine.
Change-Id: Ifc0b831c90a1a45daa507a009d1dcffcd6e2deca
| 16 | 17 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,73 @@ |
| 0 |
+.. |
|
| 1 |
+ Note to reviewers: the intent of this file is to be easy for |
|
| 2 |
+ community members to update. As such fast approving (single core +2) |
|
| 3 |
+ is fine as long as you've identified that the plugin listed actually exists. |
|
| 4 |
+ |
|
| 5 |
+========================== |
|
| 6 |
+ DevStack Plugin Registry |
|
| 7 |
+========================== |
|
| 8 |
+ |
|
| 9 |
+Since we've created the external plugin mechanism, it's gotten used by |
|
| 10 |
+a lot of projects. The following is a list of plugins that currently |
|
| 11 |
+exist. Any project that wishes to list their plugin here is welcomed |
|
| 12 |
+to. |
|
| 13 |
+ |
|
| 14 |
+Official OpenStack Projects |
|
| 15 |
+=========================== |
|
| 16 |
+ |
|
| 17 |
+The following are plugins that exist for official OpenStack projects. |
|
| 18 |
+ |
|
| 19 |
++--------------------+-------------------------------------------+--------------------+ |
|
| 20 |
+|Plugin Name |URL |Comments | |
|
| 21 |
++--------------------+-------------------------------------------+--------------------+ |
|
| 22 |
+|magnum |git://git.openstack.org/openstack/magnum | | |
|
| 23 |
++--------------------+-------------------------------------------+--------------------+ |
|
| 24 |
+|trove |git://git.openstack.org/openstack/trove | | |
|
| 25 |
++--------------------+-------------------------------------------+--------------------+ |
|
| 26 |
+|zaqar |git://git.openstack.org/openstack/zarar | | |
|
| 27 |
++--------------------+-------------------------------------------+--------------------+ |
|
| 28 |
+ |
|
| 29 |
+ |
|
| 30 |
+ |
|
| 31 |
+Drivers |
|
| 32 |
+======= |
|
| 33 |
+ |
|
| 34 |
++--------------------+-------------------------------------------------+------------------+ |
|
| 35 |
+|Plugin Name |URL |Comments | |
|
| 36 |
++--------------------+-------------------------------------------------+------------------+ |
|
| 37 |
+|dragonflow |git://git.openstack.org/openstack/dragonflow |[d1]_ | |
|
| 38 |
++--------------------+-------------------------------------------------+------------------+ |
|
| 39 |
+|odl |git://git.openstack.org/openstack/networking-odl |[d2]_ | |
|
| 40 |
++--------------------+-------------------------------------------------+------------------+ |
|
| 41 |
+ |
|
| 42 |
+.. [d1] demonstrates example of installing 3rd party SDN controller |
|
| 43 |
+.. [d2] demonstrates a pretty advanced set of modes that that allow |
|
| 44 |
+ one to run OpenDayLight either from a pre-existing install, or |
|
| 45 |
+ also from source |
|
| 46 |
+ |
|
| 47 |
+Alternate Configs |
|
| 48 |
+================= |
|
| 49 |
+ |
|
| 50 |
++-------------+------------------------------------------------------------+------------+ |
|
| 51 |
+| Plugin Name | URL | Comments | |
|
| 52 |
+| | | | |
|
| 53 |
++-------------+------------------------------------------------------------+------------+ |
|
| 54 |
+|glusterfs |git://git.openstack.org/stackforge/devstack-plugin-glusterfs| | |
|
| 55 |
++-------------+------------------------------------------------------------+------------+ |
|
| 56 |
+| | | | |
|
| 57 |
++-------------+------------------------------------------------------------+------------+ |
|
| 58 |
+ |
|
| 59 |
+Additional Services |
|
| 60 |
+=================== |
|
| 61 |
+ |
|
| 62 |
++-------------+------------------------------------------+------------+ |
|
| 63 |
+| Plugin Name | URL | Comments | |
|
| 64 |
+| | | | |
|
| 65 |
++-------------+------------------------------------------+------------+ |
|
| 66 |
+|ec2-api |git://git.openstack.org/stackforge/ec2api |[as1]_ | |
|
| 67 |
++-------------+------------------------------------------+------------+ |
|
| 68 |
+| | | | |
|
| 69 |
++-------------+------------------------------------------+------------+ |
|
| 70 |
+ |
|
| 71 |
+.. [as1] first functional devstack plugin, hence why used in most of |
|
| 72 |
+ the examples. |
| ... | ... |
@@ -2,78 +2,83 @@ |
| 2 | 2 |
Plugins |
| 3 | 3 |
======= |
| 4 | 4 |
|
| 5 |
-DevStack has a couple of plugin mechanisms to allow easily adding |
|
| 6 |
-support for additional projects and features. |
|
| 5 |
+The OpenStack ecosystem is wide and deep, and only growing more so |
|
| 6 |
+every day. The value of DevStack is that it's simple enough to |
|
| 7 |
+understand what it's doing clearly. And yet we'd like to support as |
|
| 8 |
+much of the OpenStack Ecosystem as possible. We do that with plugins. |
|
| 7 | 9 |
|
| 8 |
-Extras.d Hooks |
|
| 9 |
-============== |
|
| 10 |
+DevStack plugins are bits of bash code that live outside the DevStack |
|
| 11 |
+tree. They are called through a strong contract, so these plugins can |
|
| 12 |
+be sure that they will continue to work in the future as DevStack |
|
| 13 |
+evolves. |
|
| 10 | 14 |
|
| 11 |
-These hooks are an extension of the service calls in |
|
| 12 |
-``stack.sh`` at specific points in its run, plus ``unstack.sh`` and |
|
| 13 |
-``clean.sh``. A number of the higher-layer projects are implemented in |
|
| 14 |
-DevStack using this mechanism. |
|
| 15 |
+Plugin Interface |
|
| 16 |
+================ |
|
| 15 | 17 |
|
| 16 |
-The script in ``extras.d`` is expected to be mostly a dispatcher to |
|
| 17 |
-functions in a ``lib/*`` script. The scripts are named with a |
|
| 18 |
-zero-padded two digits sequence number prefix to control the order that |
|
| 19 |
-the scripts are called, and with a suffix of ``.sh``. DevStack reserves |
|
| 20 |
-for itself the sequence numbers 00 through 09 and 90 through 99. |
|
| 18 |
+DevStack supports a standard mechansim for including plugins from |
|
| 19 |
+external repositories. The plugin interface assumes the following: |
|
| 21 | 20 |
|
| 22 |
-Below is a template that shows handlers for the possible command-line |
|
| 23 |
-arguments: |
|
| 21 |
+An external git repository that includes a ``devstack/`` top level |
|
| 22 |
+directory. Inside this directory there can be 2 files. |
|
| 24 | 23 |
|
| 25 |
-:: |
|
| 24 |
+- ``settings`` - a file containing global variables that will be |
|
| 25 |
+ sourced very early in the process. This is helpful if other plugins |
|
| 26 |
+ might depend on this one, and need access to global variables to do |
|
| 27 |
+ their work. |
|
| 26 | 28 |
|
| 27 |
- # template.sh - DevStack extras.d dispatch script template |
|
| 29 |
+ Your settings should include any ``enable_service`` lines required |
|
| 30 |
+ by your plugin. This is especially important if you are kicking off |
|
| 31 |
+ services using ``run_process`` as it only works with enabled |
|
| 32 |
+ services. |
|
| 28 | 33 |
|
| 29 |
- # check for service enabled |
|
| 30 |
- if is_service_enabled template; then |
|
| 34 |
+ Be careful to allow users to override global-variables for |
|
| 35 |
+ customizing their environment. Usually it is best to provide a |
|
| 36 |
+ default value only if the variable is unset or empty; e.g. in bash |
|
| 37 |
+ syntax ``FOO=${FOO:-default}``.
|
|
| 31 | 38 |
|
| 32 |
- if [[ "$1" == "source" ]]; then |
|
| 33 |
- # Initial source of lib script |
|
| 34 |
- source $TOP_DIR/lib/template |
|
| 35 |
- fi |
|
| 39 |
+- ``plugin.sh`` - the actual plugin. It is executed by devstack at |
|
| 40 |
+ well defined points during a ``stack.sh`` run. The plugin.sh |
|
| 41 |
+ internal structure is discussed bellow. |
|
| 36 | 42 |
|
| 37 |
- if [[ "$1" == "stack" && "$2" == "pre-install" ]]; then |
|
| 38 |
- # Set up system services |
|
| 39 |
- echo_summary "Configuring system services Template" |
|
| 40 |
- install_package cowsay |
|
| 41 | 43 |
|
| 42 |
- elif [[ "$1" == "stack" && "$2" == "install" ]]; then |
|
| 43 |
- # Perform installation of service source |
|
| 44 |
- echo_summary "Installing Template" |
|
| 45 |
- install_template |
|
| 44 |
+Plugins are registered by adding the following to the localrc section |
|
| 45 |
+of ``local.conf``. |
|
| 46 | 46 |
|
| 47 |
- elif [[ "$1" == "stack" && "$2" == "post-config" ]]; then |
|
| 48 |
- # Configure after the other layer 1 and 2 services have been configured |
|
| 49 |
- echo_summary "Configuring Template" |
|
| 50 |
- configure_template |
|
| 47 |
+They are added in the following format:: |
|
| 51 | 48 |
|
| 52 |
- elif [[ "$1" == "stack" && "$2" == "extra" ]]; then |
|
| 53 |
- # Initialize and start the template service |
|
| 54 |
- echo_summary "Initializing Template" |
|
| 55 |
- ##init_template |
|
| 56 |
- fi |
|
| 49 |
+ [[local|localrc]] |
|
| 50 |
+ enable_plugin <NAME> <GITURL> [GITREF] |
|
| 57 | 51 |
|
| 58 |
- if [[ "$1" == "unstack" ]]; then |
|
| 59 |
- # Shut down template services |
|
| 60 |
- # no-op |
|
| 61 |
- : |
|
| 62 |
- fi |
|
| 52 |
+- ``name`` - an arbitrary name. (ex: glustfs, docker, zaqar, congress) |
|
| 53 |
+- ``giturl`` - a valid git url that can be cloned |
|
| 54 |
+- ``gitref`` - an optional git ref (branch / ref / tag) that will be |
|
| 55 |
+ cloned. Defaults to master. |
|
| 63 | 56 |
|
| 64 |
- if [[ "$1" == "clean" ]]; then |
|
| 65 |
- # Remove state and transient data |
|
| 66 |
- # Remember clean.sh first calls unstack.sh |
|
| 67 |
- # no-op |
|
| 68 |
- : |
|
| 69 |
- fi |
|
| 70 |
- fi |
|
| 57 |
+An example would be as follows:: |
|
| 71 | 58 |
|
| 72 |
-The arguments are: |
|
| 59 |
+ enable_plugin ec2api git://git.openstack.org/stackforge/ec2api |
|
| 60 |
+ |
|
| 61 |
+plugin.sh contract |
|
| 62 |
+================== |
|
| 63 |
+ |
|
| 64 |
+``plugin.sh`` is a bash script that will be called at specific points |
|
| 65 |
+during ``stack.sh``, ``unstack.sh``, and ``clean.sh``. It will be |
|
| 66 |
+called in the following way:: |
|
| 67 |
+ |
|
| 68 |
+ source $PATH/TO/plugin.sh <mode> [phase] |
|
| 73 | 69 |
|
| 74 |
-- **source** - Called by each script that utilizes ``extras.d`` hooks; |
|
| 75 |
- this replaces directly sourcing the ``lib/*`` script. |
|
| 76 |
-- **stack** - Called by ``stack.sh`` three times for different phases |
|
| 70 |
+``mode`` can be thought of as the major mode being called, currently |
|
| 71 |
+one of: ``stack``, ``unstack``, ``clean``. ``phase`` is used by modes |
|
| 72 |
+which have multiple points during their run where it's necessary to |
|
| 73 |
+be able to execute code. All existing ``mode`` and ``phase`` points |
|
| 74 |
+are considered **strong contracts** and won't be removed without a |
|
| 75 |
+reasonable deprecation period. Additional new ``mode`` or ``phase`` |
|
| 76 |
+points may be added at any time if we discover we need them to support |
|
| 77 |
+additional kinds of plugins in devstack. |
|
| 78 |
+ |
|
| 79 |
+The current full list of ``mode`` and ``phase`` are: |
|
| 80 |
+ |
|
| 81 |
+- **stack** - Called by ``stack.sh`` four times for different phases |
|
| 77 | 82 |
of its run: |
| 78 | 83 |
|
| 79 | 84 |
- **pre-install** - Called after system (OS) setup is complete and |
| ... | ... |
@@ -84,106 +89,90 @@ The arguments are: |
| 84 | 84 |
been configured. All configuration files for enabled services |
| 85 | 85 |
should exist at this point. |
| 86 | 86 |
- **extra** - Called near the end after layer 1 and 2 services have |
| 87 |
- been started. This is the existing hook and has not otherwise |
|
| 88 |
- changed. |
|
| 87 |
+ been started. |
|
| 89 | 88 |
|
| 90 | 89 |
- **unstack** - Called by ``unstack.sh`` before other services are shut |
| 91 | 90 |
down. |
| 92 | 91 |
- **clean** - Called by ``clean.sh`` before other services are cleaned, |
| 93 | 92 |
but after ``unstack.sh`` has been called. |
| 94 | 93 |
|
| 94 |
+Example plugin |
|
| 95 |
+==================== |
|
| 95 | 96 |
|
| 96 |
-Externally Hosted Plugins |
|
| 97 |
-========================= |
|
| 97 |
+An example plugin would look something as follows. |
|
| 98 | 98 |
|
| 99 |
-Based on the extras.d hooks, DevStack supports a standard mechansim |
|
| 100 |
-for including plugins from external repositories. The plugin interface |
|
| 101 |
-assumes the following: |
|
| 99 |
+``devstack/settings``:: |
|
| 102 | 100 |
|
| 103 |
-An external git repository that includes a ``devstack/`` top level |
|
| 104 |
-directory. Inside this directory there can be 2 files. |
|
| 101 |
+ # settings file for template |
|
| 102 |
+ enable_service template |
|
| 105 | 103 |
|
| 106 |
-- ``settings`` - a file containing global variables that will be |
|
| 107 |
- sourced very early in the process. This is helpful if other plugins |
|
| 108 |
- might depend on this one, and need access to global variables to do |
|
| 109 |
- their work. |
|
| 110 | 104 |
|
| 111 |
- Your settings should include any ``enable_service`` lines required |
|
| 112 |
- by your plugin. This is especially important if you are kicking off |
|
| 113 |
- services using ``run_process`` as it only works with enabled |
|
| 114 |
- services. |
|
| 105 |
+``devstack/plugin.sh``:: |
|
| 115 | 106 |
|
| 116 |
- Be careful to allow users to override global-variables for |
|
| 117 |
- customizing their environment. Usually it is best to provide a |
|
| 118 |
- default value only if the variable is unset or empty; e.g. in bash |
|
| 119 |
- syntax ``FOO=${FOO:-default}``.
|
|
| 107 |
+ # plugin.sh - DevStack plugin.sh dispatch script template |
|
| 120 | 108 |
|
| 121 |
-- ``plugin.sh`` - the actual plugin. It will be executed by devstack |
|
| 122 |
- during it's run. The run order will be done in the registration |
|
| 123 |
- order for these plugins, and will occur immediately after all in |
|
| 124 |
- tree extras.d dispatch at the phase in question. The plugin.sh |
|
| 125 |
- looks like the extras.d dispatcher above. |
|
| 109 |
+ function install_template {
|
|
| 110 |
+ ... |
|
| 111 |
+ } |
|
| 126 | 112 |
|
| 127 |
-Plugins are registered by adding the following to the localrc section |
|
| 128 |
-of ``local.conf``. |
|
| 113 |
+ function init_template {
|
|
| 114 |
+ ... |
|
| 115 |
+ } |
|
| 129 | 116 |
|
| 130 |
-They are added in the following format:: |
|
| 117 |
+ function configure_template {
|
|
| 118 |
+ ... |
|
| 119 |
+ } |
|
| 131 | 120 |
|
| 132 |
- [[local|localrc]] |
|
| 133 |
- enable_plugin <NAME> <GITURL> [GITREF] |
|
| 121 |
+ # check for service enabled |
|
| 122 |
+ if is_service_enabled template; then |
|
| 134 | 123 |
|
| 135 |
-- ``name`` - an arbitrary name. (ex: glustfs, docker, zaqar, congress) |
|
| 136 |
-- ``giturl`` - a valid git url that can be cloned |
|
| 137 |
-- ``gitref`` - an optional git ref (branch / ref / tag) that will be |
|
| 138 |
- cloned. Defaults to master. |
|
| 124 |
+ if [[ "$1" == "stack" && "$2" == "pre-install" ]]; then |
|
| 125 |
+ # Set up system services |
|
| 126 |
+ echo_summary "Configuring system services Template" |
|
| 127 |
+ install_package cowsay |
|
| 139 | 128 |
|
| 140 |
-An example would be as follows:: |
|
| 129 |
+ elif [[ "$1" == "stack" && "$2" == "install" ]]; then |
|
| 130 |
+ # Perform installation of service source |
|
| 131 |
+ echo_summary "Installing Template" |
|
| 132 |
+ install_template |
|
| 141 | 133 |
|
| 142 |
- enable_plugin ec2api git://git.openstack.org/stackforge/ec2api |
|
| 134 |
+ elif [[ "$1" == "stack" && "$2" == "post-config" ]]; then |
|
| 135 |
+ # Configure after the other layer 1 and 2 services have been configured |
|
| 136 |
+ echo_summary "Configuring Template" |
|
| 137 |
+ configure_template |
|
| 138 |
+ |
|
| 139 |
+ elif [[ "$1" == "stack" && "$2" == "extra" ]]; then |
|
| 140 |
+ # Initialize and start the template service |
|
| 141 |
+ echo_summary "Initializing Template" |
|
| 142 |
+ init_template |
|
| 143 |
+ fi |
|
| 144 |
+ |
|
| 145 |
+ if [[ "$1" == "unstack" ]]; then |
|
| 146 |
+ # Shut down template services |
|
| 147 |
+ # no-op |
|
| 148 |
+ : |
|
| 149 |
+ fi |
|
| 143 | 150 |
|
| 144 |
-Plugins for gate jobs |
|
| 145 |
- |
|
| 146 |
-All OpenStack plugins that wish to be used as gate jobs need to exist |
|
| 147 |
-in OpenStack's gerrit. Both ``openstack`` namespace and ``stackforge`` |
|
| 148 |
-namespace are fine. This allows testing of the plugin as well as |
|
| 149 |
-provides network isolation against upstream git repository failures |
|
| 150 |
-(which we see often enough to be an issue). |
|
| 151 |
- |
|
| 152 |
-Ideally plugins will be implemented as ``devstack`` directory inside |
|
| 153 |
-the project they are testing. For example, the stackforge/ec2-api |
|
| 154 |
-project has it's pluggin support in it's tree. |
|
| 155 |
- |
|
| 156 |
-In the cases where there is no "project tree" per say (like |
|
| 157 |
-integrating a backend storage configuration such as ceph or glusterfs) |
|
| 158 |
-it's also allowed to build a dedicated |
|
| 159 |
-``stackforge/devstack-plugin-FOO`` project to house the plugin. |
|
| 160 |
- |
|
| 161 |
-Note jobs must not require cloning of repositories during tests. |
|
| 162 |
-Tests must list their repository in the ``PROJECTS`` variable for |
|
| 163 |
-`devstack-gate |
|
| 164 |
-<https://git.openstack.org/cgit/openstack-infra/devstack-gate/tree/devstack-vm-gate-wrap.sh>`_ |
|
| 165 |
-for the repository to be available to the test. Further information |
|
| 166 |
-is provided in the project creator's guide. |
|
| 167 |
- |
|
| 168 |
-Hypervisor |
|
| 169 |
-========== |
|
| 170 |
- |
|
| 171 |
-Hypervisor plugins are fairly new and condense most hypervisor |
|
| 172 |
-configuration into one place. |
|
| 173 |
- |
|
| 174 |
-The initial plugin implemented was for Docker support and is a useful |
|
| 175 |
-template for the required support. Plugins are placed in |
|
| 176 |
-``lib/nova_plugins`` and named ``hypervisor-<name>`` where ``<name>`` is |
|
| 177 |
-the value of ``VIRT_DRIVER``. Plugins must define the following |
|
| 178 |
-functions: |
|
| 179 |
- |
|
| 180 |
-- ``install_nova_hypervisor`` - install any external requirements |
|
| 181 |
-- ``configure_nova_hypervisor`` - make configuration changes, including |
|
| 182 |
- those to other services |
|
| 183 |
-- ``start_nova_hypervisor`` - start any external services |
|
| 184 |
-- ``stop_nova_hypervisor`` - stop any external services |
|
| 185 |
-- ``cleanup_nova_hypervisor`` - remove transient data and cache |
|
| 151 |
+ if [[ "$1" == "clean" ]]; then |
|
| 152 |
+ # Remove state and transient data |
|
| 153 |
+ # Remember clean.sh first calls unstack.sh |
|
| 154 |
+ # no-op |
|
| 155 |
+ : |
|
| 156 |
+ fi |
|
| 157 |
+ fi |
|
| 158 |
+ |
|
| 159 |
+Plugin Execution Order |
|
| 160 |
+====================== |
|
| 161 |
+ |
|
| 162 |
+Plugins are run after in tree services at each of the stages |
|
| 163 |
+above. For example, if you need something to happen before Keystone |
|
| 164 |
+starts, you should do that at the ``post-config`` phase. |
|
| 165 |
+ |
|
| 166 |
+Multiple plugins can be specified in your ``local.conf``. When that |
|
| 167 |
+happens the plugins will be executed **in order** at each phase. This |
|
| 168 |
+allows plugins to conceptually depend on each other through |
|
| 169 |
+documenting to the user the order they must be declared. A formal |
|
| 170 |
+dependency mechanism is beyond the scope of the current work. |
|
| 186 | 171 |
|
| 187 | 172 |
System Packages |
| 188 | 173 |
=============== |
| ... | ... |
@@ -205,3 +194,47 @@ repository: |
| 205 | 205 |
|
| 206 | 206 |
- ``./devstack/files/rpms-suse/$plugin_name`` - Packages to install when |
| 207 | 207 |
running on SUSE Linux or openSUSE. |
| 208 |
+ |
|
| 209 |
+ |
|
| 210 |
+Using Plugins in the OpenStack Gate |
|
| 211 |
+=================================== |
|
| 212 |
+ |
|
| 213 |
+For everyday use, DevStack plugins can exist in any git tree that's |
|
| 214 |
+accessible on the internet. However, when using DevStack plugins in |
|
| 215 |
+the OpenStack gate, they must live in projects in OpenStack's |
|
| 216 |
+gerrit. Both ``openstack`` namespace and ``stackforge`` namespace are |
|
| 217 |
+fine. This allows testing of the plugin as well as provides network |
|
| 218 |
+isolation against upstream git repository failures (which we see often |
|
| 219 |
+enough to be an issue). |
|
| 220 |
+ |
|
| 221 |
+Ideally a plugin will be included within the ``devstack`` directory of |
|
| 222 |
+the project they are being tested. For example, the stackforge/ec2-api |
|
| 223 |
+project has its pluggin support in its own tree. |
|
| 224 |
+ |
|
| 225 |
+However, some times a DevStack plugin might be used solely to |
|
| 226 |
+configure a backend service that will be used by the rest of |
|
| 227 |
+OpenStack, so there is no "project tree" per say. Good examples |
|
| 228 |
+include: integration of back end storage (e.g. ceph or glusterfs), |
|
| 229 |
+integration of SDN controllers (e.g. ovn, OpenDayLight), or |
|
| 230 |
+integration of alternate RPC systems (e.g. zmq, qpid). In these cases |
|
| 231 |
+the best practice is to build a dedicated |
|
| 232 |
+``stackforge/devstack-plugin-FOO`` project. |
|
| 233 |
+ |
|
| 234 |
+To enable a plugin to be used in a gate job, the following lines will |
|
| 235 |
+be needed in your project.yaml definition:: |
|
| 236 |
+ |
|
| 237 |
+ # Because we are testing a non standard project, add the |
|
| 238 |
+ # our project repository. This makes zuul do the right |
|
| 239 |
+ # reference magic for testing changes. |
|
| 240 |
+ export PROJECTS="stackforge/ec2-api $PROJECTS" |
|
| 241 |
+ |
|
| 242 |
+ # note the actual url here is somewhat irrelevant because it |
|
| 243 |
+ # caches in nodepool, however make it a valid url for |
|
| 244 |
+ # documentation purposes. |
|
| 245 |
+ export DEVSTACK_LOCAL_CONFIG="enable_plugin ec2-api git://git.openstack.org/stackforge/ec2-api" |
|
| 246 |
+ |
|
| 247 |
+See Also |
|
| 248 |
+======== |
|
| 249 |
+ |
|
| 250 |
+For additional inspiration on devstack plugins you can check out the |
|
| 251 |
+`Plugin Registry <plugin-registry.html>`_. |