Browse code

Implement devstack external plugins

This is an initial pass at plugin infrastructure for devstack which
allows specifying an external repository via:

enable_plugin <name> <giturl> [branch]

It implements the devstack specification for this at
I173dee3d57967b1d2ffd30e4868a2832aeac97ce

Change-Id: I8e4175313b3cf0b12e981122358b1288a7eb0746

Sean Dague authored on 2014/12/18 23:44:56
Showing 4 changed files
... ...
@@ -92,6 +92,45 @@ The arguments are:
92 92
 -  **clean** - Called by ``clean.sh`` before other services are cleaned,
93 93
    but after ``unstack.sh`` has been called.
94 94
 
95
+
96
+Externally Hosted Plugins
97
+=========================
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:
102
+
103
+An external git repository that includes a ``devstack/`` top level
104
+directory. Inside this directory there can be 2 files.
105
+
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
+- ``plugin.sh`` - the actual plugin. It will be executed by devstack
111
+  during it's run. The run order will be done in the registration
112
+  order for these plugins, and will occur immediately after all in
113
+  tree extras.d dispatch at the phase in question.  The plugin.sh
114
+  looks like the extras.d dispatcher above **except** it should not
115
+  include the is_service_enabled conditional. All external plugins are
116
+  always assumed to be enabled.
117
+
118
+Plugins are registered by adding the following to the localrc section
119
+of ``local.conf``.
120
+
121
+They are added in the following format::
122
+
123
+  enable_plugin <NAME> <GITURL> [GITREF]
124
+
125
+- ``name`` - an arbitrary name. (ex: glustfs, docker, zaqar, congress)
126
+- ``giturl`` - a valid git url that can be cloned
127
+- ``gitref`` - an optional git ref (branch / ref / tag) that will be
128
+  cloned. Defaults to master.
129
+
130
+An example would be as follows::
131
+
132
+  enable_plugin glusterfs https://github.com/sdague/devstack-plugins glusterfs
133
+
95 134
 Hypervisor
96 135
 ==========
97 136
 
... ...
@@ -44,7 +44,6 @@ declare -A GITREPO
44 44
 declare -A GITBRANCH
45 45
 declare -A GITDIR
46 46
 
47
-
48 47
 # Config Functions
49 48
 # ================
50 49
 
... ...
@@ -1722,6 +1721,97 @@ function setup_package {
1722 1722
     fi
1723 1723
 }
1724 1724
 
