Merge "Enable MySQL slow query log."
diff --git a/.gitignore b/.gitignore
index 5e770c8..f9e2644 100644
--- a/.gitignore
+++ b/.gitignore
@@ -11,3 +11,4 @@
 stack-screenrc
 *.pem
 accrc
+.stackenv
diff --git a/AUTHORS b/AUTHORS
index ba68e32..7ec1f66 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -35,6 +35,7 @@
 Osamu Habuka <xiu.yushen@gmail.com>
 Russell Bryant <rbryant@redhat.com>
 Scott Moser <smoser@ubuntu.com>
+Sumit Naiksatam <sumitnaiksatam@gmail.com>
 Thierry Carrez <thierry@openstack.org>
 Todd Willey <xtoddx@gmail.com>
 Tres Henry <tres@treshenry.net>
diff --git a/HACKING.rst b/HACKING.rst
index c4641fa..6ad8c7e 100644
--- a/HACKING.rst
+++ b/HACKING.rst
@@ -88,6 +88,30 @@
 ``configure_swift()``.
 
 
+stackrc
+-------
+
+``stackrc`` is the global configuration file for DevStack.  It is responsible for
+calling ``localrc`` if it exists so configuration can be overridden by the user.
+
+The criteria for what belongs in ``stackrc`` can be vaguely summarized as
+follows:
+
+* All project respositories and branches (for historical reasons)
+* Global configuration that may be referenced in ``localrc``, i.e. ``DEST``, ``DATA_DIR``
+* Global service configuration like ``ENABLED_SERVICES``
+* Variables used by multiple services that do not have a clear owner, i.e.
+  ``VOLUME_BACKING_FILE_SIZE`` (nova-volumes and cinder) or ``PUBLIC_NETWORK_NAME``
+  (nova-network and quantum)
+* Variables that can not be cleanly declared in a project file due to
+  dependency ordering, i.e. the order of sourcing the project files can
+  not be changed for other reasons but the earlier file needs to dereference a
+  variable set in the later file.  This should be rare.
+
+Also, variable declarations in ``stackrc`` do NOT allow overriding (the form
+``FOO=${FOO:-baz}``); if they did then they can already be changed in ``localrc``
+and can stay in the project file.
+
 Documentation
 -------------
 
diff --git a/exercise.sh b/exercise.sh
index a0349ce..5b3c56e 100755
--- a/exercise.sh
+++ b/exercise.sh
@@ -28,7 +28,7 @@
 
 # Loop over each possible script (by basename)
 for script in $basenames; do
-    if [[ "$SKIP_EXERCISES" =~ $script ]] ; then
+    if [[ ,$SKIP_EXERCISES, =~ ,$script, ]] ; then
         skips="$skips $script"
     else
         echo "====================================================================="
diff --git a/exercises/volumes.sh b/exercises/volumes.sh
index 48a976e..45b8645 100755
--- a/exercises/volumes.sh
+++ b/exercises/volumes.sh
@@ -86,8 +86,12 @@
 fi
 
 # Configure Security Group Rules
-nova secgroup-add-rule $SECGROUP icmp -1 -1 0.0.0.0/0
-nova secgroup-add-rule $SECGROUP tcp 22 22 0.0.0.0/0
+if ! nova secgroup-list-rules $SECGROUP | grep -q icmp; then
+    nova secgroup-add-rule $SECGROUP icmp -1 -1 0.0.0.0/0
+fi
+if ! nova secgroup-list-rules $SECGROUP | grep -q " tcp .* 22 "; then
+    nova secgroup-add-rule $SECGROUP tcp 22 22 0.0.0.0/0
+fi
 
 # determinine instance type
 # -------------------------
@@ -192,7 +196,7 @@
 # Delete volume
 start_time=`date +%s`
 cinder delete $VOL_ID || die "Failure deleting volume $VOL_NAME"
-if ! timeout $ACTIVE_TIMEOUT sh -c "while ! cinder list | grep $VOL_NAME; do sleep 1; done"; then
+if ! timeout $ACTIVE_TIMEOUT sh -c "while cinder list | grep $VOL_NAME; do sleep 1; done"; then
     echo "Volume $VOL_NAME not deleted"
     exit 1
 fi
diff --git a/extras.d/80-tempest.sh b/extras.d/80-tempest.sh
new file mode 100644
index 0000000..506ccef
--- /dev/null
+++ b/extras.d/80-tempest.sh
@@ -0,0 +1,20 @@
+# tempest.sh - DevStack extras script
+
+source $TOP_DIR/lib/tempest
+
+if [[ "$1" == "stack" ]]; then
+    # Configure Tempest last to ensure that the runtime configuration of
+    # the various OpenStack services can be queried.
+    if is_service_enabled tempest; then
+        echo_summary "Configuring Tempest"
+        install_tempest
+        configure_tempest
+    fi
+fi
+
+if [[ "$1" == "unstack" ]]; then
+    # no-op
+    :
+fi
+
+
diff --git a/extras.d/README b/extras.d/README
new file mode 100644
index 0000000..ffc6793
--- /dev/null
+++ b/extras.d/README
@@ -0,0 +1,14 @@
+The extras.d directory contains project initialization scripts to be
+sourced by stack.sh at the end of its run.  This is expected to be
+used by external projects that want to be configured, started and
+stopped with DevStack.
+
+Order is controlled by prefixing the script names with the a two digit
+sequence number.  Script names must end with '.sh'.  This provides a
+convenient way to disable scripts by simoy renaming them.
+
+DevStack reserves the sequence numbers 00 through 09 and 90 through 99
+for its own use.
+
+The scripts are called with an argument of 'stack' by stack.sh and
+with an argument of 'unstack' by unstack.sh.
diff --git a/files/apts/general b/files/apts/general
index 12a92e0..0264066 100644
--- a/files/apts/general
+++ b/files/apts/general
@@ -6,7 +6,7 @@
 unzip
 wget
 psmisc
-git-core
+git
 lsof # useful when debugging
 openssh-server
 vim-nox
diff --git a/functions b/functions
index 294c380..55a81c5 100644
--- a/functions
+++ b/functions
@@ -73,7 +73,6 @@
         set +o xtrace
         local evar=$1; shift
         if ! is_set $evar || [ $exitcode != 0 ]; then
-            set +o xtrace
             echo $@
             exit -1
         fi
@@ -225,6 +224,7 @@
         os_VENDOR=$(lsb_release -i -s)
         os_RELEASE=$(lsb_release -r -s)
         os_UPDATE=""
+        os_PACKAGE="rpm"
         if [[ "Debian,Ubuntu" =~ $os_VENDOR ]]; then
             os_PACKAGE="deb"
         elif [[ "SUSE LINUX" =~ $os_VENDOR ]]; then
@@ -232,9 +232,8 @@
             if [[ $? -eq 0 ]]; then
                 os_VENDOR="openSUSE"
             fi
-            os_PACKAGE="rpm"
-        else
-            os_PACKAGE="rpm"
+        elif [[ $os_VENDOR =~ Red.*Hat ]]; then
+            os_VENDOR="Red Hat"
         fi
         os_CODENAME=$(lsb_release -c -s)
     elif [[ -r /etc/redhat-release ]]; then
@@ -460,7 +459,7 @@
     local file=$1
     local section=$2
     local option=$3
-    sed -i -e "/^\[ *$section *\]/,/^\[.*\]/ s|^\($option[ \t]*=.*$\)|#\1|" $file
+    sed -i -e "/^\[$section\]/,/^\[.*\]/ s|^\($option[ \t]*=.*$\)|#\1|" "$file"
 }
 
 # Uncomment an option in an INI file
@@ -469,7 +468,7 @@
     local file=$1
     local section=$2
     local option=$3
-    sed -i -e "/^\[ *$section *\]/,/^\[.*\]/ s|[^ \t]*#[ \t]*\($option[ \t]*=.*$\)|\1|" $file
+    sed -i -e "/^\[$section\]/,/^\[.*\]/ s|[^ \t]*#[ \t]*\($option[ \t]*=.*$\)|\1|" "$file"
 }
 
 
@@ -480,10 +479,20 @@
     local section=$2
     local option=$3
     local line
-    line=$(sed -ne "/^\[ *$section *\]/,/^\[.*\]/ { /^$option[ \t]*=/ p; }" $file)
+    line=$(sed -ne "/^\[$section\]/,/^\[.*\]/ { /^$option[ \t]*=/ p; }" "$file")
     echo ${line#*=}
 }
 
+# Determinate is the given option present in the INI file
+# ini_has_option config-file section option
+function ini_has_option() {
+    local file=$1
+    local section=$2
+    local option=$3
+    local line
+    line=$(sed -ne "/^\[$section\]/,/^\[.*\]/ { /^$option[ \t]*=/ p; }" "$file")
+    [ -n "$line" ]
+}
 
 # Set an option in an INI file
 # iniset config-file section option value
@@ -492,18 +501,18 @@
     local section=$2
     local option=$3
     local value=$4
-    if ! grep -q "^\[ *$section *\]" $file; then
+    if ! grep -q "^\[$section\]" "$file"; then
         # Add section at the end
-        echo -e "\n[$section]" >>$file
+        echo -e "\n[$section]" >>"$file"
     fi
-    if [[ -z "$(iniget $file $section $option)" ]]; then
+    if ! ini_has_option "$file" "$section" "$option"; then
         # Add it
-        sed -i -e "/^\[ *$section *\]/ a\\
+        sed -i -e "/^\[$section\]/ a\\
 $option = $value
-" $file
+" "$file"
     else
         # Replace it
-        sed -i -e "/^\[ *$section *\]/,/^\[.*\]/ s|^\($option[ \t]*=[ \t]*\).*$|\1$value|" $file
+        sed -i -e "/^\[$section\]/,/^\[.*\]/ s|^\($option[ \t]*=[ \t]*\).*$|\1$value|" "$file"
     fi
 }
 
@@ -650,10 +659,8 @@
 
     if [[ "$os_PACKAGE" = "deb" ]]; then
         dpkg -l "$@" > /dev/null
-        return $?
     elif [[ "$os_PACKAGE" = "rpm" ]]; then
         rpm --quiet -q "$@"
-        return $?
     else
         exit_distro_not_supported "finding if a package is installed"
     fi
@@ -664,10 +671,7 @@
 # is_set env-var
 function is_set() {
     local var=\$"$1"
-    if eval "[ -z \"$var\" ]"; then
-        return 1
-    fi
-    return 0
+    eval "[ -n \"$var\" ]" # For ex.: sh -c "[ -n \"$var\" ]" would be better, but several exercises depends on this
 }
 
 
@@ -973,11 +977,9 @@
     if [[ -z "$DATABASE_BACKENDS" ]]; then
         # The backends haven't initialized yet, just save the selection for now
         DATABASE_TYPE=$1
-        return
+    else
+        use_exclusive_service DATABASE_BACKENDS DATABASE_TYPE $1
     fi
-    use_exclusive_service DATABASE_BACKENDS DATABASE_TYPE $1 && return 0
-    ret=$?
-    return $ret
 }
 
 # Toggle enable/disable_service for services that must run exclusive of each other
@@ -1141,7 +1143,6 @@
     # Qpid was introduced to Ubuntu in precise, disallow it on oneiric; it is
     # not in openSUSE either right now.
     ( ! ([[ "$DISTRO" = "oneiric" ]] || is_suse) )
-    return $?
 }
 
 # Restore xtrace
