Merge "neutron: use config files from neutron-*aas repos"
diff --git a/doc/source/plugins.rst b/doc/source/plugins.rst
index 485cd0f..d1f7377 100644
--- a/doc/source/plugins.rst
+++ b/doc/source/plugins.rst
@@ -92,6 +92,45 @@
 -  **clean** - Called by ``clean.sh`` before other services are cleaned,
    but after ``unstack.sh`` has been called.
 
+
+Externally Hosted Plugins
+=========================
+
+Based on the extras.d hooks, DevStack supports a standard mechansim
+for including plugins from external repositories. The plugin interface
+assumes the following:
+
+An external git repository that includes a ``devstack/`` top level
+directory. Inside this directory there can be 2 files.
+
+- ``settings`` - a file containing global variables that will be
+  sourced very early in the process. This is helpful if other plugins
+  might depend on this one, and need access to global variables to do
+  their work.
+- ``plugin.sh`` - the actual plugin. It will be executed by devstack
+  during it's run. The run order will be done in the registration
+  order for these plugins, and will occur immediately after all in
+  tree extras.d dispatch at the phase in question.  The plugin.sh
+  looks like the extras.d dispatcher above **except** it should not
+  include the is_service_enabled conditional. All external plugins are
+  always assumed to be enabled.
+
+Plugins are registered by adding the following to the localrc section
+of ``local.conf``.
+
+They are added in the following format::
+
+  enable_plugin <NAME> <GITURL> [GITREF]
+
+- ``name`` - an arbitrary name. (ex: glustfs, docker, zaqar, congress)
+- ``giturl`` - a valid git url that can be cloned
+- ``gitref`` - an optional git ref (branch / ref / tag) that will be
+  cloned. Defaults to master.
+
+An example would be as follows::
+
+  enable_plugin glusterfs https://github.com/sdague/devstack-plugins glusterfs
+
 Hypervisor
 ==========
 
diff --git a/driver_certs/cinder_driver_cert.sh b/driver_certs/cinder_driver_cert.sh
index 2757038..d066e06 100755
--- a/driver_certs/cinder_driver_cert.sh
+++ b/driver_certs/cinder_driver_cert.sh
@@ -94,7 +94,7 @@
 
 # run tempest api/volume/test_*
 log_message "Run the actual tempest volume tests (./tools/pretty_tox.sh volume)...", True
-./tools/pretty_tox.sh api.volume 2>&1 | tee -a $TEMPFILE
+./tools/pretty_tox.sh volume 2>&1 | tee -a $TEMPFILE
 if [[ $? = 0 ]]; then
     log_message "CONGRATULATIONS!!!  Device driver PASSED!", True
     log_message "Submit output: ($TEMPFILE)"
diff --git a/files/debs/neutron b/files/debs/neutron
index a48a800..fd99677 100644
--- a/files/debs/neutron
+++ b/files/debs/neutron
@@ -24,3 +24,4 @@
 sqlite3
 vlan
 radvd # NOPRIME
+uuid-runtime
diff --git a/functions-common b/functions-common
index 40a0d2b..3b4309a 100644
--- a/functions-common
+++ b/functions-common
@@ -44,7 +44,6 @@
 declare -A GITBRANCH
 declare -A GITDIR
 
-
 # Config Functions
 # ================
 
@@ -148,6 +147,21 @@
     $xtrace
 }
 