1725
+# Plugin Functions
1726
+# =================
1727
+
1728
+DEVSTACK_PLUGINS=${DEVSTACK_PLUGINS:-""}
1729
+
1730
+# enable_plugin <name> <url> [branch]
1731
+#
1732
+# ``name`` is an arbitrary name - (aka: glusterfs, nova-docker, zaqar)
1733
+# ``url`` is a git url
1734
+# ``branch`` is a gitref. If it's not set, defaults to master
1735
+function enable_plugin {
1736
+    local name=$1
1737
+    local url=$2
1738
+    local branch=${3:-master}
1739
+    DEVSTACK_PLUGINS+=",$name"
1740
+    GITREPO[$name]=$url
1741
+    GITDIR[$name]=$DEST/$name
1742
+    GITBRANCH[$name]=$branch
1743
+}
1744
+
1745
+# fetch_plugins
1746
+#
1747
+# clones all plugins
1748
+function fetch_plugins {
1749
+    local plugins="${DEVSTACK_PLUGINS}"
1750
+    local plugin
1751
+
1752
+    # short circuit if nothing to do
1753
+    if [[ -z $plugins ]]; then
1754
+        return
1755
+    fi
1756
+
1757
+    echo "Fetching devstack plugins"
1758
+    for plugin in ${plugins//,/ }; do
1759
+        git_clone_by_name $plugin
1760
+    done
1761
+}
1762
+
1763
+# load_plugin_settings
1764
+#
1765
+# Load settings from plugins in the order that they were registered
1766
+function load_plugin_settings {
1767
+    local plugins="${DEVSTACK_PLUGINS}"
1768
+    local plugin
1769
+
1770
+    # short circuit if nothing to do
1771
+    if [[ -z $plugins ]]; then
1772
+        return
1773
+    fi
1774
+
1775
+    echo "Loading plugin settings"
1776
+    for plugin in ${plugins//,/ }; do
1777
+        local dir=${GITDIR[$plugin]}
1778
+        # source any known settings
1779
+        if [[ -f $dir/devstack/settings ]]; then
1780
+            source $dir/devstack/settings
1781
+        fi
1782
+    done
1783
+}
1784
+
1785
+# run_plugins
1786
+#
1787
+# Run the devstack/plugin.sh in all the plugin directories. These are
1788
+# run in registration order.
1789
+function run_plugins {
1790
+    local mode=$1
1791
+    local phase=$2
1792
+    for plugin in ${plugins//,/ }; do
1793
+        local dir=${GITDIR[$plugin]}
1794
+        if [[ -f $dir/devstack/plugin.sh ]]; then
1795
+            source $dir/devstack/plugin.sh $mode $phase
1796
+        fi
1797
+    done
1798
+}
1799
+
1800
+function run_phase {
1801
+    local mode=$1
1802
+    local phase=$2
1803
+    if [[ -d $TOP_DIR/extras.d ]]; then
1804
+        for i in $TOP_DIR/extras.d/*.sh; do
1805
+            [[ -r $i ]] && source $i $mode $phase
1806
+        done
1807
+    fi
1808
+    # the source phase corresponds to settings loading in plugins
1809
+    if [[ "$mode" == "source" ]]; then
1810
+        load_plugin_settings
1811
+    else
1812
+        run_plugins $mode $phase
1813
+    fi
1814
+}
1815
+
1725 1816
 
1726 1817
 # Service Functions
1727 1818
 # =================
... ...
@@ -564,15 +564,14 @@ source $TOP_DIR/lib/neutron
564 564
 source $TOP_DIR/lib/ldap
565 565
 source $TOP_DIR/lib/dstat
566 566
 
567
+# Clone all external plugins
568
+fetch_plugins
569
+
567 570
 # Extras Source
568 571
 # --------------
569 572
 
570 573
 # Phase: source
571
-if [[ -d $TOP_DIR/extras.d ]]; then
572
-    for i in $TOP_DIR/extras.d/*.sh; do
573
-        [[ -r $i ]] && source $i source
574
-    done
575
-fi
574
+run_phase source
576 575
 
577 576
 # Interactive Configuration
578 577
 # -------------------------
... ...
@@ -714,12 +713,7 @@ source $TOP_DIR/tools/fixup_stuff.sh
714 714
 # ------------------
715 715
 
716 716
 # Phase: pre-install
717
-if [[ -d $TOP_DIR/extras.d ]]; then
718
-    for i in $TOP_DIR/extras.d/*.sh; do
719
-        [[ -r $i ]] && source $i stack pre-install
720
-    done
721
-fi
722
-
717
+run_phase stack pre-install
723 718
 
724 719
 install_rpc_backend
725 720
 
... ...
@@ -865,11 +859,7 @@ fi
865 865
 # --------------
866 866
 
867 867
 # Phase: install
868
-if [[ -d $TOP_DIR/extras.d ]]; then
869
-    for i in $TOP_DIR/extras.d/*.sh; do
870
-        [[ -r $i ]] && source $i stack install
871
-    done
872
-fi
868
+run_phase stack install
873 869
 
874 870
 if [[ $TRACK_DEPENDS = True ]]; then
875 871
     $DEST/.venv/bin/pip freeze > $DEST/requires-post-pip
... ...
@@ -1142,11 +1132,7 @@ fi
1142 1142
 # ====================
1143 1143
 
1144 1144
 # Phase: post-config
1145
-if [[ -d $TOP_DIR/extras.d ]]; then
1146
-    for i in $TOP_DIR/extras.d/*.sh; do
1147
-        [[ -r $i ]] && source $i stack post-config
1148
-    done
1149
-fi
1145
+run_phase stack post-config
1150 1146
 
1151 1147
 
1152 1148
 # Local Configuration
... ...
@@ -1328,11 +1314,7 @@ merge_config_group $TOP_DIR/local.conf extra
1328 1328
 # ==========
1329 1329
 
1330 1330
 # Phase: extra
1331
-if [[ -d $TOP_DIR/extras.d ]]; then
1332
-    for i in $TOP_DIR/extras.d/*.sh; do
1333
-        [[ -r $i ]] && source $i stack extra
1334
-    done
1335
-fi
1331
+run_phase stack extra
1336 1332
 
1337 1333
 # Local Configuration
1338 1334
 # ===================
... ...
@@ -66,6 +66,8 @@ if [[ -d $TOP_DIR/extras.d ]]; then
66 66
     done
67 67
 fi
68 68
 
69
+load_plugin_settings
70
+
69 71
 # Determine what system we are running on.  This provides ``os_VENDOR``,
70 72
 # ``os_RELEASE``, ``os_UPDATE``, ``os_PACKAGE``, ``os_CODENAME``
71 73
 GetOSVersion
... ...
@@ -78,11 +80,7 @@ fi
78 78
 # ==========
79 79
 
80 80
 # Phase: unstack
81
-if [[ -d $TOP_DIR/extras.d ]]; then
82
-    for i in $TOP_DIR/extras.d/*.sh; do
83
-        [[ -r $i ]] && source $i unstack
84
-    done
85
-fi
81
+run_phase unstack
86 82
 
87 83
 if [[ "$Q_USE_DEBUG_COMMAND" == "True" ]]; then
88 84
     source $TOP_DIR/openrc