diff --git a/lib/baremetal b/lib/baremetal
index 112fd6d..3cc2429 100644
--- a/lib/baremetal
+++ b/lib/baremetal
@@ -200,14 +200,14 @@
     sudo mkdir -p /tftpboot
     sudo mkdir -p /tftpboot/pxelinux.cfg
     sudo cp /usr/lib/syslinux/pxelinux.0 /tftpboot/
-    sudo chown -R `whoami`:libvirtd /tftpboot
+    sudo chown -R $STACK_USER:libvirtd /tftpboot
 
     # ensure $NOVA_STATE_PATH/baremetal is prepared
     sudo mkdir -p $NOVA_STATE_PATH/baremetal
     sudo mkdir -p $NOVA_STATE_PATH/baremetal/console
     sudo mkdir -p $NOVA_STATE_PATH/baremetal/dnsmasq
     sudo touch $NOVA_STATE_PATH/baremetal/dnsmasq/dnsmasq-dhcp.host
-    sudo chown -R `whoami` $NOVA_STATE_PATH/baremetal
+    sudo chown -R $STACK_USER $NOVA_STATE_PATH/baremetal
 
     # ensure dnsmasq is installed but not running
     # because baremetal driver will reconfigure and restart this as needed
diff --git a/lib/bigswitch_floodlight b/lib/bigswitch_floodlight
new file mode 100644
index 0000000..77aeb61
--- /dev/null
+++ b/lib/bigswitch_floodlight
@@ -0,0 +1,50 @@
+# Big Switch/FloodLight  OpenFlow Controller
+# ------------------------------------------
+
+# Save trace setting
+XTRACE=$(set +o | grep xtrace)
+set +o xtrace
+
+BS_FL_CONTROLLERS_PORT=${BS_FL_CONTROLLERS_PORT:-localhost:80}
+BS_FL_OF_PORT=${BS_FL_OF_PORT:-6633}
+OVS_BRIDGE=${OVS_BRIDGE:-br-int}
+
+function configure_bigswitch_floodlight() {
+    :
+}
+
+function init_bigswitch_floodlight() {
+    install_quantum_agent_packages
+
+    echo -n "Installing OVS managed by the openflow controllers:"
+    echo ${BS_FL_CONTROLLERS_PORT}
+
+    # Create local OVS bridge and configure it
+    sudo ovs-vsctl --no-wait -- --if-exists del-br ${OVS_BRIDGE}
+    sudo ovs-vsctl --no-wait add-br ${OVS_BRIDGE}
+    sudo ovs-vsctl --no-wait br-set-external-id ${OVS_BRIDGE} bridge-id ${OVS_BRIDGE}
+
+    ctrls=
+    for ctrl in `echo ${BS_FL_CONTROLLERS_PORT} | tr ',' ' '`
+    do
+        ctrl=${ctrl%:*}
+        ctrls="${ctrls} tcp:${ctrl}:${BS_FL_OF_PORT}"
+    done
+    echo "Adding Network conttrollers: " ${ctrls}
+    sudo ovs-vsctl --no-wait set-controller ${OVS_BRIDGE} ${ctrls}
+}
+
+function install_bigswitch_floodlight() {
+    :
+}
+
+function start_bigswitch_floodlight() {
+    :
+}
+
+function stop_bigswitch_floodlight() {
+    :
+}
+
+# Restore xtrace
+$XTRACE
diff --git a/lib/ceilometer b/lib/ceilometer
index 76ab254..0fae397 100644
--- a/lib/ceilometer
+++ b/lib/ceilometer
@@ -9,6 +9,7 @@
 # - OS_AUTH_URL for auth in api
 # - DEST set to the destination directory
 # - SERVICE_PASSWORD, SERVICE_TENANT_NAME for auth in api
+# - STACK_USER service user
 
 # stack.sh
 # ---------
@@ -29,9 +30,11 @@
 
 # Set up default directories
 CEILOMETER_DIR=$DEST/ceilometer
+CEILOMETERCLIENT_DIR=$DEST/python-ceilometerclient
 CEILOMETER_CONF_DIR=/etc/ceilometer
 CEILOMETER_CONF=$CEILOMETER_CONF_DIR/ceilometer.conf
 CEILOMETER_API_LOG_DIR=/var/log/ceilometer-api
+CEILOMETER_AUTH_CACHE_DIR=${CEILOMETER_AUTH_CACHE_DIR:-/var/cache/ceilometer}
 
 # Support potential entry-points console scripts
 if [ -d $CEILOMETER_DIR/bin ] ; then
@@ -46,6 +49,11 @@
     mongo ceilometer --eval "db.dropDatabase();"
 }
 
+# configure_ceilometerclient() - Set config files, create data dirs, etc
+function configure_ceilometerclient() {
+    setup_develop $CEILOMETERCLIENT_DIR
+}
+
 # configure_ceilometer() - Set config files, create data dirs, etc
 function configure_ceilometer() {
     setup_develop $CEILOMETER_DIR
@@ -78,15 +86,29 @@
     iniset $CEILOMETER_CONF keystone_authtoken admin_user ceilometer
     iniset $CEILOMETER_CONF keystone_authtoken admin_password $SERVICE_PASSWORD
     iniset $CEILOMETER_CONF keystone_authtoken admin_tenant_name $SERVICE_TENANT_NAME
+    iniset $CEILOMETER_CONF keystone_authtoken signing_dir $CEILOMETER_AUTH_CACHE_DIR
 
     cleanup_ceilometer
 }
 