+function inidelete {
+    local xtrace=$(set +o | grep xtrace)
+    set +o xtrace
+    local file=$1
+    local section=$2
+    local option=$3
+
+    [[ -z $section || -z $option ]] && return
+
+    # Remove old values
+    sed -i -e "/^\[$section\]/,/^\[.*\]/ { /^$option[ \t]*=/ d; }" "$file"
+
+    $xtrace
+}
+
 # Set an option in an INI file
 # iniset config-file section option value
 function iniset {
@@ -997,7 +1011,6 @@
     fi
     if [[ -z "$DISTRO" ]]; then
         GetDistro
-        echo "Found Distro $DISTRO"
     fi
     for service in ${services//,/ }; do
         # Allow individual services to specify dependencies
@@ -1722,6 +1735,100 @@
     fi
 }
 
+# Plugin Functions
+# =================
+
+DEVSTACK_PLUGINS=${DEVSTACK_PLUGINS:-""}
+
+# enable_plugin <name> <url> [branch]
+#
+# ``name`` is an arbitrary name - (aka: glusterfs, nova-docker, zaqar)
+# ``url`` is a git url
+# ``branch`` is a gitref. If it's not set, defaults to master
+function enable_plugin {
+    local name=$1
+    local url=$2
+    local branch=${3:-master}
+    DEVSTACK_PLUGINS+=",$name"
+    GITREPO[$name]=$url
+    GITDIR[$name]=$DEST/$name
+    GITBRANCH[$name]=$branch
+}
+
+# fetch_plugins
+#
+# clones all plugins
+function fetch_plugins {
+    local plugins="${DEVSTACK_PLUGINS}"
+    local plugin
+
+    # short circuit if nothing to do
+    if [[ -z $plugins ]]; then
+        return
+    fi
+
+    echo "Fetching devstack plugins"
+    for plugin in ${plugins//,/ }; do
+        git_clone_by_name $plugin
+    done
+}
+
+# load_plugin_settings
+#
+# Load settings from plugins in the order that they were registered
+function load_plugin_settings {
+    local plugins="${DEVSTACK_PLUGINS}"
+    local plugin
+
+    # short circuit if nothing to do
+    if [[ -z $plugins ]]; then
+        return
+    fi
+
+    echo "Loading plugin settings"
+    for plugin in ${plugins//,/ }; do
+        local dir=${GITDIR[$plugin]}
+        # source any known settings
+        if [[ -f $dir/devstack/settings ]]; then
+            source $dir/devstack/settings
+        fi
+    done
+}
+
+# run_plugins
+#
+# Run the devstack/plugin.sh in all the plugin directories. These are
+# run in registration order.
+function run_plugins {
+    local mode=$1
+    local phase=$2
+
+    local plugins="${DEVSTACK_PLUGINS}"
+    local plugin
+    for plugin in ${plugins//,/ }; do
+        local dir=${GITDIR[$plugin]}
+        if [[ -f $dir/devstack/plugin.sh ]]; then
+            source $dir/devstack/plugin.sh $mode $phase
+        fi
+    done
+}
+
+function run_phase {
+    local mode=$1
+    local phase=$2
+    if [[ -d $TOP_DIR/extras.d ]]; then
+        for i in $TOP_DIR/extras.d/*.sh; do
+            [[ -r $i ]] && source $i $mode $phase
+        done
+    fi
+    # the source phase corresponds to settings loading in plugins
+    if [[ "$mode" == "source" ]]; then
+        load_plugin_settings
+    else
+        run_plugins $mode $phase
+    fi
+}
+
 
 # Service Functions
 # =================
diff --git a/lib/config b/lib/config
index c0756bf..31c6fa6 100644
--- a/lib/config
+++ b/lib/config
@@ -144,6 +144,7 @@
                     else {
                         # For multiline, invoke the ini routines in the reverse order
                         count = cfg_attr_count[section, attr]
+                        print "inidelete " configfile " " section " " attr
                         print "iniset " configfile " " section " " attr " \"" cfg_attr[section, attr, count - 1] "\""
                         for (l = count -2; l >= 0; l--)
                             print "iniadd_literal " configfile " " section " " attr " \"" cfg_attr[section, attr, l] "\""
diff --git a/lib/databases/mysql b/lib/databases/mysql
index d39d966..0e423de 100644
--- a/lib/databases/mysql
+++ b/lib/databases/mysql
@@ -23,22 +23,27 @@
     if is_ubuntu; then
         # Get ruthless with mysql
         stop_service $MYSQL
-        apt_get purge -y mysql*
+        uninstall_package mysql-server mariadb-server
         sudo rm -rf /var/lib/mysql
         sudo rm -rf /etc/mysql
         return
     elif is_fedora; then
         if [[ $DISTRO =~ (rhel6) ]]; then
-            MYSQL=mysqld
+            stop_service mysqld
+            uninstall_package mysql-server
+            sudo rm -rf /var/lib/mysql
         else
-            MYSQL=mariadb
+            stop_service mariadb
+            uninstall_package mariadb-server
+            sudo rm -rf /var/lib/mysql
         fi
     elif is_suse; then
-        MYSQL=mysql
+        stop_service mysql
+        uninstall_package mysql-community-server
+        sudo rm -rf /var/lib/mysql
     else
         return
     fi
-    stop_service $MYSQL
 }
 
 function recreate_database_mysql {
diff --git a/lib/heat b/lib/heat
index 49ed533..544ec45 100644
--- a/lib/heat
+++ b/lib/heat
@@ -38,6 +38,7 @@
 HEAT_TEMPLATES_REPO_DIR=$DEST/heat-templates
 HEAT_AUTH_CACHE_DIR=${HEAT_AUTH_CACHE_DIR:-/var/cache/heat}
 HEAT_STANDALONE=`trueorfalse False $HEAT_STANDALONE`
+HEAT_ENABLE_ADOPT_ABANDON=`trueorfalse False $HEAT_ENABLE_ADOPT_ABANDON`
 HEAT_CONF_DIR=/etc/heat
 HEAT_CONF=$HEAT_CONF_DIR/heat.conf
 HEAT_ENV_DIR=$HEAT_CONF_DIR/environment.d
@@ -73,7 +74,6 @@
 
 # configure_heat() - Set config files, create data dirs, etc
 function configure_heat {
-    setup_develop $HEAT_DIR
     if [[ "$HEAT_STANDALONE" = "True" ]]; then
         setup_develop $HEAT_DIR/contrib/heat_keystoneclient_v2
     fi
@@ -152,6 +152,11 @@
         iniset $HEAT_CONF clients_cinder ca_file $SSL_BUNDLE_FILE
     fi
 
+    if [[ "$HEAT_ENABLE_ADOPT_ABANDON" = "True" ]]; then
+        iniset $HEAT_CONF DEFAULT enable_stack_adopt true
+        iniset $HEAT_CONF DEFAULT enable_stack_abandon true
+    fi
+
     # heat environment
     sudo mkdir -p $HEAT_ENV_DIR
     sudo chown $STACK_USER $HEAT_ENV_DIR
@@ -195,6 +200,7 @@
 # install_heat() - Collect source and prepare
 function install_heat {
     git_clone $HEAT_REPO $HEAT_DIR $HEAT_BRANCH
+    setup_develop $HEAT_DIR
 }
 
 # install_heat_other() - Collect source and prepare
diff --git a/lib/ironic b/lib/ironic
index 3f7ae21..55272b9 100644
--- a/lib/ironic
+++ b/lib/ironic
@@ -536,7 +536,7 @@
             -i ssh_address=$IRONIC_VM_SSH_ADDRESS \
             -i ssh_port=$IRONIC_VM_SSH_PORT \
             -i ssh_username=$IRONIC_SSH_USERNAME \
-            -i ssh_key_filename=$IRONIC_SSH_KEY_DIR/$IRONIC_SSH_KEY_FILENAME"
+            -i ssh_key_filename=$IRONIC_KEY_FILE"
     else
         local ironic_node_cpu=$IRONIC_HW_NODE_CPU
         local ironic_node_ram=$IRONIC_HW_NODE_RAM
diff --git a/lib/keystone b/lib/keystone
index 071dc90..1599fa5 100644
--- a/lib/keystone
+++ b/lib/keystone
@@ -116,7 +116,7 @@
 
 # _cleanup_keystone_apache_wsgi() - Remove wsgi files, disable and remove apache vhost file
 function _cleanup_keystone_apache_wsgi {
-    sudo rm -f $KEYSTONE_WSGI_DIR/*.wsgi
+    sudo rm -f $KEYSTONE_WSGI_DIR/*
     sudo rm -f $(apache_site_config_for keystone)
 }
 
diff --git a/lib/neutron b/lib/neutron
index 111a13b..b4d0b8c 100755
--- a/lib/neutron
+++ b/lib/neutron
@@ -595,6 +595,16 @@
     recreate_database $Q_DB_NAME utf8
     # Run Neutron db migrations
     $NEUTRON_BIN_DIR/neutron-db-manage --config-file $NEUTRON_CONF --config-file /$Q_PLUGIN_CONF_FILE upgrade head
+    for svc in fwaas lbaas vpnaas; do
+        if [ "$svc" = "vpnaas" ]; then
+            q_svc="q-vpn"
+        else
+            q_svc="q-$svc"
+        fi
+        if is_service_enabled $q_svc; then
+            $NEUTRON_BIN_DIR/neutron-db-manage --service $svc --config-file $NEUTRON_CONF --config-file /$Q_PLUGIN_CONF_FILE upgrade head
+        fi
+    done
 }
 
 # install_neutron() - Collect source and prepare
diff --git a/lib/nova b/lib/nova
index cbfbdfa..5ac9ff1 100644
--- a/lib/nova
+++ b/lib/nova
@@ -769,8 +769,8 @@
 }
 
 function start_nova {
-    start_nova_compute
     start_nova_rest
+    start_nova_compute
 }
 
 function stop_nova_compute {
diff --git a/lib/rpc_backend b/lib/rpc_backend
index 400204a..778d466 100644
--- a/lib/rpc_backend
+++ b/lib/rpc_backend
@@ -87,11 +87,20 @@
         fi
     elif is_service_enabled zeromq; then
         if is_fedora; then
-            uninstall_package zeromq python-zmq redis
+            uninstall_package zeromq python-zmq
+            if [ "$ZEROMQ_MATCHMAKER" == "redis" ]; then
+                uninstall_package redis python-redis
+            fi
         elif is_ubuntu; then
-            uninstall_package libzmq1 python-zmq redis-server
+            uninstall_package libzmq1 python-zmq
+            if [ "$ZEROMQ_MATCHMAKER" == "redis" ]; then
+                uninstall_package redis-server python-redis
+            fi
         elif is_suse; then
-            uninstall_package libzmq1 python-pyzmq redis
+            uninstall_package libzmq1 python-pyzmq
+            if [ "$ZEROMQ_MATCHMAKER" == "redis" ]; then
+                uninstall_package redis python-redis
+            fi
         else
             exit_distro_not_supported "zeromq installation"
         fi
@@ -150,11 +159,20 @@
         # but there is a matchmaker driver that works
         # really well & out of the box for multi-node.
         if is_fedora; then
-            install_package zeromq python-zmq redis
+            install_package zeromq python-zmq
+            if [ "$ZEROMQ_MATCHMAKER" == "redis" ]; then
+                install_package redis python-redis
+            fi
         elif is_ubuntu; then
-            install_package libzmq1 python-zmq redis-server
+            install_package libzmq1 python-zmq
+            if [ "$ZEROMQ_MATCHMAKER" == "redis" ]; then
+                install_package redis-server python-redis
+            fi
         elif is_suse; then
-            install_package libzmq1 python-pyzmq redis
+            install_package libzmq1 python-pyzmq
+            if [ "$ZEROMQ_MATCHMAKER" == "redis" ]; then
+                install_package redis python-redis
+            fi
         else
             exit_distro_not_supported "zeromq installation"
         fi
@@ -221,9 +239,9 @@
     local file=$2
     local section=$3
     if is_service_enabled zeromq; then
-        iniset $file $section rpc_backend ${package}.openstack.common.rpc.impl_zmq
+        iniset $file $section rpc_backend "zmq"
         iniset $file $section rpc_zmq_matchmaker \
-            ${package}.openstack.common.rpc.matchmaker_redis.MatchMakerRedis
+            oslo.messaging._drivers.matchmaker_redis.MatchMakerRedis
         # Set MATCHMAKER_REDIS_HOST if running multi-node.
         MATCHMAKER_REDIS_HOST=${MATCHMAKER_REDIS_HOST:-127.0.0.1}
         iniset $file matchmaker_redis host $MATCHMAKER_REDIS_HOST
diff --git a/lib/tempest b/lib/tempest
index 7cac6dd..d31119b 100644
--- a/lib/tempest
+++ b/lib/tempest
@@ -464,6 +464,13 @@
         iniset $TEMPEST_CONFIG compute-feature-enabled suspend False
     fi
 
+    # Libvirt-LXC
+    if [ "$VIRT_DRIVER" = "libvirt" ] && [ "$LIBVIRT_TYPE" = "lxc" ]; then
+        iniset $TEMPEST_CONFIG compute-feature-enabled rescue False
+        iniset $TEMPEST_CONFIG compute-feature-enabled resize False
+        iniset $TEMPEST_CONFIG compute-feature-enabled suspend False
+    fi
+
     # service_available
     for service in ${TEMPEST_SERVICES//,/ }; do
         if is_service_enabled $service ; then
diff --git a/lib/trove b/lib/trove
index d889b05..abf4e87 100644
--- a/lib/trove
+++ b/lib/trove
@@ -123,11 +123,8 @@
     sudo chown -R $STACK_USER: ${TROVE_CONF_DIR}
     sudo chown -R $STACK_USER: ${TROVE_AUTH_CACHE_DIR}
 
-    # Copy api-paste file over to the trove conf dir and configure it
+    # Copy api-paste file over to the trove conf dir
     cp $TROVE_LOCAL_CONF_DIR/api-paste.ini $TROVE_CONF_DIR/api-paste.ini
-    TROVE_API_PASTE_INI=$TROVE_CONF_DIR/api-paste.ini
-
-    configure_auth_token_middleware $TROVE_API_PASTE_INI trove $TROVE_AUTH_CACHE_DIR filter:authtoken
 
     # (Re)create trove conf files
     rm -f $TROVE_CONF_DIR/trove.conf
@@ -141,6 +138,7 @@
     setup_trove_logging $TROVE_CONF_DIR/trove.conf
     iniset $TROVE_CONF_DIR/trove.conf DEFAULT trove_api_workers "$API_WORKERS"
 
+    configure_auth_token_middleware $TROVE_CONF_DIR/trove.conf trove $TROVE_AUTH_CACHE_DIR
 
     # (Re)create trove taskmanager conf file if needed
     if is_service_enabled tr-tmgr; then
diff --git a/stack.sh b/stack.sh
index d6699f5..696dc24 100755
--- a/stack.sh
+++ b/stack.sh
@@ -143,7 +143,7 @@
 
 # Warn users who aren't on an explicitly supported distro, but allow them to
 # override check and attempt installation with ``FORCE=yes ./stack``
-if [[ ! ${DISTRO} =~ (precise|trusty|7.0|wheezy|sid|testing|jessie|f19|f20|f21|rhel6|rhel7) ]]; then
+if [[ ! ${DISTRO} =~ (precise|trusty|7.0|wheezy|sid|testing|jessie|f20|f21|rhel6|rhel7) ]]; then
     echo "WARNING: this script has not been tested on $DISTRO"
     if [[ "$FORCE" != "yes" ]]; then
         die $LINENO "If you wish to run this script anyway run with FORCE=yes"
@@ -570,15 +570,14 @@
 source $TOP_DIR/lib/ldap
 source $TOP_DIR/lib/dstat
 
+# Clone all external plugins
+fetch_plugins
+
 # Extras Source
 # --------------
 
 # Phase: source
-if [[ -d $TOP_DIR/extras.d ]]; then
-    for i in $TOP_DIR/extras.d/*.sh; do
-        [[ -r $i ]] && source $i source
-    done
-fi
+run_phase source
 
 # Interactive Configuration
 # -------------------------
@@ -720,12 +719,7 @@
 # ------------------
 
 # Phase: pre-install
-if [[ -d $TOP_DIR/extras.d ]]; then
-    for i in $TOP_DIR/extras.d/*.sh; do
-        [[ -r $i ]] && source $i stack pre-install
-    done
-fi
-
+run_phase stack pre-install
 
 install_rpc_backend
 
@@ -871,11 +865,7 @@
 # --------------
 
 # Phase: install
-if [[ -d $TOP_DIR/extras.d ]]; then
-    for i in $TOP_DIR/extras.d/*.sh; do
-        [[ -r $i ]] && source $i stack install
-    done
-fi
+run_phase stack install
 
 if [[ $TRACK_DEPENDS = True ]]; then
     $DEST/.venv/bin/pip freeze > $DEST/requires-post-pip
@@ -1040,6 +1030,14 @@
 fi
 
 
+# ZeroMQ
+# ------
+if is_service_enabled zeromq; then
+    echo_summary "Starting zeromq receiver"
+    run_process zeromq "$OSLO_BIN_DIR/oslo-messaging-zmq-receiver"
+fi
+
+
 # Horizon
 # -------
 
@@ -1148,11 +1146,7 @@
 # ====================
 
 # Phase: post-config
-if [[ -d $TOP_DIR/extras.d ]]; then
-    for i in $TOP_DIR/extras.d/*.sh; do
-        [[ -r $i ]] && source $i stack post-config
-    done
-fi
+run_phase stack post-config
 
 
 # Local Configuration
@@ -1222,11 +1216,6 @@
     iniset $NOVA_CONF keymgr fixed_key $(generate_hex_string 32)
 fi
 
-if is_service_enabled zeromq; then
-    echo_summary "Starting zermomq receiver"
-    run_process zeromq "$OSLO_BIN_DIR/oslo-messaging-zmq-receiver"
-fi
-
 # Launch the nova-api and wait for it to answer before continuing
 if is_service_enabled n-api; then
     echo_summary "Starting Nova API"
@@ -1334,11 +1323,7 @@
 # ==========
 
 # Phase: extra
-if [[ -d $TOP_DIR/extras.d ]]; then
-    for i in $TOP_DIR/extras.d/*.sh; do
-        [[ -r $i ]] && source $i stack extra
-    done
-fi
+run_phase stack extra
 
 # Local Configuration
 # ===================
diff --git a/stackrc b/stackrc
index be27dce..355c0dc 100644
--- a/stackrc
+++ b/stackrc
@@ -33,7 +33,8 @@
 # For example, to enable Swift add this to ``local.conf``:
 #  enable_service s-proxy s-object s-container s-account
 # In order to enable Neutron (a single node setup) add the following
-# settings in `` localrc``:
+# settings in ``local.conf``:
+#  [[local|localrc]]
 #  disable_service n-net
 #  enable_service q-svc
 #  enable_service q-agt
@@ -529,8 +530,8 @@
 CIRROS_ARCH=${CIRROS_ARCH:-"x86_64"}
 
 # Set default image based on ``VIRT_DRIVER`` and ``LIBVIRT_TYPE``, either of
-# which may be set in ``localrc``.  Also allow ``DEFAULT_IMAGE_NAME`` and
-# ``IMAGE_URLS`` to be set directly in ``localrc``.
+# which may be set in ``local.conf``.  Also allow ``DEFAULT_IMAGE_NAME`` and
+# ``IMAGE_URLS`` to be set in the `localrc` section of ``local.conf``.
 case "$VIRT_DRIVER" in
     openvz)
         DEFAULT_IMAGE_NAME=${DEFAULT_IMAGE_NAME:-ubuntu-12.04-x86_64}
diff --git a/tests/test_ini.sh b/tests/test_ini.sh
index 598cd57..106cc95 100755
--- a/tests/test_ini.sh
+++ b/tests/test_ini.sh
@@ -34,6 +34,32 @@
 [eee]
 multi = foo1
 multi = foo2
+
+# inidelete(a)
+[del_separate_options]
+a=b
+b=c
+
+# inidelete(a)
+[del_same_option]
+a=b
+a=c
+
+# inidelete(a)
+[del_missing_option]
+b=c
+
+# inidelete(a)
+[del_missing_option_multi]
+b=c
+b=d
+
+# inidelete(a)
+[del_no_options]
+
+# inidelete(a)
+# no section - del_no_section
+
 EOF
 
 # Test with missing arguments
@@ -237,4 +263,33 @@
     echo "iniadd with non-exsting failed: $VAL"
 fi
 
+# Test inidelete
+del_cases="
+    del_separate_options
+    del_same_option
+    del_missing_option
+    del_missing_option_multi
+    del_no_options
+    del_no_section"
+
+for x in $del_cases; do
+    inidelete test.ini $x a
+    VAL=$(iniget_multiline test.ini $x a)
+    if [ -z "$VAL" ]; then
+        echo "OK: inidelete $x"
+    else
+        echo "inidelete $x failed: $VAL"
+    fi
+    if [ "$x" = "del_separate_options" -o \
+        "$x" = "del_missing_option" -o \
+        "$x" = "del_missing_option_multi" ]; then
+        VAL=$(iniget_multiline test.ini $x b)
+        if [ "$VAL" = "c" -o "$VAL" = "c d" ]; then
+            echo "OK: inidelete other_options $x"
+        else
+            echo "inidelete other_option $x failed: $VAL"
+        fi
+    fi
+done
+
 rm test.ini
diff --git a/tools/fixup_stuff.sh b/tools/fixup_stuff.sh
index 26aae82..c7f1efa 100755
--- a/tools/fixup_stuff.sh
+++ b/tools/fixup_stuff.sh
@@ -111,8 +111,8 @@
     fi
 
     FORCE_FIREWALLD=$(trueorfalse False $FORCE_FIREWALLD)
-    if [[ ${DISTRO} =~ (f19|f20) && $FORCE_FIREWALLD == "False" ]]; then
-        # On Fedora 19 and 20 firewalld interacts badly with libvirt and
+    if [[ ${DISTRO} =~ (f20) && $FORCE_FIREWALLD == "False" ]]; then
+        # On Fedora 20 firewalld interacts badly with libvirt and
         # slows things down significantly.  However, for those cases
         # where that combination is desired, allow this fix to be skipped.
 
diff --git a/unstack.sh b/unstack.sh
index 3403919..ea45da9 100755
--- a/unstack.sh
+++ b/unstack.sh
@@ -66,6 +66,8 @@
     done
 fi
 
+load_plugin_settings
+
 # Determine what system we are running on.  This provides ``os_VENDOR``,
 # ``os_RELEASE``, ``os_UPDATE``, ``os_PACKAGE``, ``os_CODENAME``
 GetOSVersion
@@ -78,11 +80,7 @@
 # ==========
 
 # Phase: unstack
-if [[ -d $TOP_DIR/extras.d ]]; then
-    for i in $TOP_DIR/extras.d/*.sh; do
-        [[ -r $i ]] && source $i unstack
-    done
-fi
+run_phase unstack
 
 if [[ "$Q_USE_DEBUG_COMMAND" == "True" ]]; then
     source $TOP_DIR/openrc