+# init_ceilometer() - Initialize etc.
+function init_ceilometer() {
+    # Create cache dir
+    sudo mkdir -p $CEILOMETER_AUTH_CACHE_DIR
+    sudo chown $STACK_USER $CEILOMETER_AUTH_CACHE_DIR
+    rm -f $CEILOMETER_AUTH_CACHE_DIR/*
+}
+
 # install_ceilometer() - Collect source and prepare
 function install_ceilometer() {
     git_clone $CEILOMETER_REPO $CEILOMETER_DIR $CEILOMETER_BRANCH
 }
 
+# install_ceilometerclient() - Collect source and prepare
+function install_ceilometerclient() {
+    git_clone $CEILOMETERCLIENT_REPO $CEILOMETERCLIENT_DIR $CEILOMETERCLIENT_BRANCH
+}
+
 # start_ceilometer() - Start running processes, including screen
 function start_ceilometer() {
     screen_it ceilometer-acompute "cd $CEILOMETER_DIR && sg libvirtd \"$CEILOMETER_BIN_DIR/ceilometer-agent-compute --config-file $CEILOMETER_CONF\""
diff --git a/lib/cinder b/lib/cinder
index 385a5a2..d9f8d63 100644
--- a/lib/cinder
+++ b/lib/cinder
@@ -3,7 +3,7 @@
 
 # Dependencies:
 # - functions
-# - DEST, DATA_DIR must be defined
+# - DEST, DATA_DIR, STACK_USER must be defined
 # SERVICE_{TENANT_NAME|PASSWORD} must be defined
 # ``KEYSTONE_TOKEN_FORMAT`` must be defined
 
@@ -37,6 +37,12 @@
 CINDER_CONF=$CINDER_CONF_DIR/cinder.conf
 CINDER_API_PASTE_INI=$CINDER_CONF_DIR/api-paste.ini
 
+# Public facing bits
+CINDER_SERVICE_HOST=${CINDER_SERVICE_HOST:-$SERVICE_HOST}
+CINDER_SERVICE_PORT=${CINDER_SERVICE_PORT:-8776}
+CINDER_SERVICE_PORT_INT=${CINDER_SERVICE_PORT_INT:-18776}
+CINDER_SERVICE_PROTOCOL=${CINDER_SERVICE_PROTOCOL:-$SERVICE_PROTOCOL}
+
 # Support entry points installation of console scripts
 if [[ -d $CINDER_DIR/bin ]]; then
     CINDER_BIN_DIR=$CINDER_DIR/bin
@@ -48,6 +54,20 @@
 VOLUME_GROUP=${VOLUME_GROUP:-stack-volumes}
 VOLUME_NAME_PREFIX=${VOLUME_NAME_PREFIX:-volume-}
 
+# _clean_volume_group removes all cinder volumes from the specified volume group
+# _clean_volume_group $VOLUME_GROUP $VOLUME_NAME_PREFIX
+function _clean_volume_group() {
+    local vg=$1
+    local vg_prefix=$2
+    # Clean out existing volumes
+    for lv in `sudo lvs --noheadings -o lv_name $vg`; do
+        # vg_prefix prefixes the LVs we want
+        if [[ "${lv#$vg_prefix}" != "$lv" ]]; then
+            sudo lvremove -f $vg/$lv
+        fi
+    done
+}
+
 # cleanup_cinder() - Remove residual data files, anything left over from previous
 # runs that a clean run would need to clean up
 function cleanup_cinder() {
@@ -84,7 +104,8 @@
         stop_service tgtd
     fi
 
-    sudo vgremove -f $VOLUME_GROUP
+    # Campsite rule: leave behind a volume group at least as clean as we found it
+    _clean_volume_group $VOLUME_GROUP $VOLUME_NAME_PREFIX
 }
 
 # configure_cinder() - Set config files, create data dirs, etc
@@ -95,7 +116,7 @@
     if [[ ! -d $CINDER_CONF_DIR ]]; then
         sudo mkdir -p $CINDER_CONF_DIR
     fi
-    sudo chown `whoami` $CINDER_CONF_DIR
+    sudo chown $STACK_USER $CINDER_CONF_DIR
 
     cp -p $CINDER_DIR/etc/cinder/policy.json $CINDER_CONF_DIR
 
@@ -154,6 +175,11 @@
     iniset $CINDER_CONF DEFAULT osapi_volume_extension cinder.api.openstack.volume.contrib.standard_extensions
     iniset $CINDER_CONF DEFAULT state_path $CINDER_STATE_PATH
 
+    if is_service_enabled tls-proxy; then
+        # Set the service port for a proxy to take the original
+        iniset $CINDER_CONF DEFAULT osapi_volume_listen_port $CINDER_SERVICE_PORT_INT
+    fi
+
     if [ "$SYSLOG" != "False" ]; then
         iniset $CINDER_CONF DEFAULT use_syslog True
     fi
@@ -169,6 +195,7 @@
 
     if [[ "$CINDER_SECURE_DELETE" == "False" ]]; then
         iniset $CINDER_CONF DEFAULT secure_delete False
+        iniset $CINDER_CONF DEFAULT volume_clear none
     fi
 
     if [ "$LOG_COLOR" == "True" ] && [ "$SYSLOG" == "False" ]; then
@@ -225,9 +252,9 @@
             keystone endpoint-create \
                 --region RegionOne \
                 --service_id $CINDER_SERVICE \
-                --publicurl "http://$SERVICE_HOST:8776/v1/\$(tenant_id)s" \
-                --adminurl "http://$SERVICE_HOST:8776/v1/\$(tenant_id)s" \
-                --internalurl "http://$SERVICE_HOST:8776/v1/\$(tenant_id)s"
+                --publicurl "$CINDER_SERVICE_PROTOCOL://$CINDER_SERVICE_HOST:$CINDER_SERVICE_PORT/v1/\$(tenant_id)s" \
+                --adminurl "$CINDER_SERVICE_PROTOCOL://$CINDER_SERVICE_HOST:$CINDER_SERVICE_PORT/v1/\$(tenant_id)s" \
+                --internalurl "$CINDER_SERVICE_PROTOCOL://$CINDER_SERVICE_HOST:$CINDER_SERVICE_PORT/v1/\$(tenant_id)s"
         fi
     fi
 }
@@ -272,19 +299,14 @@
 
             # Remove iscsi targets
             sudo tgtadm --op show --mode target | grep $VOLUME_NAME_PREFIX | grep Target | cut -f3 -d ' ' | sudo xargs -n1 tgt-admin --delete || true
-            # Clean out existing volumes
-            for lv in `sudo lvs --noheadings -o lv_name $VOLUME_GROUP`; do
-                # VOLUME_NAME_PREFIX prefixes the LVs we want
-                if [[ "${lv#$VOLUME_NAME_PREFIX}" != "$lv" ]]; then
-                    sudo lvremove -f $VOLUME_GROUP/$lv
-                fi
-            done
+            # Start with a clean volume group
+            _clean_volume_group $VOLUME_GROUP $VOLUME_NAME_PREFIX
         fi
     fi
 
     # Create cache dir
     sudo mkdir -p $CINDER_AUTH_CACHE_DIR
-    sudo chown `whoami` $CINDER_AUTH_CACHE_DIR
+    sudo chown $STACK_USER $CINDER_AUTH_CACHE_DIR
     rm -f $CINDER_AUTH_CACHE_DIR/*
 }
 
@@ -329,6 +351,11 @@
     screen_it c-api "cd $CINDER_DIR && $CINDER_BIN_DIR/cinder-api --config-file $CINDER_CONF"
     screen_it c-vol "cd $CINDER_DIR && $CINDER_BIN_DIR/cinder-volume --config-file $CINDER_CONF"
     screen_it c-sch "cd $CINDER_DIR && $CINDER_BIN_DIR/cinder-scheduler --config-file $CINDER_CONF"
+
+    # Start proxies if enabled
+    if is_service_enabled c-api && is_service_enabled tls-proxy; then
+        start_tls_proxy '*' $CINDER_SERVICE_PORT $CINDER_SERVICE_HOST $CINDER_SERVICE_PORT_INT &
+    fi
 }
 
 # stop_cinder() - Stop running processes
diff --git a/lib/glance b/lib/glance
index dff247a..1c56a67 100644
--- a/lib/glance
+++ b/lib/glance
@@ -3,7 +3,7 @@
 
 # Dependencies:
 # ``functions`` file
-# ``DEST``, ``DATA_DIR`` must be defined
+# ``DEST``, ``DATA_DIR``, ``STACK_USER`` must be defined
 # ``SERVICE_{TENANT_NAME|PASSWORD}`` must be defined
 # ``SERVICE_HOST``
 # ``KEYSTONE_TOKEN_FORMAT`` must be defined
@@ -75,7 +75,7 @@
     if [[ ! -d $GLANCE_CONF_DIR ]]; then
         sudo mkdir -p $GLANCE_CONF_DIR
     fi
-    sudo chown `whoami` $GLANCE_CONF_DIR
+    sudo chown $STACK_USER $GLANCE_CONF_DIR
 
     # Copy over our glance configurations and update them
     cp $GLANCE_DIR/etc/glance-registry.conf $GLANCE_REGISTRY_CONF
@@ -158,10 +158,10 @@
 
     # Create cache dir
     sudo mkdir -p $GLANCE_AUTH_CACHE_DIR/api
-    sudo chown `whoami` $GLANCE_AUTH_CACHE_DIR/api
+    sudo chown $STACK_USER $GLANCE_AUTH_CACHE_DIR/api
     rm -f $GLANCE_AUTH_CACHE_DIR/api/*
     sudo mkdir -p $GLANCE_AUTH_CACHE_DIR/registry
-    sudo chown `whoami` $GLANCE_AUTH_CACHE_DIR/registry
+    sudo chown $STACK_USER $GLANCE_AUTH_CACHE_DIR/registry
     rm -f $GLANCE_AUTH_CACHE_DIR/registry/*
 }
 
diff --git a/lib/heat b/lib/heat
index a6f7286..89bd44f 100644
--- a/lib/heat
+++ b/lib/heat
@@ -49,7 +49,7 @@
     if [[ ! -d $HEAT_CONF_DIR ]]; then
         sudo mkdir -p $HEAT_CONF_DIR
     fi
-    sudo chown `whoami` $HEAT_CONF_DIR
+    sudo chown $STACK_USER $HEAT_CONF_DIR
 
     HEAT_API_CFN_HOST=${HEAT_API_CFN_HOST:-$SERVICE_HOST}
     HEAT_API_CFN_PORT=${HEAT_API_CFN_PORT:-8000}
diff --git a/lib/keystone b/lib/keystone
index 34f3372..7a70cc4 100644
--- a/lib/keystone
+++ b/lib/keystone
@@ -7,6 +7,7 @@
 # ``SERVICE_HOST``, ``SERVICE_PROTOCOL``
 # ``SERVICE_TOKEN``
 # ``S3_SERVICE_PORT`` (template backend only)
+# ``STACK_USER``
 
 # ``stack.sh`` calls the entry points in this order:
 #
@@ -79,7 +80,7 @@
     if [[ ! -d $KEYSTONE_CONF_DIR ]]; then
         sudo mkdir -p $KEYSTONE_CONF_DIR
     fi
-    sudo chown `whoami` $KEYSTONE_CONF_DIR
+    sudo chown $STACK_USER $KEYSTONE_CONF_DIR
 
     if [[ "$KEYSTONE_CONF_DIR" != "$KEYSTONE_DIR/etc" ]]; then
         cp -p $KEYSTONE_DIR/etc/keystone.conf.sample $KEYSTONE_CONF
@@ -261,7 +262,7 @@
 
         # Create cache dir
         sudo mkdir -p $KEYSTONE_AUTH_CACHE_DIR
-        sudo chown `whoami` $KEYSTONE_AUTH_CACHE_DIR
+        sudo chown $STACK_USER $KEYSTONE_AUTH_CACHE_DIR
         rm -f $KEYSTONE_AUTH_CACHE_DIR/*
     fi
 }
diff --git a/lib/nova b/lib/nova
index 4fef552..8135bf1 100644
--- a/lib/nova
+++ b/lib/nova
@@ -3,7 +3,7 @@
 
 # Dependencies:
 # ``functions`` file
-# ``DEST``, ``DATA_DIR`` must be defined
+# ``DEST``, ``DATA_DIR``, ``STACK_USER`` must be defined
 # ``SERVICE_{TENANT_NAME|PASSWORD}`` must be defined
 # ``LIBVIRT_TYPE`` must be defined
 # ``INSTANCE_NAME_PREFIX``, ``VOLUME_NAME_PREFIX`` must be defined
@@ -149,7 +149,7 @@
     if [[ ! -d $NOVA_CONF_DIR ]]; then
         sudo mkdir -p $NOVA_CONF_DIR
     fi
-    sudo chown `whoami` $NOVA_CONF_DIR
+    sudo chown $STACK_USER $NOVA_CONF_DIR
 
     cp -p $NOVA_DIR/etc/nova/policy.json $NOVA_CONF_DIR
 
@@ -277,7 +277,7 @@
         if ! getent group libvirtd >/dev/null; then
             sudo groupadd libvirtd
         fi
-        add_user_to_group `whoami` libvirtd
+        add_user_to_group $STACK_USER libvirtd
 
         # libvirt detects various settings on startup, as we potentially changed
         # the system configuration (modules, filesystems), we need to restart
@@ -297,7 +297,7 @@
         if [ -L /dev/disk/by-label/nova-instances ]; then
             if ! mount -n | grep -q $NOVA_INSTANCES_PATH; then
                 sudo mount -L nova-instances $NOVA_INSTANCES_PATH
-                sudo chown -R `whoami` $NOVA_INSTANCES_PATH
+                sudo chown -R $STACK_USER $NOVA_INSTANCES_PATH
             fi
         fi
 
@@ -354,73 +354,73 @@
     # (Re)create ``nova.conf``
     rm -f $NOVA_CONF
     add_nova_opt "[DEFAULT]"
-    add_nova_opt "verbose=True"
-    add_nova_opt "auth_strategy=keystone"
-    add_nova_opt "allow_resize_to_same_host=True"
-    add_nova_opt "api_paste_config=$NOVA_API_PASTE_INI"
-    add_nova_opt "rootwrap_config=$NOVA_CONF_DIR/rootwrap.conf"
-    add_nova_opt "compute_scheduler_driver=$SCHEDULER"
-    add_nova_opt "dhcpbridge_flagfile=$NOVA_CONF"
-    add_nova_opt "force_dhcp_release=True"
-    add_nova_opt "fixed_range=$FIXED_RANGE"
-    add_nova_opt "default_floating_pool=$PUBLIC_NETWORK_NAME"
-    add_nova_opt "s3_host=$SERVICE_HOST"
-    add_nova_opt "s3_port=$S3_SERVICE_PORT"
-    add_nova_opt "osapi_compute_extension=nova.api.openstack.compute.contrib.standard_extensions"
-    add_nova_opt "my_ip=$HOST_IP"
+    iniset $NOVA_CONF DEFAULT verbose "True"
+    iniset $NOVA_CONF DEFAULT auth_strategy "keystone"
+    iniset $NOVA_CONF DEFAULT allow_resize_to_same_host "True"
+    iniset $NOVA_CONF DEFAULT api_paste_config "$NOVA_API_PASTE_INI"
+    iniset $NOVA_CONF DEFAULT rootwrap_config "$NOVA_CONF_DIR/rootwrap.conf"
+    iniset $NOVA_CONF DEFAULT compute_scheduler_driver "$SCHEDULER"
+    iniset $NOVA_CONF DEFAULT dhcpbridge_flagfile "$NOVA_CONF"
+    iniset $NOVA_CONF DEFAULT force_dhcp_release "True"
+    iniset $NOVA_CONF DEFAULT fixed_range "$FIXED_RANGE"
+    iniset $NOVA_CONF DEFAULT default_floating_pool "$PUBLIC_NETWORK_NAME"
+    iniset $NOVA_CONF DEFAULT s3_host "$SERVICE_HOST"
+    iniset $NOVA_CONF DEFAULT s3_port "$S3_SERVICE_PORT"
+    iniset $NOVA_CONF DEFAULT osapi_compute_extension "nova.api.openstack.compute.contrib.standard_extensions"
+    iniset $NOVA_CONF DEFAULT my_ip "$HOST_IP"
     local dburl
     database_connection_url dburl nova
-    add_nova_opt "sql_connection=$dburl"
+    iniset $NOVA_CONF DEFAULT sql_connection "$dburl"
     if is_baremetal; then
         database_connection_url dburl nova_bm
-        add_nova_opt "baremetal_sql_connection=$dburl"
+        iniset $NOVA_CONF baremetal sql_connection $dburl
     fi
-    add_nova_opt "libvirt_type=$LIBVIRT_TYPE"
-    add_nova_opt "libvirt_cpu_mode=none"
-    add_nova_opt "instance_name_template=${INSTANCE_NAME_PREFIX}%08x"
+    iniset $NOVA_CONF DEFAULT libvirt_type "$LIBVIRT_TYPE"
+    iniset $NOVA_CONF DEFAULT libvirt_cpu_mode "none"
+    iniset $NOVA_CONF DEFAULT instance_name_template "${INSTANCE_NAME_PREFIX}%08x"
 
     if is_service_enabled n-api; then
-        add_nova_opt "enabled_apis=$NOVA_ENABLED_APIS"
+        iniset $NOVA_CONF DEFAULT enabled_apis "$NOVA_ENABLED_APIS"
         if is_service_enabled tls-proxy; then
             # Set the service port for a proxy to take the original
-            add_nova_opt "osapi_compute_listen_port=$NOVA_SERVICE_PORT_INT"
+            iniset $NOVA_CONF DEFAULT osapi_compute_listen_port "$NOVA_SERVICE_PORT_INT"
         fi
     fi
     if is_service_enabled cinder; then
-        add_nova_opt "volume_api_class=nova.volume.cinder.API"
+        iniset $NOVA_CONF DEFAULT volume_api_class "nova.volume.cinder.API"
     fi
     if [ -n "$NOVA_STATE_PATH" ]; then
-        add_nova_opt "state_path=$NOVA_STATE_PATH"
-        add_nova_opt "lock_path=$NOVA_STATE_PATH"
+        iniset $NOVA_CONF DEFAULT state_path "$NOVA_STATE_PATH"
+        iniset $NOVA_CONF DEFAULT lock_path "$NOVA_STATE_PATH"
     fi
     if [ -n "$NOVA_INSTANCES_PATH" ]; then
-        add_nova_opt "instances_path=$NOVA_INSTANCES_PATH"
+        iniset $NOVA_CONF DEFAULT instances_path "$NOVA_INSTANCES_PATH"
     fi
     if [ "$MULTI_HOST" != "False" ]; then
-        add_nova_opt "multi_host=True"
-        add_nova_opt "send_arp_for_ha=True"
+        iniset $NOVA_CONF DEFAULT multi_host "True"
+        iniset $NOVA_CONF DEFAULT send_arp_for_ha "True"
     fi
     if [ "$SYSLOG" != "False" ]; then
-        add_nova_opt "use_syslog=True"
+        iniset $NOVA_CONF DEFAULT use_syslog "True"
     fi
     if [ "$API_RATE_LIMIT" != "True" ]; then
-        add_nova_opt "api_rate_limit=False"
+        iniset $NOVA_CONF DEFAULT api_rate_limit "False"
     fi
     if [ "$LOG_COLOR" == "True" ] && [ "$SYSLOG" == "False" ]; then
         # Add color to logging output
-        add_nova_opt "logging_context_format_string=%(asctime)s.%(msecs)d %(color)s%(levelname)s %(name)s [%(request_id)s %(user_name)s %(project_name)s%(color)s] %(instance)s%(color)s%(message)s"
-        add_nova_opt "logging_default_format_string=%(asctime)s.%(msecs)d %(color)s%(levelname)s %(name)s [-%(color)s] %(instance)s%(color)s%(message)s"
-        add_nova_opt "logging_debug_format_suffix=from (pid=%(process)d) %(funcName)s %(pathname)s:%(lineno)d"
-        add_nova_opt "logging_exception_prefix=%(color)s%(asctime)s.%(msecs)d TRACE %(name)s %(instance)s"
+        iniset $NOVA_CONF DEFAULT logging_context_format_string "%(asctime)s.%(msecs)d %(color)s%(levelname)s %(name)s [%(request_id)s %(user_name)s %(project_name)s%(color)s] %(instance)s%(color)s%(message)s"
+        iniset $NOVA_CONF DEFAULT logging_default_format_string "%(asctime)s.%(msecs)d %(color)s%(levelname)s %(name)s [-%(color)s] %(instance)s%(color)s%(message)s"
+        iniset $NOVA_CONF DEFAULT logging_debug_format_suffix "from (pid=%(process)d) %(funcName)s %(pathname)s:%(lineno)d"
+        iniset $NOVA_CONF DEFAULT logging_exception_prefix "%(color)s%(asctime)s.%(msecs)d TRACE %(name)s %(instance)s"
     else
         # Show user_name and project_name instead of user_id and project_id
-        add_nova_opt "logging_context_format_string=%(asctime)s.%(msecs) %(levelname)s %(name)s [%(request_id)s %(user_name)s %(project_name)s] %(instance)s%(message)s"
+        iniset $NOVA_CONF DEFAULT logging_context_format_string "%(asctime)s.%(msecs)d %(levelname)s %(name)s [%(request_id)s %(user_name)s %(project_name)s] %(instance)s%(message)s"
     fi
     if is_service_enabled ceilometer; then
-        add_nova_opt "instance_usage_audit=True"
-        add_nova_opt "instance_usage_audit_period=hour"
-        add_nova_opt "notification_driver=nova.openstack.common.notifier.rabbit_notifier"
-        add_nova_opt "notification_driver=ceilometer.compute.nova_notifier"
+        iniset $NOVA_CONF DEFAULT instance_usage_audit "True"
+        iniset $NOVA_CONF DEFAULT instance_usage_audit_period "hour"
+        iniset $NOVA_CONF DEFAULT notification_driver "nova.openstack.common.notifier.rpc_notifier"
+        iniset $NOVA_CONF DEFAULT notification_driver "ceilometer.compute.nova_notifier"
     fi
 
 
@@ -432,18 +432,18 @@
     # Define extra nova conf flags by defining the array ``EXTRA_OPTS``.
     # For Example: ``EXTRA_OPTS=(foo=true bar=2)``
     for I in "${EXTRA_OPTS[@]}"; do
-        # Attempt to convert flags to options
-        add_nova_opt ${I//--}
+        # Replace the first '=' with ' ' for iniset syntax
+        iniset $NOVA_CONF DEFAULT ${I/=/ }
     done
 }
 
 function create_nova_conf_nova_network() {
-    add_nova_opt "network_manager=nova.network.manager.$NET_MAN"
-    add_nova_opt "public_interface=$PUBLIC_INTERFACE"
-    add_nova_opt "vlan_interface=$VLAN_INTERFACE"
-    add_nova_opt "flat_network_bridge=$FLAT_NETWORK_BRIDGE"
+    iniset $NOVA_CONF DEFAULT network_manager "nova.network.manager.$NET_MAN"
+    iniset $NOVA_CONF DEFAULT public_interface "$PUBLIC_INTERFACE"
+    iniset $NOVA_CONF DEFAULT vlan_interface "$VLAN_INTERFACE"
+    iniset $NOVA_CONF DEFAULT flat_network_bridge "$FLAT_NETWORK_BRIDGE"
     if [ -n "$FLAT_INTERFACE" ]; then
-        add_nova_opt "flat_interface=$FLAT_INTERFACE"
+        iniset $NOVA_CONF DEFAULT flat_interface "$FLAT_INTERFACE"
     fi
 }
 
@@ -474,13 +474,13 @@
 
     # Create cache dir
     sudo mkdir -p $NOVA_AUTH_CACHE_DIR
-    sudo chown `whoami` $NOVA_AUTH_CACHE_DIR
+    sudo chown $STACK_USER $NOVA_AUTH_CACHE_DIR
     rm -f $NOVA_AUTH_CACHE_DIR/*
 
     # Create the keys folder
     sudo mkdir -p ${NOVA_STATE_PATH}/keys
     # make sure we own NOVA_STATE_PATH and all subdirs
-    sudo chown -R `whoami` ${NOVA_STATE_PATH}
+    sudo chown -R $STACK_USER ${NOVA_STATE_PATH}
 }
 
 # install_novaclient() - Collect source and prepare
diff --git a/lib/quantum b/lib/quantum
index ea0e311..343e5a9 100644
--- a/lib/quantum
+++ b/lib/quantum
@@ -200,13 +200,13 @@
 }
 
 function create_nova_conf_quantum() {
-    add_nova_opt "network_api_class=nova.network.quantumv2.api.API"
-    add_nova_opt "quantum_admin_username=$Q_ADMIN_USERNAME"
-    add_nova_opt "quantum_admin_password=$SERVICE_PASSWORD"
-    add_nova_opt "quantum_admin_auth_url=$KEYSTONE_SERVICE_PROTOCOL://$KEYSTONE_SERVICE_HOST:$KEYSTONE_AUTH_PORT/v2.0"
-    add_nova_opt "quantum_auth_strategy=$Q_AUTH_STRATEGY"
-    add_nova_opt "quantum_admin_tenant_name=$SERVICE_TENANT_NAME"
-    add_nova_opt "quantum_url=http://$Q_HOST:$Q_PORT"
+    iniset $NOVA_CONF DEFAULT network_api_class "nova.network.quantumv2.api.API"
+    iniset $NOVA_CONF DEFAULT quantum_admin_username "$Q_ADMIN_USERNAME"
+    iniset $NOVA_CONF DEFAULT quantum_admin_password "$SERVICE_PASSWORD"
+    iniset $NOVA_CONF DEFAULT quantum_admin_auth_url "$KEYSTONE_SERVICE_PROTOCOL://$KEYSTONE_SERVICE_HOST:$KEYSTONE_AUTH_PORT/v2.0"
+    iniset $NOVA_CONF DEFAULT quantum_auth_strategy "$Q_AUTH_STRATEGY"
+    iniset $NOVA_CONF DEFAULT quantum_admin_tenant_name "$SERVICE_TENANT_NAME"
+    iniset $NOVA_CONF DEFAULT quantum_url "http://$Q_HOST:$Q_PORT"
 
     if [[ "$Q_PLUGIN" = "openvswitch" ]]; then
         NOVA_VIF_DRIVER=${NOVA_VIF_DRIVER:-"nova.virt.libvirt.vif.LibvirtHybridOVSBridgeDriver"}
@@ -214,14 +214,16 @@
         NOVA_VIF_DRIVER=${NOVA_VIF_DRIVER:-"nova.virt.libvirt.vif.QuantumLinuxBridgeVIFDriver"}
     elif [[ "$Q_PLUGIN" = "ryu" ]]; then
         NOVA_VIF_DRIVER=${NOVA_VIF_DRIVER:-"quantum.plugins.ryu.nova.vif.LibvirtOpenVswitchOFPRyuDriver"}
-        add_nova_opt "libvirt_ovs_integration_bridge=$OVS_BRIDGE"
-        add_nova_opt "linuxnet_ovs_ryu_api_host=$RYU_API_HOST:$RYU_API_PORT"
-        add_nova_opt "libvirt_ovs_ryu_api_host=$RYU_API_HOST:$RYU_API_PORT"
+        iniset $NOVA_CONF DEFAULT libvirt_ovs_integration_bridge "$OVS_BRIDGE"
+        iniset $NOVA_CONF DEFAULT linuxnet_ovs_ryu_api_host "$RYU_API_HOST:$RYU_API_PORT"
+        iniset $NOVA_CONF DEFAULT libvirt_ovs_ryu_api_host "$RYU_API_HOST:$RYU_API_PORT"
+    elif [[ "$Q_PLUGIN" = "bigswitch_floodlight" ]]; then
+        NOVA_VIF_DRIVER=${NOVA_VIF_DRIVER:-"nova.virt.libvirt.vif.LibvirtHybridOVSBridgeDriver"}
     fi
-    add_nova_opt "libvirt_vif_driver=$NOVA_VIF_DRIVER"
-    add_nova_opt "linuxnet_interface_driver=$LINUXNET_VIF_DRIVER"
+    iniset $NOVA_CONF DEFAULT libvirt_vif_driver "$NOVA_VIF_DRIVER"
+    iniset $NOVA_CONF DEFAULT linuxnet_interface_driver "$LINUXNET_VIF_DRIVER"
     if is_service_enabled q-meta; then
-        add_nova_opt "service_quantum_metadata_proxy=True"
+        iniset $NOVA_CONF DEFAULT service_quantum_metadata_proxy "True"
     fi
 }
 
@@ -332,7 +334,7 @@
 
 function is_quantum_ovs_base_plugin() {
     local plugin=$1
-    if [[ ",openvswitch,ryu," =~ ,${plugin}, ]]; then
+    if [[ ",openvswitch,ryu,bigswitch_floodlight," =~ ,${plugin}, ]]; then
         return 0
     fi
     return 1
@@ -388,7 +390,7 @@
     if [[ ! -d $QUANTUM_CONF_DIR ]]; then
         sudo mkdir -p $QUANTUM_CONF_DIR
     fi
-    sudo chown `whoami` $QUANTUM_CONF_DIR
+    sudo chown $STACK_USER $QUANTUM_CONF_DIR
 
     cp $QUANTUM_DIR/etc/quantum.conf $QUANTUM_CONF
 
@@ -407,6 +409,13 @@
         Q_PLUGIN_CONF_FILENAME=ryu.ini
         Q_DB_NAME="ovs_quantum"
         Q_PLUGIN_CLASS="quantum.plugins.ryu.ryu_quantum_plugin.RyuQuantumPluginV2"
+    elif [[ "$Q_PLUGIN" = "bigswitch_floodlight" ]]; then
+        Q_PLUGIN_CONF_PATH=etc/quantum/plugins/bigswitch
+        Q_PLUGIN_CONF_FILENAME=restproxy.ini
+        Q_DB_NAME="restproxy_quantum"
+        Q_PLUGIN_CLASS="quantum.plugins.bigswitch.plugin.QuantumRestProxyV2"
+        BS_FL_CONTROLLERS_PORT=${BS_FL_CONTROLLERS_PORT:-localhost:80}
+        BS_FL_CONTROLLER_TIMEOUT=${BS_FL_CONTROLLER_TIMEOUT:-10}
     fi
 
     if [[ $Q_PLUGIN_CONF_PATH == '' || $Q_PLUGIN_CONF_FILENAME == '' || $Q_PLUGIN_CLASS == '' ]]; then
@@ -674,6 +683,9 @@
     elif [[ "$Q_PLUGIN" = "ryu" ]]; then
         iniset /$Q_PLUGIN_CONF_FILE OVS openflow_controller $RYU_OFP_HOST:$RYU_OFP_PORT
         iniset /$Q_PLUGIN_CONF_FILE OVS openflow_rest_api $RYU_API_HOST:$RYU_API_PORT
+    elif [[ "$Q_PLUGIN" = "bigswitch_floodlight" ]]; then
+        iniset /$Q_PLUGIN_CONF_FILE RESTPROXY servers $BS_FL_CONTROLLERS_PORT
+        iniset /$Q_PLUGIN_CONF_FILE RESTPROXY servertimeout $BS_FL_CONTROLLER_TIMEOUT
     fi
 }
 
@@ -730,7 +742,7 @@
     iniset $conf_file $section signing_dir $QUANTUM_AUTH_CACHE_DIR
     # Create cache dir
     sudo mkdir -p $QUANTUM_AUTH_CACHE_DIR
-    sudo chown `whoami` $QUANTUM_AUTH_CACHE_DIR
+    sudo chown $STACK_USER $QUANTUM_AUTH_CACHE_DIR
     rm -f $QUANTUM_AUTH_CACHE_DIR/*
 }
 
@@ -749,6 +761,8 @@
         iniset $conf_file DEFAULT interface_driver quantum.agent.linux.interface.BridgeInterfaceDriver
     elif [[ "$Q_PLUGIN" = "ryu" ]]; then
         iniset $conf_file DEFAULT interface_driver quantum.agent.linux.interface.RyuInterfaceDriver
+    elif [[ "$Q_PLUGIN" = "bigswitch_floodlight" ]]; then
+        iniset $conf_file DEFAULT interface_driver quantum.agent.linux.interface.OVSInterfaceDriver
     fi
 }
 
@@ -835,7 +849,7 @@
 # Quantum 3rd party programs
 #---------------------------
 # A comma-separated list of 3rd party programs
-QUANTUM_THIRD_PARTIES="ryu"
+QUANTUM_THIRD_PARTIES="ryu,bigswitch_floodlight"
 for third_party in ${QUANTUM_THIRD_PARTIES//,/ }; do
     source lib/$third_party
 done
diff --git a/lib/ryu b/lib/ryu
index ac3462b..1292313 100644
--- a/lib/ryu
+++ b/lib/ryu
@@ -27,7 +27,7 @@
     if [[ ! -d $RYU_CONF_DIR ]]; then
         sudo mkdir -p $RYU_CONF_DIR
     fi
-    sudo chown `whoami` $RYU_CONF_DIR
+    sudo chown $STACK_USER $RYU_CONF_DIR
     RYU_CONF=$RYU_CONF_DIR/ryu.conf
     sudo rm -rf $RYU_CONF
 
diff --git a/lib/swift b/lib/swift
index 8934264..46c6eb2 100644
--- a/lib/swift
+++ b/lib/swift
@@ -4,6 +4,7 @@
 # Dependencies:
 # ``functions`` file
 # ``DEST``, ``SCREEN_NAME``, `SWIFT_HASH` must be defined
+# ``STACK_USER`` must be defined
 # ``SWIFT_DATA_DIR`` or ``DATA_DIR`` must be defined
 # ``lib/keystone`` file
 # ``stack.sh`` calls the entry points in this order:
@@ -39,7 +40,8 @@
 SWIFT_CONFIG_DIR=${SWIFT_CONFIG_DIR:-/etc/swift}
 
 # DevStack will create a loop-back disk formatted as XFS to store the
-# swift data. Set ``SWIFT_LOOPBACK_DISK_SIZE`` to the disk size in bytes.
+# swift data. Set ``SWIFT_LOOPBACK_DISK_SIZE`` to the disk size in
+# kilobytes.
 # Default is 1 gigabyte.
 SWIFT_LOOPBACK_DISK_SIZE=${SWIFT_LOOPBACK_DISK_SIZE:-1000000}
 
@@ -99,7 +101,7 @@
     # changing the permissions so we can run it as our user.
 
     USER_GROUP=$(id -g)
-    sudo mkdir -p ${SWIFT_DATA_DIR}/drives
+    sudo mkdir -p ${SWIFT_DATA_DIR}/{drives,cache}
     sudo chown -R $USER:${USER_GROUP} ${SWIFT_DATA_DIR}
 
     # Create a loopback disk and format it to XFS.
@@ -273,16 +275,22 @@
         swift_node_config=${SWIFT_CONFIG_DIR}/object-server/${node_number}.conf
         cp ${SWIFT_DIR}/etc/object-server.conf-sample ${swift_node_config}
         generate_swift_config ${swift_node_config} ${node_number} $[OBJECT_PORT_BASE + 10 * (node_number - 1)]
+        iniset ${swift_node_config} filter:recon recon_cache_path  ${SWIFT_DATA_DIR}/cache
+        # Using a sed and not iniset/iniuncomment because we want to a global
+        # modification and make sure it works for new sections.
+        sed -i -e "s,#[ ]*recon_cache_path .*,recon_cache_path = ${SWIFT_DATA_DIR}/cache," ${swift_node_config}
 
         swift_node_config=${SWIFT_CONFIG_DIR}/container-server/${node_number}.conf
         cp ${SWIFT_DIR}/etc/container-server.conf-sample ${swift_node_config}
         generate_swift_config ${swift_node_config} ${node_number} $[CONTAINER_PORT_BASE + 10 * (node_number - 1)]
         iniuncomment ${swift_node_config} app:container-server allow_versions
         iniset ${swift_node_config} app:container-server allow_versions  "true"
+        sed -i -e "s,#[ ]*recon_cache_path .*,recon_cache_path = ${SWIFT_DATA_DIR}/cache," ${swift_node_config}
 
         swift_node_config=${SWIFT_CONFIG_DIR}/account-server/${node_number}.conf
         cp ${SWIFT_DIR}/etc/account-server.conf-sample ${swift_node_config}
         generate_swift_config ${swift_node_config} ${node_number} $[ACCOUNT_PORT_BASE + 10 * (node_number - 1)]
+        sed -i -e "s,#[ ]*recon_cache_path .*,recon_cache_path = ${SWIFT_DATA_DIR}/cache," ${swift_node_config}
     done
 
     swift_log_dir=${SWIFT_DATA_DIR}/logs
@@ -326,7 +334,7 @@
 
     # Create cache dir
     sudo mkdir -p $SWIFT_AUTH_CACHE_DIR
-    sudo chown `whoami` $SWIFT_AUTH_CACHE_DIR
+    sudo chown $STACK_USER $SWIFT_AUTH_CACHE_DIR
     rm -f $SWIFT_AUTH_CACHE_DIR/*
 }
 
diff --git a/lib/tempest b/lib/tempest
index d08daeb..84afc09 100644
--- a/lib/tempest
+++ b/lib/tempest
@@ -129,31 +129,41 @@
     ALT_USERNAME=${ALT_USERNAME:-alt_demo}
     ALT_TENANT_NAME=${ALT_TENANT_NAME:-alt_demo}
 
-    # Check Nova for existing flavors and, if set, look for the
-    # ``DEFAULT_INSTANCE_TYPE`` and use that. Otherwise, just use the first flavor.
-    flavor_lines=`nova flavor-list`
-    IFS=$'\r\n'
-    flavors=""
-    for line in $flavor_lines; do
-        if [ -z $DEFAULT_INSTANCE_TYPE ]; then
-            flavors="$flavors `echo $line | grep -v "^\(|\s*ID\|+--\)" | cut -d' ' -f2`"
-        else
-            flavors="$flavors `echo $line | grep -v "^\(|\s*ID\|+--\)" | grep "$DEFAULT_INSTANCE_TYPE" | cut -d' ' -f2`"
-    fi
-    done
+    # If the ``DEFAULT_INSTANCE_TYPE`` not declared, use the new behavior
+    # Tempest creates instane types for himself
+    if  [[ -z "$DEFAULT_INSTANCE_TYPE" ]]; then
+        nova flavor-create m1.nano 42 64 0 1
+        flavor_ref=42
+        nova flavor-create m1.micro 84 128 0 1
+        flavor_ref_alt=84
+    else
+        # Check Nova for existing flavors and, if set, look for the
+        # ``DEFAULT_INSTANCE_TYPE`` and use that.
+        flavor_lines=`nova flavor-list`
+        IFS=$'\r\n'
+        flavors=""
+        for line in $flavor_lines; do
+            f=$(echo $line | awk "/ $DEFAULT_INSTANCE_TYPE / { print \$2 }")
+            flavors="$flavors $f"
+        done
 
-    IFS=" "
-    flavors=($flavors)
-    num_flavors=${#flavors[*]}
-    echo "Found $num_flavors flavors"
-    if [[ $num_flavors -eq 0 ]]; then
-        echo "Found no valid flavors to use!"
-        exit 1
-    fi
-    flavor_ref=${flavors[0]}
-    flavor_ref_alt=$flavor_ref
-    if [[ $num_flavors -gt 1 ]]; then
-        flavor_ref_alt=${flavors[1]}
+        for line in $flavor_lines; do
+            flavors="$flavors `echo $line | grep -v "^\(|\s*ID\|+--\)" | cut -d' ' -f2`"
+        done
+
+        IFS=" "
+        flavors=($flavors)
+        num_flavors=${#flavors[*]}
+        echo "Found $num_flavors flavors"
+        if [[ $num_flavors -eq 0 ]]; then
+            echo "Found no valid flavors to use!"
+            exit 1
+        fi
+        flavor_ref=${flavors[0]}
+        flavor_ref_alt=$flavor_ref
+        if [[ $num_flavors -gt 1 ]]; then
+            flavor_ref_alt=${flavors[1]}
+        fi
     fi
 
     if [ "$Q_USE_NAMESPACE" != "False" ]; then
@@ -188,6 +198,12 @@
     iniset $TEMPEST_CONF compute resize_available False
     iniset $TEMPEST_CONF compute change_password_available False
     iniset $TEMPEST_CONF compute compute_log_level ERROR
+    # Note(nati) current tempest don't create network for each tenant
+    # so reuse same tenant for now
+    if is_service_enabled quantum; then
+        TEMPEST_ALLOW_TENANT_ISOLATION=${TEMPEST_ALLOW_TENANT_ISOLATION:-False}
+    fi
+    iniset $TEMPEST_CONF compute allow_tenant_isolation ${TEMPEST_ALLOW_TENANT_ISOLATION:-True}
     #Skip until #1074039 is fixed
     iniset $TEMPEST_CONF compute run_ssh False
     iniset $TEMPEST_CONF compute ssh_user ${DEFAULT_INSTANCE_USER:-$OS_USERNAME}
diff --git a/lib/tls b/lib/tls
index 1e2a899..202edef 100644
--- a/lib/tls
+++ b/lib/tls
@@ -189,7 +189,7 @@
 " >$ca_dir/signing.conf
 }
 
-# Create root and intermediate CAs and an initial server cert
+# Create root and intermediate CAs
 # init_CA
 function init_CA {
     # Ensure CAs are built
@@ -198,7 +198,11 @@
 
     # Create the CA bundle
     cat $ROOT_CA_DIR/cacert.pem $INT_CA_DIR/cacert.pem >>$INT_CA_DIR/ca-chain.pem
+}
 
+# Create an initial server cert
+# init_cert
+function init_cert {
     if [[ ! -r $DEVSTACK_CERT ]]; then
         if [[ -n "$TLS_IP" ]]; then
             # Lie to let incomplete match routines work
diff --git a/stack.sh b/stack.sh
index 9f734b9..5c071fc 100755
--- a/stack.sh
+++ b/stack.sh
@@ -177,40 +177,43 @@
 # sudo privileges and runs as that user.
 
 if [[ $EUID -eq 0 ]]; then
+    STACK_USER=$DEFAULT_STACK_USER
     ROOTSLEEP=${ROOTSLEEP:-10}
     echo "You are running this script as root."
-    echo "In $ROOTSLEEP seconds, we will create a user 'stack' and run as that user"
+    echo "In $ROOTSLEEP seconds, we will create a user '$STACK_USER' and run as that user"
     sleep $ROOTSLEEP
 
     # Give the non-root user the ability to run as **root** via ``sudo``
     is_package_installed sudo || install_package sudo
-    if ! getent group stack >/dev/null; then
-        echo "Creating a group called stack"
-        groupadd stack
+    if ! getent group $STACK_USER >/dev/null; then
+        echo "Creating a group called $STACK_USER"
+        groupadd $STACK_USER
     fi
-    if ! getent passwd stack >/dev/null; then
-        echo "Creating a user called stack"
-        useradd -g stack -s /bin/bash -d $DEST -m stack
+    if ! getent passwd $STACK_USER >/dev/null; then
+        echo "Creating a user called $STACK_USER"
+        useradd -g $STACK_USER -s /bin/bash -d $DEST -m $STACK_USER
     fi
 
     echo "Giving stack user passwordless sudo privileges"
     # UEC images ``/etc/sudoers`` does not have a ``#includedir``, add one
     grep -q "^#includedir.*/etc/sudoers.d" /etc/sudoers ||
         echo "#includedir /etc/sudoers.d" >> /etc/sudoers
-    ( umask 226 && echo "stack ALL=(ALL) NOPASSWD:ALL" \
+    ( umask 226 && echo "$STACK_USER ALL=(ALL) NOPASSWD:ALL" \
         > /etc/sudoers.d/50_stack_sh )
 
-    echo "Copying files to stack user"
+    echo "Copying files to $STACK_USER user"
     STACK_DIR="$DEST/${TOP_DIR##*/}"
     cp -r -f -T "$TOP_DIR" "$STACK_DIR"
-    chown -R stack "$STACK_DIR"
+    chown -R $STACK_USER "$STACK_DIR"
+    cd "$STACK_DIR"
     if [[ "$SHELL_AFTER_RUN" != "no" ]]; then
-        exec su -c "set -e; cd $STACK_DIR; bash stack.sh; bash" stack
+        exec sudo -u $STACK_USER  bash -l -c "set -e; bash stack.sh; bash"
     else
-        exec su -c "set -e; cd $STACK_DIR; bash stack.sh" stack
+        exec sudo -u $STACK_USER bash -l -c "set -e; source stack.sh"
     fi
     exit 1
 else
+    STACK_USER=`whoami`
     # We're not **root**, make sure ``sudo`` is available
     is_package_installed sudo || die "Sudo is required.  Re-run stack.sh as root ONE TIME ONLY to set up sudo."
 
@@ -220,10 +223,10 @@
 
     # Set up devstack sudoers
     TEMPFILE=`mktemp`
-    echo "`whoami` ALL=(root) NOPASSWD:ALL" >$TEMPFILE
+    echo "$STACK_USER ALL=(root) NOPASSWD:ALL" >$TEMPFILE
     # Some binaries might be under /sbin or /usr/sbin, so make sure sudo will
     # see them by forcing PATH
-    echo "Defaults:`whoami` secure_path=/sbin:/usr/sbin:/usr/bin:/bin:/usr/local/sbin:/usr/local/bin" >> $TEMPFILE
+    echo "Defaults:$STACK_USER secure_path=/sbin:/usr/sbin:/usr/bin:/bin:/usr/local/sbin:/usr/local/bin" >> $TEMPFILE
     chmod 0440 $TEMPFILE
     sudo chown root:root $TEMPFILE
     sudo mv $TEMPFILE /etc/sudoers.d/50_stack_sh
@@ -235,7 +238,7 @@
 # Create the destination directory and ensure it is writable by the user
 sudo mkdir -p $DEST
 if [ ! -w $DEST ]; then
-    sudo chown `whoami` $DEST
+    sudo chown $STACK_USER $DEST
 fi
 
 # Set ``OFFLINE`` to ``True`` to configure ``stack.sh`` to run cleanly without
@@ -251,7 +254,7 @@
 # Destination path for service data
 DATA_DIR=${DATA_DIR:-${DEST}/data}
 sudo mkdir -p $DATA_DIR
-sudo chown `whoami` $DATA_DIR
+sudo chown $STACK_USER $DATA_DIR
 
 
 # Common Configuration
@@ -321,7 +324,6 @@
 source $TOP_DIR/lib/ceilometer
 source $TOP_DIR/lib/heat
 source $TOP_DIR/lib/quantum
-source $TOP_DIR/lib/tempest
 source $TOP_DIR/lib/baremetal
 
 # Set the destination directories for OpenStack projects
@@ -773,11 +775,9 @@
     install_cinder
 fi
 if is_service_enabled ceilometer; then
+    install_ceilometerclient
     install_ceilometer
 fi
-if is_service_enabled tempest; then
-    install_tempest
-fi
 
 
 # Initialization
@@ -838,6 +838,7 @@
 if is_service_enabled tls-proxy; then
     configure_CA
     init_CA
+    init_cert
     # Add name to /etc/hosts
     # don't be naive and add to existing line!
 fi
@@ -1059,9 +1060,9 @@
     # These settings don't hurt anything if n-xvnc and n-novnc are disabled
     if is_service_enabled n-cpu; then
         NOVNCPROXY_URL=${NOVNCPROXY_URL:-"http://$SERVICE_HOST:6080/vnc_auto.html"}
-        add_nova_opt "novncproxy_base_url=$NOVNCPROXY_URL"
+        iniset $NOVA_CONF DEFAULT novncproxy_base_url "$NOVNCPROXY_URL"
         XVPVNCPROXY_URL=${XVPVNCPROXY_URL:-"http://$SERVICE_HOST:6081/console"}
-        add_nova_opt "xvpvncproxy_base_url=$XVPVNCPROXY_URL"
+        iniset $NOVA_CONF DEFAULT xvpvncproxy_base_url "$XVPVNCPROXY_URL"
     fi
     if [ "$VIRT_DRIVER" = 'xenserver' ]; then
         VNCSERVER_PROXYCLIENT_ADDRESS=${VNCSERVER_PROXYCLIENT_ADDRESS=169.254.0.1}
@@ -1071,18 +1072,18 @@
     # Address on which instance vncservers will listen on compute hosts.
     # For multi-host, this should be the management ip of the compute host.
     VNCSERVER_LISTEN=${VNCSERVER_LISTEN=127.0.0.1}
-    add_nova_opt "vncserver_listen=$VNCSERVER_LISTEN"
-    add_nova_opt "vncserver_proxyclient_address=$VNCSERVER_PROXYCLIENT_ADDRESS"
-    add_nova_opt "ec2_dmz_host=$EC2_DMZ_HOST"
+    iniset $NOVA_CONF DEFAULT vncserver_listen "$VNCSERVER_LISTEN"
+    iniset $NOVA_CONF DEFAULT vncserver_proxyclient_address "$VNCSERVER_PROXYCLIENT_ADDRESS"
+    iniset $NOVA_CONF DEFAULT ec2_dmz_host "$EC2_DMZ_HOST"
     if is_service_enabled zeromq; then
-        add_nova_opt "rpc_backend=nova.openstack.common.rpc.impl_zmq"
+        iniset $NOVA_CONF DEFAULT rpc_backend "nova.openstack.common.rpc.impl_zmq"
     elif is_service_enabled qpid; then
-        add_nova_opt "rpc_backend=nova.rpc.impl_qpid"
+        iniset $NOVA_CONF DEFAULT rpc_backend "nova.rpc.impl_qpid"
     elif [ -n "$RABBIT_HOST" ] &&  [ -n "$RABBIT_PASSWORD" ]; then
-        add_nova_opt "rabbit_host=$RABBIT_HOST"
-        add_nova_opt "rabbit_password=$RABBIT_PASSWORD"
+        iniset $NOVA_CONF DEFAULT rabbit_host "$RABBIT_HOST"
+        iniset $NOVA_CONF DEFAULT rabbit_password "$RABBIT_PASSWORD"
     fi
-    add_nova_opt "glance_api_servers=$GLANCE_HOSTPORT"
+    iniset $NOVA_CONF DEFAULT glance_api_servers "$GLANCE_HOSTPORT"
 
 
     # XenServer
@@ -1091,16 +1092,16 @@
     if [ "$VIRT_DRIVER" = 'xenserver' ]; then
         echo_summary "Using XenServer virtualization driver"
         read_password XENAPI_PASSWORD "ENTER A PASSWORD TO USE FOR XEN."
-        add_nova_opt "compute_driver=xenapi.XenAPIDriver"
+        iniset $NOVA_CONF DEFAULT compute_driver "xenapi.XenAPIDriver"
         XENAPI_CONNECTION_URL=${XENAPI_CONNECTION_URL:-"http://169.254.0.1"}
         XENAPI_USER=${XENAPI_USER:-"root"}
-        add_nova_opt "xenapi_connection_url=$XENAPI_CONNECTION_URL"
-        add_nova_opt "xenapi_connection_username=$XENAPI_USER"
-        add_nova_opt "xenapi_connection_password=$XENAPI_PASSWORD"
-        add_nova_opt "flat_injected=False"
+        iniset $NOVA_CONF DEFAULT xenapi_connection_url "$XENAPI_CONNECTION_URL"
+        iniset $NOVA_CONF DEFAULT xenapi_connection_username "$XENAPI_USER"
+        iniset $NOVA_CONF DEFAULT xenapi_connection_password "$XENAPI_PASSWORD"
+        iniset $NOVA_CONF DEFAULT flat_injected "False"
         # Need to avoid crash due to new firewall support
         XEN_FIREWALL_DRIVER=${XEN_FIREWALL_DRIVER:-"nova.virt.firewall.IptablesFirewallDriver"}
-        add_nova_opt "firewall_driver=$XEN_FIREWALL_DRIVER"
+        iniset $NOVA_CONF DEFAULT firewall_driver "$XEN_FIREWALL_DRIVER"
 
     # OpenVZ
     # ------
@@ -1109,34 +1110,40 @@
         echo_summary "Using OpenVZ virtualization driver"
         # TODO(deva): OpenVZ driver does not yet work if compute_driver is set here.
         #             Replace connection_type when this is fixed.
-        #             add_nova_opt "compute_driver=openvz.connection.OpenVzConnection"
-        add_nova_opt "connection_type=openvz"
+        #             iniset $NOVA_CONF DEFAULT compute_driver "openvz.connection.OpenVzConnection"
+        iniset $NOVA_CONF DEFAULT connection_type "openvz"
         LIBVIRT_FIREWALL_DRIVER=${LIBVIRT_FIREWALL_DRIVER:-"nova.virt.libvirt.firewall.IptablesFirewallDriver"}
-        add_nova_opt "firewall_driver=$LIBVIRT_FIREWALL_DRIVER"
+        iniset $NOVA_CONF DEFAULT firewall_driver "$LIBVIRT_FIREWALL_DRIVER"
 
     # Bare Metal
     # ----------
 
     elif [ "$VIRT_DRIVER" = 'baremetal' ]; then
         echo_summary "Using BareMetal driver"
-        add_nova_opt "compute_driver=nova.virt.baremetal.driver.BareMetalDriver"
         LIBVIRT_FIREWALL_DRIVER=${LIBVIRT_FIREWALL_DRIVER:-"nova.virt.firewall.NoopFirewallDriver"}
-        add_nova_opt "firewall_driver=$LIBVIRT_FIREWALL_DRIVER"
-        add_nova_opt "baremetal_driver=$BM_DRIVER"
-        add_nova_opt "baremetal_tftp_root=/tftpboot"
-        add_nova_opt "baremetal_instance_type_extra_specs=cpu_arch:$BM_CPU_ARCH"
-        add_nova_opt "baremetal_power_manager=$BM_POWER_MANAGER"
-        add_nova_opt "scheduler_host_manager=nova.scheduler.baremetal_host_manager.BaremetalHostManager"
-        add_nova_opt "scheduler_default_filters=AllHostsFilter"
+        iniset $NOVA_CONF DEFAULT compute_driver nova.virt.baremetal.driver.BareMetalDriver
+        iniset $NOVA_CONF DEFAULT firewall_driver $LIBVIRT_FIREWALL_DRIVER
+        iniset $NOVA_CONF DEFAULT scheduler_host_manager nova.scheduler.baremetal_host_manager.BaremetalHostManager
+        iniset $NOVA_CONF DEFAULT scheduler_default_filters AllHostsFilter
+        iniset $NOVA_CONF baremetal driver $BM_DRIVER
+        iniset $NOVA_CONF baremetal instance_type_extra_specs cpu_arch:$BM_CPU_ARCH
+        iniset $NOVA_CONF baremetal power_manager $BM_POWER_MANAGER
+        iniset $NOVA_CONF baremetal tftp_root /tftpboot
+
+        # Define extra baremetal nova conf flags by defining the array ``EXTRA_BAREMETAL_OPTS``.
+        for I in "${EXTRA_BAREMETAL_OPTS[@]}"; do
+           # Attempt to convert flags to options
+           iniset $NOVA_CONF baremetal ${I//=/ }
+        done
 
     # Default
     # -------
 
     else
         echo_summary "Using libvirt virtualization driver"
-        add_nova_opt "compute_driver=libvirt.LibvirtDriver"
+        iniset $NOVA_CONF DEFAULT compute_driver "libvirt.LibvirtDriver"
         LIBVIRT_FIREWALL_DRIVER=${LIBVIRT_FIREWALL_DRIVER:-"nova.virt.libvirt.firewall.IptablesFirewallDriver"}
-        add_nova_opt "firewall_driver=$LIBVIRT_FIREWALL_DRIVER"
+        iniset $NOVA_CONF DEFAULT firewall_driver "$LIBVIRT_FIREWALL_DRIVER"
     fi
 fi
 
@@ -1174,9 +1181,9 @@
     CREDS=$(keystone ec2-credentials-create --user_id $NOVA_USER_ID --tenant_id $NOVA_TENANT_ID)
     ACCESS_KEY=$(echo "$CREDS" | awk '/ access / { print $4 }')
     SECRET_KEY=$(echo "$CREDS" | awk '/ secret / { print $4 }')
-    add_nova_opt "s3_access_key=$ACCESS_KEY"
-    add_nova_opt "s3_secret_key=$SECRET_KEY"
-    add_nova_opt "s3_affix_tenant=True"
+    iniset $NOVA_CONF DEFAULT s3_access_key "$ACCESS_KEY"
+    iniset $NOVA_CONF DEFAULT s3_secret_key "$SECRET_KEY"
+    iniset $NOVA_CONF DEFAULT s3_affix_tenant "True"
 fi
 
 screen_it zeromq "cd $NOVA_DIR && $NOVA_BIN_DIR/nova-rpc-zmq-receiver"
@@ -1218,7 +1225,9 @@
 if is_service_enabled ceilometer; then
     echo_summary "Configuring Ceilometer"
     configure_ceilometer
+    configure_ceilometerclient
     echo_summary "Starting Ceilometer"
+    init_ceilometer
     start_ceilometer
 fi
 
@@ -1314,16 +1323,6 @@
     screen_it baremetal "nova-baremetal-deploy-helper"
 fi
 
-# Configure Tempest last to ensure that the runtime configuration of
-# the various OpenStack services can be queried.
-if is_service_enabled tempest; then
-    echo_summary "Configuring Tempest"
-    configure_tempest
-    echo '**************************************************'
-    echo_summary "Finished Configuring Tempest"
-    echo '**************************************************'
-fi
-
 # Save some values we generated for later use
 CURRENT_RUN_TIME=$(date "+$TIMESTAMP_FORMAT")
 echo "# $CURRENT_RUN_TIME" >$TOP_DIR/.stackenv
@@ -1333,6 +1332,16 @@
 done
 
 
+# Run extras
+# ==========
+
+if [[ -d $TOP_DIR/extras.d ]]; then
+    for i in $TOP_DIR/extras.d/*.sh; do
+        [[ -r $i ]] && source $i stack
+    done
+fi
+
+
 # Run local script
 # ================
 
diff --git a/stackrc b/stackrc
index 0e84db8..8d19440 100644
--- a/stackrc
+++ b/stackrc
@@ -12,6 +12,9 @@
 # Select the default database
 DATABASE_TYPE=mysql
 
+# Default stack user
+DEFAULT_STACK_USER=stack
+
 # Specify which services to launch.  These generally correspond to
 # screen tabs. To change the default list, use the ``enable_service`` and
 # ``disable_service`` functions in ``localrc``.
@@ -33,6 +36,10 @@
 CEILOMETER_REPO=${GIT_BASE}/openstack/ceilometer.git
 CEILOMETER_BRANCH=master
 
+# ceilometer client library
+CEILOMETERCLIENT_REPO=${GIT_BASE}/openstack/python-ceilometerclient
+CEILOMETERCLIENT_BRANCH=master
+
 # volume service
 CINDER_REPO=${GIT_BASE}/openstack/cinder
 CINDER_BRANCH=master
@@ -104,7 +111,7 @@
 HEAT_BRANCH=master
 
 # python heat client library
-HEATCLIENT_REPO=${GIT_BASE}/heat-api/python-heatclient.git
+HEATCLIENT_REPO=${GIT_BASE}/openstack/python-heatclient.git
 HEATCLIENT_BRANCH=master
 
 # ryu service
diff --git a/tests/functions.sh b/tests/functions.sh
index be48729..4fe6443 100755
--- a/tests/functions.sh
+++ b/tests/functions.sh
@@ -57,6 +57,9 @@
 
 [ ccc ]
 spaces  =  yes
+
+[ddd]
+empty =
 EOF
 
 # Test with spaces
@@ -79,13 +82,22 @@
 
 # Test with spaces in section header
 
-VAL=$(iniget test.ini ccc spaces)
+VAL=$(iniget test.ini " ccc " spaces)
 if [[ "$VAL" == "yes" ]]; then
     echo "OK: $VAL"
 else
     echo "iniget failed: $VAL"
 fi
 
+iniset test.ini "b b" opt_ion 42
+
+VAL=$(iniget test.ini "b b" opt_ion)
+if [[ "$VAL" == "42" ]]; then
+    echo "OK: $VAL"
+else
+    echo "iniget failed: $VAL"
+fi
+
 # Test without spaces, end of file
 
 VAL=$(iniget test.ini bbb handlers)
@@ -104,6 +116,29 @@
     echo "iniget failed: $VAL"
 fi
 
+# test empty option
+if ini_has_option test.ini ddd empty; then
+   echo "OK: ddd.empty present"
+else
+   echo "ini_has_option failed: ddd.empty not found"
+fi
+
+# test non-empty option
+if ini_has_option test.ini bbb handlers; then
+   echo "OK: bbb.handlers present"
+else
+   echo "ini_has_option failed: bbb.handlers not found"
+fi
+
+# test changing empty option
+iniset test.ini ddd empty "42"
+
+VAL=$(iniget test.ini ddd empty)
+if [[ "$VAL" == "42" ]]; then
+    echo "OK: $VAL"
+else
+    echo "iniget failed: $VAL"
+fi
 
 # Test section not exist
 
@@ -132,6 +167,12 @@
     echo "iniget failed: $VAL"
 fi
 
+if ! ini_has_option test.ini aaa debug; then
+    echo "OK aaa.debug not present"
+else
+    echo "ini_has_option failed: aaa.debug"
+fi
+
 iniset test.ini aaa debug "999"
 
 VAL=$(iniget test.ini aaa debug)
diff --git a/tools/build_ramdisk.sh b/tools/build_ramdisk.sh
index 5ff05b0..cfcca51 100755
--- a/tools/build_ramdisk.sh
+++ b/tools/build_ramdisk.sh
@@ -125,17 +125,17 @@
     # Create a stack user that is a member of the libvirtd group so that stack
     # is able to interact with libvirt.
     chroot $MNTDIR groupadd libvirtd
-    chroot $MNTDIR useradd stack -s /bin/bash -d $DEST -G libvirtd
+    chroot $MNTDIR useradd $DEFAULT_STACK_USER -s /bin/bash -d $DEST -G libvirtd
     mkdir -p $MNTDIR/$DEST
-    chroot $MNTDIR chown stack $DEST
+    chroot $MNTDIR chown $DEFAULT_STACK_USER $DEST
 
     # A simple password - pass
-    echo stack:pass | chroot $MNTDIR chpasswd
+    echo $DEFAULT_STACK_USER:pass | chroot $MNTDIR chpasswd
     echo root:$ROOT_PASSWORD | chroot $MNTDIR chpasswd
 
     # And has sudo ability (in the future this should be limited to only what
     # stack requires)
-    echo "stack ALL=(ALL) NOPASSWD: ALL" >> $MNTDIR/etc/sudoers
+    echo "$DEFAULT_STACK_USER ALL=(ALL) NOPASSWD: ALL" >> $MNTDIR/etc/sudoers
 
     umount $MNTDIR
     rmdir $MNTDIR
@@ -187,7 +187,7 @@
 # Use this version of devstack
 rm -rf $MNTDIR/$DEST/devstack
 cp -pr $CWD $MNTDIR/$DEST/devstack
-chroot $MNTDIR chown -R stack $DEST/devstack
+chroot $MNTDIR chown -R $DEFAULT_STACK_USER $DEST/devstack
 
 # Configure host network for DHCP
 mkdir -p $MNTDIR/etc/network
@@ -225,7 +225,7 @@
 
 # Make the run.sh executable
 chmod 755 $RUN_SH
-chroot $MNTDIR chown stack $DEST/run.sh
+chroot $MNTDIR chown $DEFAULT_STACK_USER $DEST/run.sh
 
 umount $MNTDIR
 rmdir $MNTDIR
diff --git a/tools/build_uec.sh b/tools/build_uec.sh
index 58c5425..5748b39 100755
--- a/tools/build_uec.sh
+++ b/tools/build_uec.sh
@@ -207,11 +207,11 @@
 `cat $TOP_DIR/localrc`
 LOCAL_EOF
 fi
-useradd -U -G sudo -s /bin/bash -d /opt/stack -m stack
-echo stack:pass | chpasswd
+useradd -U -G sudo -s /bin/bash -d /opt/stack -m $DEFAULT_STACK_USER
+echo $DEFAULT_STACK_USER:pass | chpasswd
 mkdir -p /opt/stack/.ssh
 echo "$PUB_KEY" > /opt/stack/.ssh/authorized_keys
-chown -R stack /opt/stack
+chown -R $DEFAULT_STACK_USER /opt/stack
 chmod 700 /opt/stack/.ssh
 chmod 600 /opt/stack/.ssh/authorized_keys
 
@@ -224,7 +224,7 @@
 
 # Run stack.sh
 cat >> $vm_dir/uec/user-data<<EOF
-su -c "cd /opt/stack/devstack && ./stack.sh" stack
+sudo -u $DEFAULT_STACK_USER bash -l -c "cd /opt/stack/devstack && ./stack.sh"
 EOF
 
 # (re)start a metadata service
diff --git a/tools/copy_dev_environment_to_uec.sh b/tools/copy_dev_environment_to_uec.sh
index 683a0d6..add4ff6 100755
--- a/tools/copy_dev_environment_to_uec.sh
+++ b/tools/copy_dev_environment_to_uec.sh
@@ -18,6 +18,9 @@
 # Change dir to top of devstack
 cd $TOP_DIR
 
+# Source params
+source ./stackrc
+
 # Echo usage
 usage() {
     echo "Add stack user and keys"
@@ -43,13 +46,13 @@
 # Create a stack user that is a member of the libvirtd group so that stack
 # is able to interact with libvirt.
 chroot $STAGING_DIR groupadd libvirtd || true
-chroot $STAGING_DIR useradd stack -s /bin/bash -d $DEST -G libvirtd || true
+chroot $STAGING_DIR useradd $DEFAULT_STACK_USER -s /bin/bash -d $DEST -G libvirtd || true
 
 # Add a simple password - pass
-echo stack:pass | chroot $STAGING_DIR chpasswd
+echo $DEFAULT_STACK_USER:pass | chroot $STAGING_DIR chpasswd
 
 # Configure sudo
-( umask 226 && echo "stack ALL=(ALL) NOPASSWD:ALL" \
+( umask 226 && echo "$DEFAULT_STACK_USER ALL=(ALL) NOPASSWD:ALL" \
     > $STAGING_DIR/etc/sudoers.d/50_stack_sh )
 
 # Copy over your ssh keys and env if desired
@@ -64,7 +67,7 @@
 cp_it . $STAGING_DIR/$DEST/devstack
 
 # Give stack ownership over $DEST so it may do the work needed
-chroot $STAGING_DIR chown -R stack $DEST
+chroot $STAGING_DIR chown -R $DEFAULT_STACK_USER $DEST
 
 # Unmount
 umount $STAGING_DIR
diff --git a/tools/create_userrc.sh b/tools/create_userrc.sh
index e39c157..55cb8fa 100755
--- a/tools/create_userrc.sh
+++ b/tools/create_userrc.sh
@@ -173,10 +173,10 @@
     fi
     cat >"$rcfile" <<EOF
 # you can source this file
-export EC2_ACCESS_KEY=$ec2_access_key
-export EC2_SECRET_KEY=$ec2_secret_key
-export EC2_URL=$EC2_URL
-export S3_URL=$S3_URL
+export EC2_ACCESS_KEY="$ec2_access_key"
+export EC2_SECRET_KEY="$ec2_secret_key"
+export EC2_URL="$EC2_URL"
+export S3_URL="$S3_URL"
 # OpenStack USER ID = $user_id
 export OS_USERNAME="$user_name"
 # Openstack Tenant ID = $tenant_id
@@ -210,7 +210,7 @@
     if [ -n "$role_id" ]; then
         echo $role_id
     else
-        keystone tenant-create --name "$role_name" |awk '/\|[[:space:]]*id[[:space:]]*\|.*\|/ {print $4}'
+        keystone role-create --name "$role_name" |awk '/\|[[:space:]]*id[[:space:]]*\|.*\|/ {print $4}'
     fi
 }
 
diff --git a/tools/make_cert.sh b/tools/make_cert.sh
new file mode 100755
index 0000000..cb93e57
--- /dev/null
+++ b/tools/make_cert.sh
@@ -0,0 +1,55 @@
+#!/bin/bash
+
+# **make_cert.sh**
+
+# Create a CA hierarchy (if necessary) and server certificate
+#
+# This mimics the CA structure that DevStack sets up when ``tls_proxy`` is enabled
+# but in the curent directory unless ``DATA_DIR`` is set
+
+ENABLE_TLS=True
+DATA_DIR=${DATA_DIR:-`pwd`/ca-data}
+
+ROOT_CA_DIR=$DATA_DIR/root
+INT_CA_DIR=$DATA_DIR/int
+
+# Import common functions
+source $TOP_DIR/functions
+
+# Import TLS functions
+source lib/tls
+
+function usage {
+    echo "$0 - Create CA and/or certs"
+    echo ""
+    echo "Usage: $0 commonName [orgUnit]"
+    exit 1
+}
+
+CN=$1
+if [ -z "$CN" ]]; then
+    usage
+fi
+ORG_UNIT_NAME=${2:-$ORG_UNIT_NAME}
+
+# Useful on OS/X
+if [[ `uname -s` == 'Darwin' && -d /usr/local/Cellar/openssl ]]; then
+    # set up for brew-installed modern OpenSSL
+    OPENSSL_CONF=/usr/local/etc/openssl/openssl.cnf
+    OPENSSL=/usr/local/Cellar/openssl/*/bin/openssl
+fi
+
+DEVSTACK_CERT_NAME=$CN
+DEVSTACK_HOSTNAME=$CN
+DEVSTACK_CERT=$DATA_DIR/$DEVSTACK_CERT_NAME.pem
+
+# Make sure the CA is set up
+configure_CA
+init_CA
+
+# Create the server cert
+make_cert $INT_CA_DIR $DEVSTACK_CERT_NAME $DEVSTACK_HOSTNAME
+
+# Create a cert bundle
+cat $INT_CA_DIR/private/$DEVSTACK_CERT_NAME.key $INT_CA_DIR/$DEVSTACK_CERT_NAME.crt $INT_CA_DIR/cacert.pem >$DEVSTACK_CERT
+
diff --git a/tools/xen/build_xva.sh b/tools/xen/build_xva.sh
index c359c55..f3f166f 100755
--- a/tools/xen/build_xva.sh
+++ b/tools/xen/build_xva.sh
@@ -65,8 +65,8 @@
 cat <<EOF >$STAGING_DIR/etc/rc.local
 # network restart required for getting the right gateway
 /etc/init.d/networking restart
-chown -R stack /opt/stack
-su -c "/opt/stack/run.sh > /opt/stack/run.sh.log" stack
+chown -R $DEFAULT_STACK_USER /opt/stack
+su -c "/opt/stack/run.sh > /opt/stack/run.sh.log" $DEFAULT_STACK_USER
 exit 0
 EOF
 
diff --git a/tools/xen/prepare_guest.sh b/tools/xen/prepare_guest.sh
index 4aa4554..fe52445 100755
--- a/tools/xen/prepare_guest.sh
+++ b/tools/xen/prepare_guest.sh
@@ -19,6 +19,7 @@
 STAGING_DIR=${STAGING_DIR:-stage}
 DO_TGZ=${DO_TGZ:-1}
 XS_TOOLS_PATH=${XS_TOOLS_PATH:-"/root/xs-tools.deb"}
+STACK_USER=${STACK_USER:-stack}
 
 # Install basics
 chroot $STAGING_DIR apt-get update
@@ -46,12 +47,12 @@
 
 # Add stack user
 chroot $STAGING_DIR groupadd libvirtd
-chroot $STAGING_DIR useradd stack -s /bin/bash -d /opt/stack -G libvirtd
-echo stack:$GUEST_PASSWORD | chroot $STAGING_DIR chpasswd
-echo "stack ALL=(ALL) NOPASSWD: ALL" >> $STAGING_DIR/etc/sudoers
+chroot $STAGING_DIR useradd $STACK_USER -s /bin/bash -d /opt/stack -G libvirtd
+echo $STACK_USER:$GUEST_PASSWORD | chroot $STAGING_DIR chpasswd
+echo "$STACK_USER ALL=(ALL) NOPASSWD: ALL" >> $STAGING_DIR/etc/sudoers
 
 # Give ownership of /opt/stack to stack user
-chroot $STAGING_DIR chown -R stack /opt/stack
+chroot $STAGING_DIR chown -R $STACK_USER /opt/stack
 
 # Make our ip address hostnames look nice at the command prompt
 echo "export PS1='${debian_chroot:+($debian_chroot)}\\u@\\H:\\w\\$ '" >> $STAGING_DIR/opt/stack/.bashrc
diff --git a/unstack.sh b/unstack.sh
index fd70916..1d4bfd5 100755
--- a/unstack.sh
+++ b/unstack.sh
@@ -39,6 +39,15 @@
     UNSTACK_ALL=${UNSTACK_ALL:-1}
 fi
 
+# Run extras
+# ==========
+
+if [[ -d $TOP_DIR/extras.d ]]; then
+    for i in $TOP_DIR/extras.d/*.sh; do
+        [[ -r $i ]] && source $i unstack
+    done
+fi
+
 if [[ "$Q_USE_DEBUG_COMMAND" == "True" ]]; then
     source $TOP_DIR/openrc
     teardown_quantum_debug