Merge "Allow devstack to build ironic agent ramdisk"
diff --git a/MAINTAINERS.rst b/MAINTAINERS.rst
index bdd9e78..1e915c7 100644
--- a/MAINTAINERS.rst
+++ b/MAINTAINERS.rst
@@ -55,6 +55,11 @@
 
 * Sergey Lukjanov <slukjanov@mirantis.com>
 
+Swift
+~~~~~
+
+* Chmouel Boudjnah <chmouel@enovance.com>
+
 SUSE
 ~~~~
 
diff --git a/docs/source/faq.html b/docs/source/faq.html
index bfac1dc..2c74a66 100644
--- a/docs/source/faq.html
+++ b/docs/source/faq.html
@@ -73,7 +73,7 @@
             <dd>A: DevStack is optimized for documentation &amp; developers.  As some of us use <a href="https://github.com/dellcloudedge/crowbar">Crowbar</a> for production deployments, we hope developers documenting how they setup systems for new features supports projects like Crowbar.</dd>
 
             <dt>Q: I'd like to help!</dt>
-            <dd>A: That isn't a question, but please do!  The source for DevStack is <a href="http://github.com/openstack-dev/devstack">github</a> and bug reports go to <a href="http://bugs.launchpad.net/devstack/">LaunchPad</a>.  Contributions follow the usual process as described in the <a href="http://wiki.openstack.org/HowToContribute">OpenStack wiki</a>. DevStack is not a core project but a gating project and therefore an official OpenStack project. This site is housed in the CloudBuilder's <a href="http://github.com/cloudbuilders/devstack">github</a> in the gh-pages branch.</dd>
+            <dd>A: That isn't a question, but please do!  The source for DevStack is <a href="http://github.com/openstack-dev/devstack">github</a> and bug reports go to <a href="http://bugs.launchpad.net/devstack/">LaunchPad</a>.  Contributions follow the usual process as described in the <a href="http://wiki.openstack.org/HowToContribute">OpenStack wiki</a> even though DevStack is not an official OpenStack project.  This site is housed in the CloudBuilder's <a href="http://github.com/cloudbuilders/devstack">github</a> in the gh-pages branch.</dd>
 
             <dt>Q: Why not use packages?</dt>
             <dd>A: Unlike packages, DevStack leaves your cloud ready to develop - checkouts of the code and services running in screen. However, many people are doing the hard work of packaging and recipes for production deployments.  We hope this script serves as a way to communicate configuration changes between developers and packagers.</dd>
@@ -85,7 +85,7 @@
             <dd>A: Fedora and CentOS/RHEL are supported via rpm dependency files and specific checks in <code>stack.sh</code>.  Support will follow the pattern set with the Ubuntu testing, i.e. only a single release of the distro will receive regular testing, others will be handled on a best-effort basis.</dd>
 
             <dt>Q: Are there any differences between Ubuntu and Fedora support?</dt>
-            <dd>A: LXC support is not complete on Fedora; Neutron is not fully supported prior to Fedora 18 due lack of OpenVSwitch packages.</dd>
+            <dd>A: Neutron is not fully supported prior to Fedora 18 due lack of OpenVSwitch packages.</dd>
 
             <dt>Q: How about RHEL 6?</dt>
             <dd>A: RHEL 6 has Python 2.6 and many old modules packaged and is a challenge to support.  There are a number of specific RHEL6 work-arounds in <code>stack.sh</code> to handle this.  But the testing on py26 is valuable so we do it...</dd>
diff --git a/docs/source/guides/multinode-lab.html b/docs/source/guides/multinode-lab.html
index 2e52379..a286954 100644
--- a/docs/source/guides/multinode-lab.html
+++ b/docs/source/guides/multinode-lab.html
@@ -184,7 +184,13 @@
 MYSQL_HOST=192.168.42.11
 RABBIT_HOST=192.168.42.11
 GLANCE_HOSTPORT=192.168.42.11:9292
-ENABLED_SERVICES=n-cpu,n-net,n-api,c-sch,c-api,c-vol</pre>
+ENABLED_SERVICES=n-cpu,n-net,n-api,c-sch,c-api,c-vol
+NOVA_VNC_ENABLED=True
+NOVNCPROXY_URL="http://192.168.42.11:6080/vnc_auto.html"
+VNCSERVER_LISTEN=$HOST_IP
+VNCSERVER_PROXYCLIENT_ADDRESS=$VNCSERVER_LISTEN
+</pre>
+
 <!-- save for vlan
 FLAT_INTERFACE=eth0.926
 -->
diff --git a/extras.d/70-sahara.sh b/extras.d/70-sahara.sh
index 80e07ff..2a34999 100644
--- a/extras.d/70-sahara.sh
+++ b/extras.d/70-sahara.sh
@@ -4,21 +4,15 @@
     if [[ "$1" == "source" ]]; then
         # Initial source
         source $TOP_DIR/lib/sahara
-        source $TOP_DIR/lib/sahara-dashboard
     elif [[ "$1" == "stack" && "$2" == "install" ]]; then
         echo_summary "Installing sahara"
         install_sahara
+        install_python_saharaclient
         cleanup_sahara
-        if is_service_enabled horizon; then
-            install_sahara_dashboard
-        fi
     elif [[ "$1" == "stack" && "$2" == "post-config" ]]; then
         echo_summary "Configuring sahara"
         configure_sahara
         create_sahara_accounts
-        if is_service_enabled horizon; then
-            configure_sahara_dashboard
-        fi
     elif [[ "$1" == "stack" && "$2" == "extra" ]]; then
         echo_summary "Initializing sahara"
         start_sahara
@@ -26,9 +20,6 @@
 
     if [[ "$1" == "unstack" ]]; then
         stop_sahara
-        if is_service_enabled horizon; then
-            cleanup_sahara_dashboard
-        fi
     fi
 
     if [[ "$1" == "clean" ]]; then
diff --git a/files/apache-keystone.template b/files/apache-keystone.template
index 7954a86..1bdb84c 100644
--- a/files/apache-keystone.template
+++ b/files/apache-keystone.template
@@ -6,9 +6,9 @@
     WSGIProcessGroup keystone-public
     WSGIScriptAlias / %PUBLICWSGI%
     WSGIApplicationGroup %{GLOBAL}
+    %ERRORLOGFORMAT%
     ErrorLog /var/log/%APACHE_NAME%/keystone.log
-    LogLevel debug
-    CustomLog /var/log/%APACHE_NAME%/access.log combined
+    CustomLog /var/log/%APACHE_NAME%/keystone_access.log combined
 </VirtualHost>
 
 <VirtualHost *:%ADMINPORT%>
@@ -16,9 +16,9 @@
     WSGIProcessGroup keystone-admin
     WSGIScriptAlias / %ADMINWSGI%
     WSGIApplicationGroup %{GLOBAL}
+    %ERRORLOGFORMAT%
     ErrorLog /var/log/%APACHE_NAME%/keystone.log
-    LogLevel debug
-    CustomLog /var/log/%APACHE_NAME%/access.log combined
+    CustomLog /var/log/%APACHE_NAME%/keystone_access.log combined
 </VirtualHost>
 
 # Workaround for missing path on RHEL6, see
diff --git a/files/apts/general b/files/apts/general
index 739fc47..c308c46 100644
--- a/files/apts/general
+++ b/files/apts/general
@@ -7,6 +7,7 @@
 psmisc
 gcc
 git
+graphviz # testonly - docs
 lsof # useful when debugging
 openssh-server
 openssl
diff --git a/files/apts/neutron b/files/apts/neutron
index d3a08c7..23dd65b 100644
--- a/files/apts/neutron
+++ b/files/apts/neutron
@@ -2,6 +2,7 @@
 iptables
 iputils-ping
 iputils-arping
+libmysqlclient-dev  # testonly
 mysql-server #NOPRIME
 sudo
 python-boto
diff --git a/files/apts/nova b/files/apts/nova
index 090ca4d..114194e 100644
--- a/files/apts/nova
+++ b/files/apts/nova
@@ -4,6 +4,7 @@
 kpartx
 parted
 iputils-arping
+libmysqlclient-dev  # testonly
 mysql-server # NOPRIME
 python-mysqldb
 python-mysql.connector
diff --git a/files/apts/q-agt b/files/apts/q-agt
new file mode 100644
index 0000000..ea8819e
--- /dev/null
+++ b/files/apts/q-agt
@@ -0,0 +1 @@
+ipset
diff --git a/files/rpms-suse/general b/files/rpms-suse/general
index 82cb09d..0a4746f 100644
--- a/files/rpms-suse/general
+++ b/files/rpms-suse/general
@@ -5,6 +5,7 @@
 euca2ools
 gcc
 git-core
+graphviz # testonly - docs
 iputils
 libopenssl-devel # to rebuild pyOpenSSL if needed
 lsof # useful when debugging
diff --git a/files/rpms-suse/q-agt b/files/rpms-suse/q-agt
new file mode 100644
index 0000000..ea8819e
--- /dev/null
+++ b/files/rpms-suse/q-agt
@@ -0,0 +1 @@
+ipset
diff --git a/files/rpms/general b/files/rpms/general
index 74997a8..7a35961 100644
--- a/files/rpms/general
+++ b/files/rpms/general
@@ -4,6 +4,7 @@
 euca2ools # only for testing client
 gcc
 git-core
+graphviz # testonly - docs
 openssh-server
 openssl
 openssl-devel # to rebuild pyOpenSSL if needed
diff --git a/files/rpms/neutron b/files/rpms/neutron
index aaff48a..c56e6e2 100644
--- a/files/rpms/neutron
+++ b/files/rpms/neutron
@@ -5,6 +5,7 @@
 iptables
 iputils
 mysql-connector-python
+mysql-devel  # testonly
 mysql-server # NOPRIME
 openvswitch # NOPRIME
 python-boto
diff --git a/files/rpms/nova b/files/rpms/nova
index ccee8a7..4c2ee57 100644
--- a/files/rpms/nova
+++ b/files/rpms/nova
@@ -16,6 +16,7 @@
 numpy # needed by websockify for spice console
 m2crypto
 mysql-connector-python
+mysql-devel  # testonly
 mysql-server # NOPRIME
 parted
 polkit
diff --git a/files/rpms/q-agt b/files/rpms/q-agt
new file mode 100644
index 0000000..ea8819e
--- /dev/null
+++ b/files/rpms/q-agt
@@ -0,0 +1 @@
+ipset
diff --git a/functions-common b/functions-common
index c096664..3d66a0b 100644
--- a/functions-common
+++ b/functions-common
@@ -695,6 +695,13 @@
     echo $host_ip
 }
 
+# Generates hex string from ``size`` byte of pseudo random data
+# generate_hex_string size
+function generate_hex_string {
+    local size=$1
+    hexdump -n "$size" -v -e '/1 "%02x"' /dev/urandom
+}
+
 # Grab a numbered field from python prettytable output
 # Fields are numbered starting with 1
 # Reverse syntax is supported: -1 is the last field, -2 is second to last, etc.
@@ -1393,6 +1400,19 @@
         $cmd_pip install --build=${pip_build_tmp} \
         $pip_mirror_opt $@ \
         && $sudo_pip rm -rf ${pip_build_tmp}
+
+    if [[ "$INSTALL_TESTONLY_PACKAGES" == "True" ]]; then
+        local test_req="$@/test-requirements.txt"
+        if [[ -e "$test_req" ]]; then
+            $sudo_pip PIP_DOWNLOAD_CACHE=${PIP_DOWNLOAD_CACHE:-/var/cache/pip} \
+                http_proxy=$http_proxy \
+                https_proxy=$https_proxy \
+                no_proxy=$no_proxy \
+                $cmd_pip install --build=${pip_build_tmp} \
+                $pip_mirror_opt -r $test_req \
+                && $sudo_pip rm -rf ${pip_build_tmp}
+        fi
+    fi
 }
 
 # this should be used if you want to install globally, all libraries should
@@ -1596,6 +1616,7 @@
         [[ ${service} == "trove" && ${ENABLED_SERVICES} =~ "tr-" ]] && enabled=0
         [[ ${service} == "swift" && ${ENABLED_SERVICES} =~ "s-" ]] && enabled=0
         [[ ${service} == s-* && ${ENABLED_SERVICES} =~ "swift" ]] && enabled=0
+        [[ ${service} == key-* && ${ENABLED_SERVICES} =~ "key" ]] && enabled=0
     done
     $xtrace
     return $enabled
diff --git a/lib/apache b/lib/apache
index f4f82a1..6d22290 100644
--- a/lib/apache
+++ b/lib/apache
@@ -61,6 +61,28 @@
     fi
 }
 
+# get_apache_version() - return the version of Apache installed
+# This function is used to determine the Apache version installed. There are
+# various differences between Apache 2.2 and 2.4 that warrant special handling.
+function get_apache_version {
+    if is_ubuntu; then
+        local version_str=$(sudo /usr/sbin/apache2ctl -v | awk '/Server version/ {print $3}' | cut -f2 -d/)
+    elif is_fedora; then
+        local version_str=$(rpm -qa --queryformat '%{VERSION}' httpd)
+    elif is_suse; then
+        local version_str=$(rpm -qa --queryformat '%{VERSION}' apache2)
+    else
+        exit_distro_not_supported "cannot determine apache version"
+    fi
+    if [[ "$version_str" =~ ^2\.2\. ]]; then
+        echo "2.2"
+    elif [[ "$version_str" =~ ^2\.4\. ]]; then
+        echo "2.4"
+    else
+        exit_distro_not_supported "apache version not supported"
+    fi
+}
+
 # apache_site_config_for() - The filename of the site's configuration file.
 # This function uses the global variables APACHE_NAME and APACHE_CONF_DIR.
 #
@@ -87,8 +109,8 @@
 function apache_site_config_for {
     local site=$@
     if is_ubuntu; then
-        local apache_version=$(sudo /usr/sbin/apache2ctl -v | awk '/Server version/ {print $3}' | cut -f2 -d/)
-        if [[ "$apache_version" =~ ^2\.2\. ]]; then
+        local apache_version=$(get_apache_version)
+        if [[ "$apache_version" == "2.2" ]]; then
             # Ubuntu 12.04 - Apache 2.2
             echo $APACHE_CONF_DIR/${site}
         else
diff --git a/lib/cinder_backends/glusterfs b/lib/cinder_backends/glusterfs
new file mode 100644
index 0000000..dd772a8
--- /dev/null
+++ b/lib/cinder_backends/glusterfs
@@ -0,0 +1,46 @@
+# lib/cinder_backends/glusterfs
+# Configure the glusterfs backend
+
+# Enable with:
+#
+#   CINDER_ENABLED_BACKENDS+=,glusterfs:<volume-type-name>
+
+# Dependencies:
+#
+# - ``functions`` file
+# - ``cinder`` configurations
+
+# CINDER_CONF
+# CINDER_CONF_DIR
+# CINDER_GLUSTERFS_SHARES - Contents of glusterfs shares config file
+
+# configure_cinder_backend_glusterfs - Configure Cinder for GlusterFS backends
+
+# Save trace setting
+GLUSTERFS_XTRACE=$(set +o | grep xtrace)
+set +o xtrace
+
+
+# Entry Points
+# ------------
+
+# configure_cinder_backend_glusterfs - Set config files, create data dirs, etc
+function configure_cinder_backend_glusterfs {
+    local be_name=$1
+    iniset $CINDER_CONF $be_name volume_backend_name $be_name
+    iniset $CINDER_CONF $be_name volume_driver "cinder.volume.drivers.glusterfs.GlusterfsDriver"
+    iniset $CINDER_CONF $be_name glusterfs_shares_config "$CINDER_CONF_DIR/glusterfs-shares-$be_name.conf"
+
+    if [[ -n "$CINDER_GLUSTERFS_SHARES" ]]; then
+        CINDER_GLUSTERFS_SHARES=$(echo $CINDER_GLUSTERFS_SHARES | tr ";" "\n")
+        echo "$CINDER_GLUSTERFS_SHARES" | tee "$CINDER_CONF_DIR/glusterfs-shares-$be_name.conf"
+    fi
+}
+
+
+# Restore xtrace
+$GLUSTERFS_XTRACE
+
+# Local variables:
+# mode: shell-script
+# End:
diff --git a/lib/cinder_backends/solidfire b/lib/cinder_backends/solidfire
new file mode 100644
index 0000000..95ffce1
--- /dev/null
+++ b/lib/cinder_backends/solidfire
@@ -0,0 +1,47 @@
+# lib/cinder_backends/solidfire
+# Configure the solidfire driver
+
+# Enable with:
+#
+#   CINDER_ENABLED_BACKENDS+=,solidfire:<volume-type-name>
+
+# Dependencies:
+#
+# - ``functions`` file
+# - ``cinder`` configurations
+
+# CINDER_CONF
+
+# configure_cinder_driver - make configuration changes, including those to other services
+
+# Save trace setting
+MY_XTRACE=$(set +o | grep xtrace)
+set +o xtrace
+
+
+# Entry Points
+# ------------
+
+# configure_cinder_backend_solidfire - Set config files, create data dirs, etc
+function configure_cinder_backend_solidfire {
+    # To use SolidFire, set the following in local.conf:
+    # CINDER_ENABLED_BACKENDS+=,solidfire:<volume-type-name>
+    # SAN_IP=<mvip>
+    # SAN_LOGIN=<cluster-admin-account>
+    # SAN_PASSWORD=<cluster-admin-password>
+
+    local be_name=$1
+    iniset $CINDER_CONF $be_name volume_backend_name $be_name
+    iniset $CINDER_CONF $be_name volume_driver "cinder.volume.drivers.solidfire.SolidFireDriver"
+    iniset $CINDER_CONF $be_name san_ip $SAN_IP
+    iniset $CINDER_CONF $be_name san_login $SAN_LOGIN
+    iniset $CINDER_CONF $be_name san_password $SAN_PASSWORD
+}
+
+
+# Restore xtrace
+$MY_XTRACE
+
+# Local variables:
+# mode: shell-script
+# End:
diff --git a/lib/cinder_plugins/solidfire b/lib/cinder_plugins/solidfire
deleted file mode 100644
index 2c970b5..0000000
--- a/lib/cinder_plugins/solidfire
+++ /dev/null
@@ -1,48 +0,0 @@
-# lib/cinder_plugins/solidfire
-# Configure the solidfire driver
-
-# Enable with:
-#
-#   CINDER_DRIVER=solidfire
-
-# Dependencies:
-#
-# - ``functions`` file
-# - ``cinder`` configurations
-
-# configure_cinder_driver - make configuration changes, including those to other services
-
-# Save trace setting
-MY_XTRACE=$(set +o | grep xtrace)
-set +o xtrace
-
-
-# Defaults
-# --------
-
-# Set up default directories
-
-
-# Entry Points
-# ------------
-
-# configure_cinder_driver - Set config files, create data dirs, etc
-function configure_cinder_driver {
-    # To use solidfire, set the following in localrc:
-    # CINDER_DRIVER=solidfire
-    # SAN_IP=<mvip>
-    # SAN_LOGIN=<cluster-admin-account>
-    # SAN_PASSWORD=<cluster-admin-password>
-
-    iniset $CINDER_CONF DEFAULT volume_driver "cinder.volume.drivers.solidfire.SolidFireDriver"
-    iniset $CINDER_CONF DEFAULT san_ip $SAN_IP
-    iniset $CINDER_CONF DEFAULT san_login $SAN_LOGIN
-    iniset $CINDER_CONF DEFAULT san_password $SAN_PASSWORD
-}
-
-# Restore xtrace
-$MY_XTRACE
-
-# Local variables:
-# mode: shell-script
-# End:
diff --git a/lib/dstat b/lib/dstat
new file mode 100644
index 0000000..a2c522c
--- /dev/null
+++ b/lib/dstat
@@ -0,0 +1,41 @@
+# lib/apache
+# Functions to start and stop dstat
+
+# Dependencies:
+#
+# - ``functions`` file
+
+# ``stack.sh`` calls the entry points in this order:
+#
+# - start_dstat
+# - stop_dstat
+
+# Save trace setting
+XTRACE=$(set +o | grep xtrace)
+set +o xtrace
+
+
+# Defaults
+# --------
+# for DSTAT logging
+DSTAT_FILE=${DSTAT_FILE:-"dstat.txt"}
+
+
+# start_dstat() - Start running processes, including screen
+function start_dstat {
+    # A better kind of sysstat, with the top process per time slice
+    DSTAT_OPTS="-tcmndrylp --top-cpu-adv"
+    if [[ -n ${SCREEN_LOGDIR} ]]; then
+        screen_it dstat "cd $TOP_DIR; dstat $DSTAT_OPTS | tee $SCREEN_LOGDIR/$DSTAT_FILE"
+    else
+        screen_it dstat "dstat $DSTAT_OPTS"
+    fi
+}
+
+# stop_dstat() stop dstat process
+function stop_dstat {
+    screen_stop dstat
+}
+
+# Restore xtrace
+$XTRACE
diff --git a/lib/glance b/lib/glance
index 1dea6cf..7a28b68 100644
--- a/lib/glance
+++ b/lib/glance
@@ -106,7 +106,6 @@
     inicomment $GLANCE_API_CONF DEFAULT log_file
     iniset $GLANCE_API_CONF DEFAULT sql_connection $dburl
     iniset $GLANCE_API_CONF DEFAULT use_syslog $SYSLOG
-    iniset $GLANCE_API_CONF DEFAULT filesystem_store_datadir $GLANCE_IMAGE_DIR/
     iniset $GLANCE_API_CONF DEFAULT image_cache_dir $GLANCE_CACHE_DIR/
     iniset $GLANCE_API_CONF paste_deploy flavor keystone+cachemanagement
     iniset $GLANCE_API_CONF keystone_authtoken identity_uri $KEYSTONE_AUTH_URI
@@ -125,6 +124,13 @@
         iniset $GLANCE_API_CONF DEFAULT disk_formats "ami,ari,aki,vhd,raw,iso"
     fi
 
+    # Store specific configs
+    iniset $GLANCE_API_CONF DEFAULT filesystem_store_datadir $GLANCE_IMAGE_DIR/
+
+    # NOTE(flaper87): Until Glance is fully migrated, set these configs in both
+    # sections.
+    iniset $GLANCE_API_CONF glance_store filesystem_store_datadir $GLANCE_IMAGE_DIR/
+
     # Store the images in swift if enabled.
     if is_service_enabled s-proxy; then
         iniset $GLANCE_API_CONF DEFAULT default_store swift
@@ -134,6 +140,15 @@
         iniset $GLANCE_API_CONF DEFAULT swift_store_create_container_on_put True
 
         iniset $GLANCE_API_CONF DEFAULT known_stores "glance.store.filesystem.Store, glance.store.http.Store, glance.store.swift.Store"
+
+        # NOTE(flaper87): Until Glance is fully migrated, set these configs in both
+        # sections.
+        iniset $GLANCE_API_CONF glance_store default_store swift
+        iniset $GLANCE_API_CONF glance_store swift_store_auth_address $KEYSTONE_SERVICE_URI/v2.0/
+        iniset $GLANCE_API_CONF glance_store swift_store_user $SERVICE_TENANT_NAME:glance-swift
+        iniset $GLANCE_API_CONF glance_store swift_store_key $SERVICE_PASSWORD
+        iniset $GLANCE_API_CONF glance_store swift_store_create_container_on_put True
+        iniset $GLANCE_API_CONF glance_store stores "file, http, swift"
     fi
 
     cp -p $GLANCE_DIR/etc/glance-registry-paste.ini $GLANCE_REGISTRY_PASTE_INI
@@ -144,7 +159,6 @@
     iniset $GLANCE_CACHE_CONF DEFAULT debug $ENABLE_DEBUG_LOG_LEVEL
     inicomment $GLANCE_CACHE_CONF DEFAULT log_file
     iniset $GLANCE_CACHE_CONF DEFAULT use_syslog $SYSLOG
-    iniset $GLANCE_CACHE_CONF DEFAULT filesystem_store_datadir $GLANCE_IMAGE_DIR/
     iniset $GLANCE_CACHE_CONF DEFAULT image_cache_dir $GLANCE_CACHE_DIR/
     iniuncomment $GLANCE_CACHE_CONF DEFAULT auth_url
     iniset $GLANCE_CACHE_CONF DEFAULT auth_url $KEYSTONE_AUTH_URI/v2.0
@@ -155,6 +169,12 @@
     iniuncomment $GLANCE_CACHE_CONF DEFAULT auth_password
     iniset $GLANCE_CACHE_CONF DEFAULT admin_password $SERVICE_PASSWORD
 
+    # Store specific confs
+    # NOTE(flaper87): Until Glance is fully migrated, set these configs in both
+    # sections.
+    iniset $GLANCE_CACHE_CONF DEFAULT filesystem_store_datadir $GLANCE_IMAGE_DIR/
+    iniset $GLANCE_CACHE_CONF glance_store filesystem_store_datadir $GLANCE_IMAGE_DIR/
+
     cp -p $GLANCE_DIR/etc/policy.json $GLANCE_POLICY_JSON
     cp -p $GLANCE_DIR/etc/schema-image.json $GLANCE_SCHEMA_JSON
 }
diff --git a/lib/heat b/lib/heat
index bd99d6b..14094a9 100644
--- a/lib/heat
+++ b/lib/heat
@@ -98,7 +98,7 @@
     iniset $HEAT_CONF DEFAULT heat_waitcondition_server_url http://$HEAT_API_CFN_HOST:$HEAT_API_CFN_PORT/v1/waitcondition
     iniset $HEAT_CONF DEFAULT heat_watch_server_url http://$HEAT_API_CW_HOST:$HEAT_API_CW_PORT
     iniset $HEAT_CONF database connection `database_connection_url heat`
-    iniset $HEAT_CONF DEFAULT auth_encryption_key `hexdump -n 16 -v -e '/1 "%02x"' /dev/urandom`
+    iniset $HEAT_CONF DEFAULT auth_encryption_key $(generate_hex_string 16)
 
     iniset $HEAT_CONF DEFAULT region_name_for_services "$REGION_NAME"
 
diff --git a/lib/ironic b/lib/ironic
index bea6fa9..fd7c816 100644
--- a/lib/ironic
+++ b/lib/ironic
@@ -75,7 +75,8 @@
 IRONIC_DEPLOY_KERNEL=${IRONIC_DEPLOY_KERNEL:-}
 IRONIC_DEPLOY_ELEMENT=${IRONIC_DEPLOY_ELEMENT:-deploy-ironic}
 
-IRONIC_AGENT_TARBALL=${IRONIC_AGENT_TARBALL:-http://tarballs.openstack.org/ironic-python-agent/coreos/ipa-coreos.tar.gz}
+IRONIC_AGENT_KERNEL_URL=${IRONIC_AGENT_KERNEL_URL:-http://tarballs.openstack.org/ironic-python-agent/coreos/files/coreos_production_pxe.vmlinuz}
+IRONIC_AGENT_RAMDISK_URL=${IRONIC_AGENT_RAMDISK_URL:-http://tarballs.openstack.org/ironic-python-agent/coreos/files/coreos_production_pxe-oem.cpio.gz}
 
 # Which deploy driver to use - valid choices right now
 # are 'pxe_ssh' and 'agent_ssh'.
@@ -608,12 +609,8 @@
         else
             if [ "$IRONIC_DEPLOY_DRIVER" == "agent_ssh" ]; then
                 # download the agent image tarball
-                wget "$IRONIC_AGENT_TARBALL" -O ironic_agent_tarball.tar.gz
-                tar zxfv ironic_agent_tarball.tar.gz
-                mv UPLOAD/coreos_production_pxe.vmlinuz $IRONIC_DEPLOY_KERNEL_PATH
-                mv UPLOAD/coreos_production_pxe_image-oem.cpio.gz $IRONIC_DEPLOY_RAMDISK_PATH
-                rm -rf UPLOAD
-                rm ironic_agent_tarball.tar.gz
+                wget "$IRONIC_AGENT_KERNEL_URL" -O $IRONIC_DEPLOY_KERNEL_PATH
+                wget "$IRONIC_AGENT_RAMDISK_URL" -O $IRONIC_DEPLOY_RAMDISK_PATH
             else
                 die $LINENO "Deploy kernel+ramdisk files don't exist and their building was disabled explicitly by IRONIC_BUILD_DEPLOY_RAMDISK"
             fi
diff --git a/lib/keystone b/lib/keystone
index c6e17ca..da5cf89 100644
--- a/lib/keystone
+++ b/lib/keystone
@@ -123,6 +123,13 @@
     sudo mkdir -p $KEYSTONE_WSGI_DIR
 
     local keystone_apache_conf=$(apache_site_config_for keystone)
+    local apache_version=$(get_apache_version)
+
+    if [[ ${apache_version#*\.} -ge 4 ]]; then
+        # Apache 2.4 supports custom error log formats
+        # this should mirror the original log formatting.
+        local errorlogformat='ErrorLogFormat "%{cu}t %M"'
+    fi
 
     # copy proxy vhost and wsgi file
     sudo cp $KEYSTONE_DIR/httpd/keystone.py $KEYSTONE_WSGI_DIR/main
@@ -136,6 +143,7 @@
         s|%PUBLICWSGI%|$KEYSTONE_WSGI_DIR/main|g;
         s|%ADMINWSGI%|$KEYSTONE_WSGI_DIR/admin|g;
         s|%USER%|$STACK_USER|g
+        s|%ERRORLOGFORMAT%|$errorlogformat|g;
     " -i $keystone_apache_conf
     enable_apache_site keystone
 }
@@ -229,11 +237,11 @@
     iniset $KEYSTONE_CONF ec2 driver "keystone.contrib.ec2.backends.sql.Ec2"
 
     if [[ "$KEYSTONE_TOKEN_BACKEND" = "sql" ]]; then
-        iniset $KEYSTONE_CONF token driver keystone.token.backends.sql.Token
+        iniset $KEYSTONE_CONF token driver keystone.token.persistence.backends.sql.Token
     elif [[ "$KEYSTONE_TOKEN_BACKEND" = "memcache" ]]; then
-        iniset $KEYSTONE_CONF token driver keystone.token.backends.memcache.Token
+        iniset $KEYSTONE_CONF token driver keystone.token.persistence.backends.memcache.Token
     else
-        iniset $KEYSTONE_CONF token driver keystone.token.backends.kvs.Token
+        iniset $KEYSTONE_CONF token driver keystone.token.persistence.backends.kvs.Token
     fi
 
     if [[ "$KEYSTONE_CATALOG_BACKEND" = "sql" ]]; then
@@ -349,9 +357,8 @@
     # The Member role is used by Horizon and Swift so we need to keep it:
     local member_role=$(get_or_create_role "Member")
 
-    # ANOTHER_ROLE demonstrates that an arbitrary role may be created and used
+    # another_role demonstrates that an arbitrary role may be created and used
     # TODO(sleepsonthefloor): show how this can be used for rbac in the future!
-
     local another_role=$(get_or_create_role "anotherrole")
 
     # invisible tenant - admin can't see this one
@@ -468,6 +475,7 @@
     if [ "$KEYSTONE_USE_MOD_WSGI" == "True" ]; then
         restart_apache_server
         screen_it key "cd $KEYSTONE_DIR && sudo tail -f /var/log/$APACHE_NAME/keystone.log"
+        screen_it key-access "sudo tail -f /var/log/$APACHE_NAME/keystone_access.log"
     else
         # Start Keystone in a screen window
         screen_it key "cd $KEYSTONE_DIR && $KEYSTONE_DIR/bin/keystone-all --config-file $KEYSTONE_CONF --debug"
diff --git a/lib/neutron b/lib/neutron
index e6de4b5..a00664e 100644
--- a/lib/neutron
+++ b/lib/neutron
@@ -423,7 +423,7 @@
     iniset $NOVA_CONF libvirt vif_driver "$NOVA_VIF_DRIVER"
     iniset $NOVA_CONF DEFAULT linuxnet_interface_driver "$LINUXNET_VIF_DRIVER"
     if is_service_enabled q-meta; then
-        iniset $NOVA_CONF DEFAULT service_neutron_metadata_proxy "True"
+        iniset $NOVA_CONF neutron service_metadata_proxy "True"
     fi
 
     iniset $NOVA_CONF DEFAULT vif_plugging_is_fatal "$VIF_PLUGGING_IS_FATAL"
diff --git a/lib/neutron_plugins/ovs_base b/lib/neutron_plugins/ovs_base
index 8375bb6..d913f7c 100644
--- a/lib/neutron_plugins/ovs_base
+++ b/lib/neutron_plugins/ovs_base
@@ -51,6 +51,7 @@
     install_package $(get_packages "openvswitch")
     if is_ubuntu; then
         _neutron_ovs_base_install_ubuntu_dkms
+        restart_service openvswitch-switch
     elif is_fedora; then
         restart_service openvswitch
     elif is_suse; then
diff --git a/lib/nova b/lib/nova
index 892aace..b3a586c 100644
--- a/lib/nova
+++ b/lib/nova
@@ -84,6 +84,10 @@
     | grep ^[ep] \
     | head -1)
 
+# $NOVA_VNC_ENABLED can be used to forcibly enable vnc configuration.
+# In multi-node setups allows compute hosts to not run n-novnc.
+NOVA_VNC_ENABLED=$(trueorfalse False $NOVA_VNC_ENABLED)
+
 # Get hypervisor configuration
 # ----------------------------
 
@@ -485,7 +489,7 @@
         iniset $NOVA_CONF spice html5proxy_base_url "$SPICEHTML5PROXY_URL"
     fi
 
-    if is_service_enabled n-novnc || is_service_enabled n-xvnc; then
+    if is_service_enabled n-novnc || is_service_enabled n-xvnc || [ "$NOVA_VNC_ENABLED" != False ]; then
         # 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}
diff --git a/lib/nova_plugins/functions-libvirt b/lib/nova_plugins/functions-libvirt
index 258e1a4..f722836 100644
--- a/lib/nova_plugins/functions-libvirt
+++ b/lib/nova_plugins/functions-libvirt
@@ -57,7 +57,7 @@
 EOF
     fi
 
-    if is_ubuntu; then
+    if [ "$os_VENDOR" = "Ubuntu" ]; then
         LIBVIRT_DAEMON=libvirt-bin
     else
         LIBVIRT_DAEMON=libvirtd
diff --git a/lib/oslo b/lib/oslo
index 025815c..e5fa37e 100644
--- a/lib/oslo
+++ b/lib/oslo
@@ -22,10 +22,15 @@
 # --------
 CLIFF_DIR=$DEST/cliff
 OSLOCFG_DIR=$DEST/oslo.config
+OSLOCON_DIR=$DEST/oslo.concurrency
 OSLODB_DIR=$DEST/oslo.db
 OSLOI18N_DIR=$DEST/oslo.i18n
+OSLOLOG_DIR=$DEST/oslo.log
+OSLOMID_DIR=$DEST/oslo.middleware
 OSLOMSG_DIR=$DEST/oslo.messaging
 OSLORWRAP_DIR=$DEST/oslo.rootwrap
+OSLOSERIALIZATION_DIR=$DEST/oslo.serialization
+OSLOUTILS_DIR=$DEST/oslo.utils
 OSLOVMWARE_DIR=$DEST/oslo.vmware
 PYCADF_DIR=$DEST/pycadf
 STEVEDORE_DIR=$DEST/stevedore
@@ -45,9 +50,24 @@
     git_clone $OSLOI18N_REPO $OSLOI18N_DIR $OSLOI18N_BRANCH
     setup_install $OSLOI18N_DIR
 
+    git_clone $OSLOUTILS_REPO $OSLOUTILS_DIR $OSLOUTILS_BRANCH
+    setup_install $OSLOUTILS_DIR
+
+    git_clone $OSLOSERIALIZATION_REPO $OSLOSERIALIZATION_DIR $OSLOSERIALIZATION_BRANCH
+    setup_install $OSLOSERIALIZATION_DIR
+
     git_clone $OSLOCFG_REPO $OSLOCFG_DIR $OSLOCFG_BRANCH
     setup_install $OSLOCFG_DIR
 
+    git_clone $OSLOCON_REPO $OSLOCON_DIR $OSLOCON_BRANCH
+    setup_install $OSLOCON_DIR
+
+    git_clone $OSLOLOG_REPO $OSLOLOG_DIR $OSLOLOG_BRANCH
+    setup_install $OSLOLOG_DIR
+
+    git_clone $OSLOMID_REPO $OSLOMID_DIR $OSLOMID_BRANCH
+    setup_install $OSLOMID_DIR
+
     git_clone $OSLOMSG_REPO $OSLOMSG_DIR $OSLOMSG_BRANCH
     setup_install $OSLOMSG_DIR
 
diff --git a/lib/sahara b/lib/sahara
index 37876dc..70319d9 100644
--- a/lib/sahara
+++ b/lib/sahara
@@ -7,6 +7,7 @@
 # ``stack.sh`` calls the entry points in this order:
 #
 # install_sahara
+# install_python_saharaclient
 # configure_sahara
 # start_sahara
 # stop_sahara
@@ -24,8 +25,13 @@
 SAHARA_REPO=${SAHARA_REPO:-${GIT_BASE}/openstack/sahara.git}
 SAHARA_BRANCH=${SAHARA_BRANCH:-master}
 
+SAHARA_PYTHONCLIENT_REPO=${SAHARA_PYTHONCLIENT_REPO:-${GIT_BASE}/openstack/python-saharaclient.git}
+SAHARA_PYTHONCLIENT_BRANCH=${SAHARA_PYTHONCLIENT_BRANCH:-master}
+
 # Set up default directories
 SAHARA_DIR=$DEST/sahara
+SAHARA_PYTHONCLIENT_DIR=$DEST/python-saharaclient
+
 SAHARA_CONF_DIR=${SAHARA_CONF_DIR:-/etc/sahara}
 SAHARA_CONF_FILE=${SAHARA_CONF_DIR}/sahara.conf
 
@@ -154,6 +160,12 @@
     setup_develop $SAHARA_DIR
 }
 
+# install_python_saharaclient() - Collect source and prepare
+function install_python_saharaclient {
+    git_clone $SAHARA_PYTHONCLIENT_REPO $SAHARA_PYTHONCLIENT_DIR $SAHARA_PYTHONCLIENT_BRANCH
+    setup_develop $SAHARA_PYTHONCLIENT_DIR
+}
+
 # start_sahara() - Start running processes, including screen
 function start_sahara {
     screen_it sahara "cd $SAHARA_DIR && $SAHARA_BIN_DIR/sahara-all --config-file $SAHARA_CONF_FILE"
diff --git a/lib/sahara-dashboard b/lib/sahara-dashboard
deleted file mode 100644
index a81df0f..0000000
--- a/lib/sahara-dashboard
+++ /dev/null
@@ -1,72 +0,0 @@
-# lib/sahara-dashboard
-
-# Dependencies:
-#
-# - ``functions`` file
-# - ``DEST``, ``DATA_DIR``, ``STACK_USER`` must be defined
-# - ``SERVICE_HOST``
-
-# ``stack.sh`` calls the entry points in this order:
-#
-# - install_sahara_dashboard
-# - configure_sahara_dashboard
-# - cleanup_sahara_dashboard
-
-# Save trace setting
-XTRACE=$(set +o | grep xtrace)
-set +o xtrace
-
-source $TOP_DIR/lib/horizon
-
-# Defaults
-# --------
-
-# Set up default repos
-SAHARA_DASHBOARD_REPO=${SAHARA_DASHBOARD_REPO:-${GIT_BASE}/openstack/sahara-dashboard.git}
-SAHARA_DASHBOARD_BRANCH=${SAHARA_DASHBOARD_BRANCH:-master}
-
-SAHARA_PYTHONCLIENT_REPO=${SAHARA_PYTHONCLIENT_REPO:-${GIT_BASE}/openstack/python-saharaclient.git}
-SAHARA_PYTHONCLIENT_BRANCH=${SAHARA_PYTHONCLIENT_BRANCH:-master}
-
-# Set up default directories
-SAHARA_DASHBOARD_DIR=$DEST/sahara-dashboard
-SAHARA_PYTHONCLIENT_DIR=$DEST/python-saharaclient
-
-# Functions
-# ---------
-
-function configure_sahara_dashboard {
-
-    echo -e "AUTO_ASSIGNMENT_ENABLED = False" >> $HORIZON_DIR/openstack_dashboard/local/local_settings.py
-    echo -e "HORIZON_CONFIG['dashboards'] += ('sahara',)" >> $HORIZON_DIR/openstack_dashboard/settings.py
-    echo -e "INSTALLED_APPS += ('saharadashboard',)" >> $HORIZON_DIR/openstack_dashboard/settings.py
-
-    if is_service_enabled neutron; then
-        echo -e "SAHARA_USE_NEUTRON = True" >> $HORIZON_DIR/openstack_dashboard/local/local_settings.py
-    fi
-}
-
-# install_sahara_dashboard() - Collect source and prepare
-function install_sahara_dashboard {
-    install_python_saharaclient
-    git_clone $SAHARA_DASHBOARD_REPO $SAHARA_DASHBOARD_DIR $SAHARA_DASHBOARD_BRANCH
-    setup_develop $SAHARA_DASHBOARD_DIR
-}
-
-function install_python_saharaclient {
-    git_clone $SAHARA_PYTHONCLIENT_REPO $SAHARA_PYTHONCLIENT_DIR $SAHARA_PYTHONCLIENT_BRANCH
-    setup_develop $SAHARA_PYTHONCLIENT_DIR
-}
-
-# Cleanup file settings.py from Sahara
-function cleanup_sahara_dashboard {
-    sed -i '/sahara/d' $HORIZON_DIR/openstack_dashboard/settings.py
-}
-
-# Restore xtrace
-$XTRACE
-
-# Local variables:
-# mode: shell-script
-# End:
-
diff --git a/lib/swift b/lib/swift
index 6b96348..b050b57 100644
--- a/lib/swift
+++ b/lib/swift
@@ -556,6 +556,7 @@
 
     local service_tenant=$(openstack project list | awk "/ $SERVICE_TENANT_NAME / { print \$2 }")
     local admin_role=$(openstack role list | awk "/ admin / { print \$2 }")
+    local another_role=$(openstack role list | awk "/ anotherrole / { print \$2 }")
 
     local swift_user=$(get_or_create_user "swift" \
         "$SERVICE_PASSWORD" $service_tenant)
@@ -582,7 +583,7 @@
     local swift_user_test3=$(get_or_create_user swiftusertest3 $swiftusertest3_password \
         "$swift_tenant_test1" "test3@example.com")
     die_if_not_set $LINENO swift_user_test3 "Failure creating swift_user_test3"
-    get_or_add_user_role $ANOTHER_ROLE $swift_user_test3 $swift_tenant_test1
+    get_or_add_user_role $another_role $swift_user_test3 $swift_tenant_test1
 
     local swift_tenant_test2=$(get_or_create_project swifttenanttest2)
     die_if_not_set $LINENO swift_tenant_test2 "Failure creating swift_tenant_test2"
diff --git a/stack.sh b/stack.sh
index f267490..7bfd072 100755
--- a/stack.sh
+++ b/stack.sh
@@ -37,6 +37,47 @@
 # Keep track of the devstack directory
 TOP_DIR=$(cd $(dirname "$0") && pwd)
 
+
+# Sanity Checks
+# -------------
+
+# Clean up last environment var cache
+if [[ -r $TOP_DIR/.stackenv ]]; then
+    rm $TOP_DIR/.stackenv
+fi
+
+# ``stack.sh`` keeps the list of ``apt`` and ``rpm`` dependencies and config
+# templates and other useful files in the ``files`` subdirectory
+FILES=$TOP_DIR/files
+if [ ! -d $FILES ]; then
+    die $LINENO "missing devstack/files"
+fi
+
+# ``stack.sh`` keeps function libraries here
+# Make sure ``$TOP_DIR/lib`` directory is present
+if [ ! -d $TOP_DIR/lib ]; then
+    die $LINENO "missing devstack/lib"
+fi
+
+# Check if run as root
+# OpenStack is designed to be run as a non-root user; Horizon will fail to run
+# as **root** since Apache will not serve content from **root** user).
+# ``stack.sh`` must not be run as **root**.  It aborts and suggests one course of
+# action to create a suitable user account.
+
+if [[ $EUID -eq 0 ]]; then
+    echo "You are running this script as root."
+    echo "Cut it out."
+    echo "Really."
+    echo "If you need an account to run DevStack, do this (as root, heh) to create a non-root account:"
+    echo "$TOP_DIR/tools/create-stack-user.sh"
+    exit 1
+fi
+
+
+# Prepare the environment
+# -----------------------
+
 # Import common functions
 source $TOP_DIR/functions
 
@@ -48,9 +89,18 @@
 # and ``DISTRO``
 GetDistro
 
+# 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|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"
+    fi
+fi
+
 
 # Global Settings
-# ===============
+# ---------------
 
 # Check for a ``localrc`` section embedded in ``local.conf`` and extract if
 # ``localrc`` does not already exist
@@ -71,6 +121,7 @@
     done
 fi
 
+
 # ``stack.sh`` is customizable by setting environment variables.  Override a
 # default setting via export::
 #
@@ -99,6 +150,15 @@
 fi
 source $TOP_DIR/stackrc
 
+# Check to see if we are already running DevStack
+# Note that this may fail if USE_SCREEN=False
+if type -p screen > /dev/null && screen -ls | egrep -q "[0-9]\.$SCREEN_NAME"; then
+    echo "You are already running a stack.sh session."
+    echo "To rejoin this session type 'screen -x stack'."
+    echo "To destroy this session, type './unstack.sh'."
+    exit 1
+fi
+
 
 # Local Settings
 # --------------
@@ -106,49 +166,11 @@
 # Make sure the proxy config is visible to sub-processes
 export_proxy_variables
 
-# Destination path for installation ``DEST``
-DEST=${DEST:-/opt/stack}
-
-
-# Sanity Check
-# ------------
-
-# Clean up last environment var cache
-if [[ -r $TOP_DIR/.stackenv ]]; then
-    rm $TOP_DIR/.stackenv
-fi
-
-# ``stack.sh`` keeps the list of ``apt`` and ``rpm`` dependencies and config
-# templates and other useful files in the ``files`` subdirectory
-FILES=$TOP_DIR/files
-if [ ! -d $FILES ]; then
-    die $LINENO "missing devstack/files"
-fi
-
-# ``stack.sh`` keeps function libraries here
-# Make sure ``$TOP_DIR/lib`` directory is present
-if [ ! -d $TOP_DIR/lib ]; then
-    die $LINENO "missing devstack/lib"
-fi
-
-# Import common services (database, message queue) configuration
-source $TOP_DIR/lib/database
-source $TOP_DIR/lib/rpc_backend
-
 # Remove services which were negated in ENABLED_SERVICES
 # using the "-" prefix (e.g., "-rabbit") instead of
 # calling disable_service().
 disable_negated_services
 
-# 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|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"
-    fi
-fi
-
 # Look for obsolete stuff
 if [[ ,${ENABLED_SERVICES}, =~ ,"swift", ]]; then
     echo "FATAL: 'swift' is not supported as a service name"
@@ -157,38 +179,11 @@
     exit 1
 fi
 
-# Make sure we only have one rpc backend enabled,
-# and the specified rpc backend is available on your platform.
-check_rpc_backend
-
-# Check to see if we are already running DevStack
-# Note that this may fail if USE_SCREEN=False
-if type -p screen >/dev/null && screen -ls | egrep -q "[0-9].$SCREEN_NAME"; then
-    echo "You are already running a stack.sh session."
-    echo "To rejoin this session type 'screen -x stack'."
-    echo "To destroy this session, type './unstack.sh'."
-    exit 1
-fi
-
 # Set up logging level
 VERBOSE=$(trueorfalse True $VERBOSE)
 
-# root Access
-# -----------
-
-# OpenStack is designed to be run as a non-root user; Horizon will fail to run
-# as **root** since Apache will not serve content from **root** user).
-# ``stack.sh`` must not be run as **root**.  It aborts and suggests one course of
-# action to create a suitable user account.
-
-if [[ $EUID -eq 0 ]]; then
-    echo "You are running this script as root."
-    echo "Cut it out."
-    echo "Really."
-    echo "If you need an account to run DevStack, do this (as root, heh) to create $STACK_USER:"
-    echo "$TOP_DIR/tools/create-stack-user.sh"
-    exit 1
-fi
+# Configure sudo
+# --------------
 
 # We're not **root**, make sure ``sudo`` is available
 is_package_installed sudo || install_package sudo
@@ -208,8 +203,9 @@
 sudo chown root:root $TEMPFILE
 sudo mv $TEMPFILE /etc/sudoers.d/50_stack_sh
 
-# Additional repos
-# ----------------
+
+# Configure Distro Repositories
+# -----------------------------
 
 # For debian/ubuntu make apt attempt to retry network ops on it's own
 if is_ubuntu; then
@@ -241,7 +237,7 @@
 if [[ is_fedora && ( $DISTRO == "rhel6" || $DISTRO == "rhel7" ) ]]; then
     # RHEL requires EPEL for many Open Stack dependencies
     if [[ $DISTRO == "rhel7" ]]; then
-        EPEL_RPM=${RHEL7_EPEL_RPM:-"http://dl.fedoraproject.org/pub/epel/beta/7/x86_64/epel-release-7-0.2.noarch.rpm"}
+        EPEL_RPM=${RHEL7_EPEL_RPM:-"http://dl.fedoraproject.org/pub/epel/beta/7/x86_64/epel-release-7-1.noarch.rpm"}
     elif [[ $DISTRO == "rhel6" ]]; then
         EPEL_RPM=${RHEL6_EPEL_RPM:-"http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm"}
     fi
@@ -261,8 +257,12 @@
     sudo yum-config-manager --enable ${OPTIONAL_REPO}
 fi
 
-# Filesystem setup
-# ----------------
+
+# Configure Target Directories
+# ----------------------------
+
+# Destination path for installation ``DEST``
+DEST=${DEST:-/opt/stack}
 
 # Create the destination directory and ensure it is writable by the user
 # and read/executable by everybody for daemons (e.g. apache run for horizon)
@@ -273,6 +273,12 @@
 # a basic test for $DEST path permissions (fatal on error unless skipped)
 check_path_perm_sanity ${DEST}
 
+# Destination path for service data
+DATA_DIR=${DATA_DIR:-${DEST}/data}
+sudo mkdir -p $DATA_DIR
+safe_chown -R $STACK_USER $DATA_DIR
+
+# Configure proper hostname
 # Certain services such as rabbitmq require that the local hostname resolves
 # correctly.  Make sure it exists in /etc/hosts so that is always true.
 LOCAL_HOSTNAME=`hostname -s`
@@ -280,11 +286,6 @@
     sudo sed -i "s/\(^127.0.0.1.*\)/\1 $LOCAL_HOSTNAME/" /etc/hosts
 fi
 
-# Destination path for service data
-DATA_DIR=${DATA_DIR:-${DEST}/data}
-sudo mkdir -p $DATA_DIR
-safe_chown -R $STACK_USER $DATA_DIR
-
 
 # Common Configuration
 # --------------------
@@ -323,9 +324,6 @@
 SYSLOG_HOST=${SYSLOG_HOST:-$HOST_IP}
 SYSLOG_PORT=${SYSLOG_PORT:-516}
 
-# for DSTAT logging
-DSTAT_FILE=${DSTAT_FILE:-"dstat.txt"}
-
 # Use color for logging output (only available if syslog is not used)
 LOG_COLOR=`trueorfalse True $LOG_COLOR`
 
@@ -336,6 +334,14 @@
 SSL_BUNDLE_FILE="$DATA_DIR/ca-bundle.pem"
 rm -f $SSL_BUNDLE_FILE
 
+# Import common services (database, message queue) configuration
+source $TOP_DIR/lib/database
+source $TOP_DIR/lib/rpc_backend
+
+# Make sure we only have one rpc backend enabled,
+# and the specified rpc backend is available on your platform.
+check_rpc_backend
+
 
 # Configure Projects
 # ==================
@@ -361,6 +367,7 @@
 source $TOP_DIR/lib/neutron
 source $TOP_DIR/lib/baremetal
 source $TOP_DIR/lib/ldap
+source $TOP_DIR/lib/dstat
 
 # Extras Source
 # --------------
@@ -418,7 +425,7 @@
             echo "Invalid chars in password.  Try again:"
         done
         if [ ! $pw ]; then
-            pw=$(cat /dev/urandom | tr -cd 'a-f0-9' | head -c 20)
+            pw=$(generate_hex_string 10)
         fi
         eval "$var=$pw"
         echo "$var=$pw" >> $localrc
@@ -940,12 +947,7 @@
 # -------
 
 # A better kind of sysstat, with the top process per time slice
-DSTAT_OPTS="-tcmndrylp --top-cpu-adv"
-if [[ -n ${SCREEN_LOGDIR} ]]; then
-    screen_it dstat "cd $TOP_DIR; dstat $DSTAT_OPTS | tee $SCREEN_LOGDIR/$DSTAT_FILE"
-else
-    screen_it dstat "dstat $DSTAT_OPTS"
-fi
+start_dstat
 
 # Start Services
 # ==============
@@ -1203,11 +1205,7 @@
 
 # Create a randomized default value for the keymgr's fixed_key
 if is_service_enabled nova; then
-    FIXED_KEY=""
-    for i in $(seq 1 64); do
-        FIXED_KEY+=$(echo "obase=16; $(($RANDOM % 16))" | bc);
-    done;
-    iniset $NOVA_CONF keymgr fixed_key "$FIXED_KEY"
+    iniset $NOVA_CONF keymgr fixed_key $(generate_hex_string 32)
 fi
 
 if is_service_enabled zeromq; then
@@ -1415,51 +1413,55 @@
     echo_summary "WARNING: $DEPRECATED_TEXT"
 fi
 
-# TODO(dtroyer): Remove Q_AGENT_EXTRA_AGENT_OPTS after stable/juno branch is cut
-if [[ -n "$Q_AGENT_EXTRA_AGENT_OPTS" ]]; then
-    echo ""
-    echo_summary "WARNING: Q_AGENT_EXTRA_AGENT_OPTS is used"
-    echo "You are using Q_AGENT_EXTRA_AGENT_OPTS to pass configuration into $NEUTRON_CONF."
-    echo "Please convert that configuration in localrc to a $NEUTRON_CONF section in local.conf:"
-    echo "Q_AGENT_EXTRA_AGENT_OPTS will be removed early in the 'K' development cycle"
-    echo "
+if is_service_enabled neutron; then
+    # TODO(dtroyer): Remove Q_AGENT_EXTRA_AGENT_OPTS after stable/juno branch is cut
+    if [[ -n "$Q_AGENT_EXTRA_AGENT_OPTS" ]]; then
+        echo ""
+        echo_summary "WARNING: Q_AGENT_EXTRA_AGENT_OPTS is used"
+        echo "You are using Q_AGENT_EXTRA_AGENT_OPTS to pass configuration into $NEUTRON_CONF."
+        echo "Please convert that configuration in localrc to a $NEUTRON_CONF section in local.conf:"
+        echo "Q_AGENT_EXTRA_AGENT_OPTS will be removed early in the 'K' development cycle"
+        echo "
 [[post-config|/\$Q_PLUGIN_CONF_FILE]]
 [DEFAULT]
 "
-    for I in "${Q_AGENT_EXTRA_AGENT_OPTS[@]}"; do
-        # Replace the first '=' with ' ' for iniset syntax
-        echo ${I}
-    done
-fi
+        for I in "${Q_AGENT_EXTRA_AGENT_OPTS[@]}"; do
+            # Replace the first '=' with ' ' for iniset syntax
+            echo ${I}
+        done
+    fi
 
-# TODO(dtroyer): Remove Q_AGENT_EXTRA_SRV_OPTS after stable/juno branch is cut
-if [[ -n "$Q_AGENT_EXTRA_SRV_OPTS" ]]; then
-    echo ""
-    echo_summary "WARNING: Q_AGENT_EXTRA_SRV_OPTS is used"
-    echo "You are using Q_AGENT_EXTRA_SRV_OPTS to pass configuration into $NEUTRON_CONF."
-    echo "Please convert that configuration in localrc to a $NEUTRON_CONF section in local.conf:"
-    echo "Q_AGENT_EXTRA_AGENT_OPTS will be removed early in the 'K' development cycle"
-    echo "
+    # TODO(dtroyer): Remove Q_AGENT_EXTRA_SRV_OPTS after stable/juno branch is cut
+    if [[ -n "$Q_AGENT_EXTRA_SRV_OPTS" ]]; then
+        echo ""
+        echo_summary "WARNING: Q_AGENT_EXTRA_SRV_OPTS is used"
+        echo "You are using Q_AGENT_EXTRA_SRV_OPTS to pass configuration into $NEUTRON_CONF."
+        echo "Please convert that configuration in localrc to a $NEUTRON_CONF section in local.conf:"
+        echo "Q_AGENT_EXTRA_AGENT_OPTS will be removed early in the 'K' development cycle"
+        echo "
 [[post-config|/\$Q_PLUGIN_CONF_FILE]]
 [DEFAULT]
 "
-    for I in "${Q_AGENT_EXTRA_SRV_OPTS[@]}"; do
-        # Replace the first '=' with ' ' for iniset syntax
-        echo ${I}
-    done
+        for I in "${Q_AGENT_EXTRA_SRV_OPTS[@]}"; do
+            # Replace the first '=' with ' ' for iniset syntax
+            echo ${I}
+        done
+    fi
 fi
 
-# TODO(dtroyer): Remove CINDER_MULTI_LVM_BACKEND after stable/juno branch is cut
-if [[ "$CINDER_MULTI_LVM_BACKEND" = "True" ]]; then
-    echo ""
-    echo_summary "WARNING: CINDER_MULTI_LVM_BACKEND is used"
-    echo "You are using CINDER_MULTI_LVM_BACKEND to configure Cinder's multiple LVM backends"
-    echo "Please convert that configuration in local.conf to use CINDER_ENABLED_BACKENDS."
-    echo "CINDER_ENABLED_BACKENDS will be removed early in the 'K' development cycle"
-    echo "
+if is_service_enabled cinder; then
+    # TODO(dtroyer): Remove CINDER_MULTI_LVM_BACKEND after stable/juno branch is cut
+    if [[ "$CINDER_MULTI_LVM_BACKEND" = "True" ]]; then
+        echo ""
+        echo_summary "WARNING: CINDER_MULTI_LVM_BACKEND is used"
+        echo "You are using CINDER_MULTI_LVM_BACKEND to configure Cinder's multiple LVM backends"
+        echo "Please convert that configuration in local.conf to use CINDER_ENABLED_BACKENDS."
+        echo "CINDER_ENABLED_BACKENDS will be removed early in the 'K' development cycle"
+        echo "
 [[local|localrc]]
 CINDER_ENABLED_BACKENDS=lvm:lvmdriver-1,lvm:lvmdriver-2
 "
+    fi
 fi
 
 # Indicate how long this took to run (bash maintained variable ``SECONDS``)
diff --git a/stackrc b/stackrc
index 34bc16c..e071132 100644
--- a/stackrc
+++ b/stackrc
@@ -222,6 +222,10 @@
 CLIFF_REPO=${CLIFF_REPO:-${GIT_BASE}/openstack/cliff.git}
 CLIFF_BRANCH=${CLIFF_BRANCH:-master}
 
+# oslo.concurrency
+OSLOCON_REPO=${OSLOCON_REPO:-${GIT_BASE}/openstack/oslo.concurrency.git}
+OSLOCON_BRANCH=${OSLOCON_BRANCH:-master}
+
 # oslo.config
 OSLOCFG_REPO=${OSLOCFG_REPO:-${GIT_BASE}/openstack/oslo.config.git}
 OSLOCFG_BRANCH=${OSLOCFG_BRANCH:-master}
@@ -234,14 +238,30 @@
 OSLOI18N_REPO=${OSLOI18N_REPO:-${GIT_BASE}/openstack/oslo.i18n.git}
 OSLOI18N_BRANCH=${OSLOI18N_BRANCH:-master}
 
+# oslo.log
+OSLOLOG_REPO=${OSLOLOG_REPO:-${GIT_BASE}/openstack/oslo.log.git}
+OSLOLOG_BRANCH=${OSLOLOG_BRANCH:-master}
+
 # oslo.messaging
 OSLOMSG_REPO=${OSLOMSG_REPO:-${GIT_BASE}/openstack/oslo.messaging.git}
 OSLOMSG_BRANCH=${OSLOMSG_BRANCH:-master}
 
+# oslo.middleware
+OSLOMID_REPO=${OSLOMID_REPO:-${GIT_BASE}/openstack/oslo.middleware.git}
+OSLOMID_BRANCH=${OSLOMID_BRANCH:-master}
+
 # oslo.rootwrap
 OSLORWRAP_REPO=${OSLORWRAP_REPO:-${GIT_BASE}/openstack/oslo.rootwrap.git}
 OSLORWRAP_BRANCH=${OSLORWRAP_BRANCH:-master}
 
+# oslo.serialization
+OSLOSERIALIZATION_REPO=${OSLOSERIALIZATION_REPO:-${GIT_BASE}/openstack/oslo.serialization.git}
+OSLOSERIALIZATION_BRANCH=${OSLOSERIALIZATION_BRANCH:-master}
+
+# oslo.utils
+OSLOUTILS_REPO=${OSLOUTILS_REPO:-${GIT_BASE}/openstack/oslo.utils.git}
+OSLOUTILS_BRANCH=${OSLOUTILS_BRANCH:-master}
+
 # oslo.vmware
 OSLOVMWARE_REPO=${OSLOVMWARE_REPO:-${GIT_BASE}/openstack/oslo.vmware.git}
 OSLOVMWARE_BRANCH=${OSLOVMWARE_BRANCH:-master}
diff --git a/tools/jenkins/README.md b/tools/jenkins/README.md
deleted file mode 100644
index 3586da9..0000000
--- a/tools/jenkins/README.md
+++ /dev/null
@@ -1,38 +0,0 @@
-Getting Started With Jenkins and Devstack
-=========================================
-This little corner of devstack is to show how to get an OpenStack jenkins
-environment up and running quickly, using the rcb configuration methodology.
-
-
-To create a jenkins server
---------------------------
-
-    cd tools/jenkins/jenkins_home
-    ./build_jenkins.sh
-
-This will create a jenkins environment configured with sample test scripts that run against xen and kvm.
-
-Configuring XS
---------------
-In order to make the tests for XS work, you must install xs 5.6 on a separate machine,
-and install the the jenkins public key on that server.  You then need to create the
-/var/lib/jenkins/xenrc on your jenkins server like so:
-
-    MYSQL_PASSWORD=secrete
-    SERVICE_TOKEN=secrete
-    ADMIN_PASSWORD=secrete
-    RABBIT_PASSWORD=secrete
-    # This is the password for your guest (for both stack and root users)
-    GUEST_PASSWORD=secrete
-    # Do not download the usual images yet!
-    IMAGE_URLS=""
-    FLOATING_RANGE=192.168.1.224/28
-    VIRT_DRIVER=xenserver
-    # Explicitly set multi-host
-    MULTI_HOST=1
-    # Give extra time for boot
-    ACTIVE_TIMEOUT=45
-    #  IMPORTANT: This is the ip of your xenserver
-    XEN_IP=10.5.5.1
-    # IMPORTANT: The following must be set to your dom0 root password!
-    XENAPI_PASSWORD='MY_XEN_ROOT_PW'
diff --git a/tools/jenkins/adapters/euca.sh b/tools/jenkins/adapters/euca.sh
deleted file mode 100755
index a7e635c..0000000
--- a/tools/jenkins/adapters/euca.sh
+++ /dev/null
@@ -1,9 +0,0 @@
-#!/bin/bash
-# Echo commands, exit on error
-set -o xtrace
-set -o errexit
-
-TOP_DIR=$(cd ../../.. && pwd)
-HEAD_IP=`cat $TOP_DIR/addresses | grep HEAD | cut -d "=" -f2`
-die_if_not_set $LINENO HEAD_IP "Failure retrieving HEAD_IP"
-ssh stack@$HEAD_IP 'cd devstack && source openrc && cd exercises &&  ./euca.sh'
diff --git a/tools/jenkins/adapters/floating_ips.sh b/tools/jenkins/adapters/floating_ips.sh
deleted file mode 100755
index 8da1eeb..0000000
--- a/tools/jenkins/adapters/floating_ips.sh
+++ /dev/null
@@ -1,9 +0,0 @@
-#!/bin/bash
-# Echo commands, exit on error
-set -o xtrace
-set -o errexit
-
-TOP_DIR=$(cd ../../.. && pwd)
-HEAD_IP=`cat $TOP_DIR/addresses | grep HEAD | cut -d "=" -f2`
-die_if_not_set $LINENO HEAD_IP "Failure retrieving HEAD_IP"
-ssh stack@$HEAD_IP 'cd devstack && source openrc && cd exercises &&  ./floating_ips.sh'
diff --git a/tools/jenkins/adapters/swift.sh b/tools/jenkins/adapters/swift.sh
deleted file mode 100755
index c1362ee..0000000
--- a/tools/jenkins/adapters/swift.sh
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/bin/bash
-# Echo commands, exit on error
-set -o xtrace
-set -o errexit
-
-TOP_DIR=$(cd ../../.. && pwd)
-HEAD_IP=`cat $TOP_DIR/addresses | grep HEAD | cut -d "=" -f2`
-ssh stack@$HEAD_IP 'cd devstack && source openrc && cd exercises &&  ./swift.sh'
diff --git a/tools/jenkins/adapters/volumes.sh b/tools/jenkins/adapters/volumes.sh
deleted file mode 100755
index 0a0b6c0..0000000
--- a/tools/jenkins/adapters/volumes.sh
+++ /dev/null
@@ -1,9 +0,0 @@
-#!/bin/bash
-# Echo commands, exit on error
-set -o xtrace
-set -o errexit
-
-TOP_DIR=$(cd ../../.. && pwd)
-HEAD_IP=`cat $TOP_DIR/addresses | grep HEAD | cut -d "=" -f2`
-die_if_not_set $LINENO HEAD_IP "Failure retrieving HEAD_IP"
-ssh stack@$HEAD_IP 'cd devstack && source openrc && cd exercises &&  ./volumes.sh'
diff --git a/tools/jenkins/build_configuration.sh b/tools/jenkins/build_configuration.sh
deleted file mode 100755
index 64ee159..0000000
--- a/tools/jenkins/build_configuration.sh
+++ /dev/null
@@ -1,21 +0,0 @@
-#!/bin/bash
-
-EXECUTOR_NUMBER=$1
-CONFIGURATION=$2
-ADAPTER=$3
-RC=$4
-
-function usage {
-    echo "Usage: $0 -  Build a configuration"
-    echo ""
-    echo "$0 [EXECUTOR_NUMBER] [CONFIGURATION] [ADAPTER] [RC (optional)]"
-    exit 1
-}
-
-# Validate inputs
-if [[ "$EXECUTOR_NUMBER" = "" || "$CONFIGURATION" = ""  || "$ADAPTER" = "" ]]; then
-    usage
-fi
-
-# Execute configuration script
-cd configurations && ./$CONFIGURATION.sh $EXECUTOR_NUMBER $CONFIGURATION $ADAPTER "$RC"
diff --git a/tools/jenkins/configurations/kvm.sh b/tools/jenkins/configurations/kvm.sh
deleted file mode 100755
index 6927fd7..0000000
--- a/tools/jenkins/configurations/kvm.sh
+++ /dev/null
@@ -1,64 +0,0 @@
-#!/bin/bash
-
-# exit on error to stop unexpected errors
-set -o errexit
-set -o xtrace
-
-EXECUTOR_NUMBER=$1
-CONFIGURATION=$2
-ADAPTER=$3
-RC=$4
-
-function usage {
-    echo "Usage: $0 - Build a test configuration"
-    echo ""
-    echo "$0 [EXECUTOR_NUMBER] [CONFIGURATION] [ADAPTER] [RC (optional)]"
-    exit 1
-}
-
-# Validate inputs
-if [[ "$EXECUTOR_NUMBER" = "" || "$CONFIGURATION" = ""  || "$ADAPTER" = "" ]]; then
-    usage
-fi
-
-# This directory
-CUR_DIR=$(cd $(dirname "$0") && pwd)
-
-# devstack directory
-cd ../../..
-TOP_DIR=$(pwd)
-
-# Deps
-apt-get install -y --force-yes libvirt-bin || true
-
-# Name test instance based on executor
-BASE_NAME=executor-`printf "%02d" $EXECUTOR_NUMBER`
-GUEST_NAME=$BASE_NAME.$ADAPTER
-virsh list | grep $BASE_NAME | cut -d " " -f1 | xargs -n 1 virsh destroy || true
-virsh net-list | grep $BASE_NAME | cut -d " " -f1 | xargs -n 1 virsh net-destroy || true
-
-# Configure localrc
-cat <<EOF >localrc
-RECLONE=yes
-GUEST_NETWORK=$EXECUTOR_NUMBER
-GUEST_NAME=$GUEST_NAME
-FLOATING_RANGE=192.168.$EXECUTOR_NUMBER.128/27
-GUEST_CORES=1
-GUEST_RAM=12574720
-MYSQL_PASSWORD=chicken
-RABBIT_PASSWORD=chicken
-SERVICE_TOKEN=chicken
-SERVICE_PASSWORD=chicken
-ADMIN_PASSWORD=chicken
-USERNAME=admin
-TENANT=admin
-NET_NAME=$BASE_NAME
-ACTIVE_TIMEOUT=45
-BOOT_TIMEOUT=45
-$RC
-EOF
-cd tools
-sudo ./build_uec.sh
-
-# Make the address of the instances available to test runners
-echo HEAD=`cat /var/lib/libvirt/dnsmasq/$BASE_NAME.leases | cut -d " " -f3` > $TOP_DIR/addresses
diff --git a/tools/jenkins/configurations/xs.sh b/tools/jenkins/configurations/xs.sh
deleted file mode 100755
index 7b671e9..0000000
--- a/tools/jenkins/configurations/xs.sh
+++ /dev/null
@@ -1,53 +0,0 @@
-#!/bin/bash
-set -o errexit
-set -o xtrace
-
-
-EXECUTOR_NUMBER=$1
-CONFIGURATION=$2
-ADAPTER=$3
-RC=$4
-
-function usage {
-    echo "Usage: $0 - Build a test configuration"
-    echo ""
-    echo "$0 [EXECUTOR_NUMBER] [CONFIGURATION] [ADAPTER] [RC (optional)]"
-    exit 1
-}
-
-# Validate inputs
-if [[ "$EXECUTOR_NUMBER" = "" || "$CONFIGURATION" = ""  || "$ADAPTER" = "" ]]; then
-    usage
-fi
-
-# Configuration of xenrc
-XENRC=/var/lib/jenkins/xenrc
-if [ ! -e $XENRC ]; then
-    echo "/var/lib/jenkins/xenrc is not present! See README.md"
-    exit 1
-fi
-
-# Move to top of devstack
-cd ../../..
-
-# Use xenrc as the start of our localrc
-cp $XENRC localrc
-
-# Set the PUB_IP
-PUB_IP=192.168.1.1$EXECUTOR_NUMBER
-echo "PUB_IP=$PUB_IP" >> localrc
-
-# Overrides
-echo "$RC" >> localrc
-
-# Source localrc
-. localrc
-
-# Make host ip available to tester
-echo "HEAD=$PUB_IP" > addresses
-
-# Build configuration
-REMOTE_DEVSTACK=/root/devstack
-ssh root@$XEN_IP "rm -rf $REMOTE_DEVSTACK"
-scp -pr . root@$XEN_IP:$REMOTE_DEVSTACK
-ssh root@$XEN_IP "cd $REMOTE_DEVSTACK/tools/xen && ./build_domU.sh"
diff --git a/tools/jenkins/jenkins_home/.gitignore b/tools/jenkins/jenkins_home/.gitignore
deleted file mode 100644
index d831d01..0000000
--- a/tools/jenkins/jenkins_home/.gitignore
+++ /dev/null
@@ -1,3 +0,0 @@
-builds
-workspace
-*.sw*
diff --git a/tools/jenkins/jenkins_home/build_jenkins.sh b/tools/jenkins/jenkins_home/build_jenkins.sh
deleted file mode 100755
index a556db0..0000000
--- a/tools/jenkins/jenkins_home/build_jenkins.sh
+++ /dev/null
@@ -1,108 +0,0 @@
-#!/bin/bash
-
-# Echo commands, exit on error
-set -o xtrace
-set -o errexit
-
-# Make sure only root can run our script
-if [[ $EUID -ne 0 ]]; then
-    echo "This script must be run as root"
-    exit 1
-fi
-
-# This directory
-CUR_DIR=$(cd $(dirname "$0") && pwd)
-
-# Configure trunk jenkins!
-echo "deb http://pkg.jenkins-ci.org/debian binary/" > /etc/apt/sources.list.d/jenkins.list
-wget -q -O - http://pkg.jenkins-ci.org/debian/jenkins-ci.org.key | sudo apt-key add -
-apt-get update
-
-
-# Clean out old jenkins - useful if you are having issues upgrading
-CLEAN_JENKINS=${CLEAN_JENKINS:-no}
-if [ "$CLEAN_JENKINS" = "yes" ]; then
-    apt-get remove jenkins jenkins-common
-fi
-
-# Install software
-DEPS="jenkins cloud-utils"
-apt-get install -y --force-yes $DEPS
-
-# Install jenkins
-if [ ! -e /var/lib/jenkins ]; then
-    echo "Jenkins installation failed"
-    exit 1
-fi
-
-# Make sure user has configured a jenkins ssh pubkey
-if [ ! -e /var/lib/jenkins/.ssh/id_rsa.pub ]; then
-    echo "Public key for jenkins is missing.  This is used to ssh into your instances."
-    echo "Please run "su -c ssh-keygen jenkins" before proceeding"
-    exit 1
-fi
-
-# Setup sudo
-JENKINS_SUDO=/etc/sudoers.d/jenkins
-cat > $JENKINS_SUDO <<EOF
-jenkins ALL = NOPASSWD: ALL
-EOF
-chmod 440 $JENKINS_SUDO
-
-# Setup .gitconfig
-JENKINS_GITCONF=/var/lib/jenkins/hudson.plugins.git.GitSCM.xml
-cat > $JENKINS_GITCONF <<EOF
-<?xml version='1.0' encoding='UTF-8'?>
-<hudson.plugins.git.GitSCM_-DescriptorImpl>
-  <generation>4</generation>
-  <globalConfigName>Jenkins</globalConfigName>
-  <globalConfigEmail>jenkins@rcb.me</globalConfigEmail>
-</hudson.plugins.git.GitSCM_-DescriptorImpl>
-EOF
-
-# Add build numbers
-JOBS=`ls jobs`
-for job in ${JOBS// / }; do
-    if [ ! -e jobs/$job/nextBuildNumber ]; then
-        echo 1 > jobs/$job/nextBuildNumber
-    fi
-done
-
-# Set ownership to jenkins
-chown -R jenkins $CUR_DIR
-
-# Make sure this directory is accessible to jenkins
-if ! su -c "ls $CUR_DIR" jenkins; then
-    echo "Your devstack directory is not accessible by jenkins."
-    echo "There is a decent chance you are trying to run this from a directory in /root."
-    echo "If so, try moving devstack elsewhere (eg. /opt/devstack)."
-    exit 1
-fi
-
-# Move aside old jobs, if present
-if [ ! -h /var/lib/jenkins/jobs ]; then
-    echo "Installing jobs symlink"
-    if [ -d /var/lib/jenkins/jobs ]; then
-        mv /var/lib/jenkins/jobs /var/lib/jenkins/jobs.old
-    fi
-fi
-
-# Set up jobs symlink
-rm -f /var/lib/jenkins/jobs
-ln -s $CUR_DIR/jobs /var/lib/jenkins/jobs
-
-# List of plugins
-PLUGINS=http://hudson-ci.org/downloads/plugins/build-timeout/1.6/build-timeout.hpi,http://mirrors.jenkins-ci.org/plugins/git/1.1.12/git.hpi,http://hudson-ci.org/downloads/plugins/global-build-stats/1.2/global-build-stats.hpi,http://hudson-ci.org/downloads/plugins/greenballs/1.10/greenballs.hpi,http://download.hudson-labs.org/plugins/console-column-plugin/1.0/console-column-plugin.hpi
-
-# Configure plugins
-for plugin in ${PLUGINS//,/ }; do
-    name=`basename $plugin`
-    dest=/var/lib/jenkins/plugins/$name
-    if [ ! -e $dest ]; then
-        curl -L $plugin -o $dest
-    fi
-done
-
-# Restart jenkins
-/etc/init.d/jenkins stop || true
-/etc/init.d/jenkins start
diff --git a/tools/jenkins/jenkins_home/clean.sh b/tools/jenkins/jenkins_home/clean.sh
deleted file mode 100755
index eb03022..0000000
--- a/tools/jenkins/jenkins_home/clean.sh
+++ /dev/null
@@ -1,21 +0,0 @@
-#!/bin/bash
-# This script is not yet for general consumption.
-
-set -o errexit
-
-if [ ! "$FORCE" = "yes" ]; then
-    echo "FORCE not set to 'yes'.  Make sure this is something you really want to do.  Exiting."
-    exit 1
-fi
-
-virsh list | cut -d " " -f1 | grep -v "-" | egrep -e "[0-9]" | xargs -n 1 virsh destroy || true
-virsh net-list | grep active | cut -d " " -f1 | xargs -n 1 virsh net-destroy || true
-killall dnsmasq || true
-if [ "$CLEAN" = "yes" ]; then
-    rm -rf jobs
-fi
-rm /var/lib/jenkins/jobs
-git checkout -f
-git fetch
-git merge origin/jenkins
-./build_jenkins.sh
diff --git a/tools/jenkins/jenkins_home/jobs/diablo-kvm_ha/config.xml b/tools/jenkins/jenkins_home/jobs/diablo-kvm_ha/config.xml
deleted file mode 100644
index 94c51f5..0000000
--- a/tools/jenkins/jenkins_home/jobs/diablo-kvm_ha/config.xml
+++ /dev/null
@@ -1,82 +0,0 @@
-<?xml version='1.0' encoding='UTF-8'?>
-<matrix-project>
-  <actions/>
-  <description></description>
-  <keepDependencies>false</keepDependencies>
-  <properties>
-    <hudson.model.ParametersDefinitionProperty>
-      <parameterDefinitions>
-        <hudson.model.StringParameterDefinition>
-          <name>RC</name>
-          <description></description>
-          <defaultValue></defaultValue>
-        </hudson.model.StringParameterDefinition>
-      </parameterDefinitions>
-    </hudson.model.ParametersDefinitionProperty>
-  </properties>
-  <scm class="hudson.plugins.git.GitSCM">
-    <configVersion>2</configVersion>
-    <userRemoteConfigs>
-      <hudson.plugins.git.UserRemoteConfig>
-        <name>origin</name>
-        <refspec>+refs/heads/*:refs/remotes/origin/*</refspec>
-        <url>git://github.com/cloudbuilders/devstack.git</url>
-      </hudson.plugins.git.UserRemoteConfig>
-    </userRemoteConfigs>
-    <branches>
-      <hudson.plugins.git.BranchSpec>
-        <name>master</name>
-      </hudson.plugins.git.BranchSpec>
-    </branches>
-    <recursiveSubmodules>false</recursiveSubmodules>
-    <doGenerateSubmoduleConfigurations>false</doGenerateSubmoduleConfigurations>
-    <authorOrCommitter>false</authorOrCommitter>
-    <clean>false</clean>
-    <wipeOutWorkspace>false</wipeOutWorkspace>
-    <pruneBranches>false</pruneBranches>
-    <remotePoll>false</remotePoll>
-    <buildChooser class="hudson.plugins.git.util.DefaultBuildChooser"/>
-    <gitTool>Default</gitTool>
-    <submoduleCfg class="list"/>
-    <relativeTargetDir></relativeTargetDir>
-    <excludedRegions></excludedRegions>
-    <excludedUsers></excludedUsers>
-    <gitConfigName></gitConfigName>
-    <gitConfigEmail></gitConfigEmail>
-    <skipTag>false</skipTag>
-    <scmName></scmName>
-  </scm>
-  <canRoam>true</canRoam>
-  <disabled>false</disabled>
-  <blockBuildWhenDownstreamBuilding>false</blockBuildWhenDownstreamBuilding>
-  <blockBuildWhenUpstreamBuilding>false</blockBuildWhenUpstreamBuilding>
-  <triggers class="vector"/>
-  <concurrentBuild>false</concurrentBuild>
-  <axes>
-    <hudson.matrix.TextAxis>
-      <name>ADAPTER</name>
-      <values>
-        <string>euca</string>
-        <string>floating_ips</string>
-      </values>
-    </hudson.matrix.TextAxis>
-  </axes>
-  <builders>
-    <hudson.tasks.Shell>
-      <command>sed -i &apos;s/) 2&gt;&amp;1 | tee &quot;${LOGFILE}&quot;/)/&apos; stack.sh</command>
-    </hudson.tasks.Shell>
-    <hudson.tasks.Shell>
-      <command>set -o errexit
-cd tools/jenkins
-sudo ./build_configuration.sh $EXECUTOR_NUMBER kvm $ADAPTER &quot;$RC&quot;</command>
-    </hudson.tasks.Shell>
-    <hudson.tasks.Shell>
-      <command>set -o errexit
-cd tools/jenkins
-./run_test.sh $EXECUTOR_NUMBER $ADAPTER $RC &quot;$RC&quot;</command>
-    </hudson.tasks.Shell>
-  </builders>
-  <publishers/>
-  <buildWrappers/>
-  <runSequentially>false</runSequentially>
-</matrix-project>
diff --git a/tools/jenkins/jenkins_home/jobs/diablo-kvm_ha/configurations/axis-ADAPTER/euca/config.xml b/tools/jenkins/jenkins_home/jobs/diablo-kvm_ha/configurations/axis-ADAPTER/euca/config.xml
deleted file mode 100644
index 0be70a5..0000000
--- a/tools/jenkins/jenkins_home/jobs/diablo-kvm_ha/configurations/axis-ADAPTER/euca/config.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-<?xml version='1.0' encoding='UTF-8'?>
-<matrix-config>
-  <keepDependencies>false</keepDependencies>
-  <properties/>
-  <scm class="hudson.scm.NullSCM"/>
-  <canRoam>false</canRoam>
-  <disabled>false</disabled>
-  <blockBuildWhenDownstreamBuilding>false</blockBuildWhenDownstreamBuilding>
-  <blockBuildWhenUpstreamBuilding>false</blockBuildWhenUpstreamBuilding>
-  <triggers class="vector"/>
-  <concurrentBuild>false</concurrentBuild>
-  <builders/>
-  <publishers/>
-  <buildWrappers/>
-</matrix-config>
\ No newline at end of file
diff --git a/tools/jenkins/jenkins_home/jobs/diablo-kvm_ha/configurations/axis-ADAPTER/floatingips/config.xml b/tools/jenkins/jenkins_home/jobs/diablo-kvm_ha/configurations/axis-ADAPTER/floatingips/config.xml
deleted file mode 100644
index 0be70a5..0000000
--- a/tools/jenkins/jenkins_home/jobs/diablo-kvm_ha/configurations/axis-ADAPTER/floatingips/config.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-<?xml version='1.0' encoding='UTF-8'?>
-<matrix-config>
-  <keepDependencies>false</keepDependencies>
-  <properties/>
-  <scm class="hudson.scm.NullSCM"/>
-  <canRoam>false</canRoam>
-  <disabled>false</disabled>
-  <blockBuildWhenDownstreamBuilding>false</blockBuildWhenDownstreamBuilding>
-  <blockBuildWhenUpstreamBuilding>false</blockBuildWhenUpstreamBuilding>
-  <triggers class="vector"/>
-  <concurrentBuild>false</concurrentBuild>
-  <builders/>
-  <publishers/>
-  <buildWrappers/>
-</matrix-config>
\ No newline at end of file
diff --git a/tools/jenkins/jenkins_home/jobs/diablo-xs_ha/config.xml b/tools/jenkins/jenkins_home/jobs/diablo-xs_ha/config.xml
deleted file mode 100644
index 49a57f0..0000000
--- a/tools/jenkins/jenkins_home/jobs/diablo-xs_ha/config.xml
+++ /dev/null
@@ -1,88 +0,0 @@
-<?xml version='1.0' encoding='UTF-8'?>
-<matrix-project>
-  <actions/>
-  <description>In order for this to work, you must create a /var/lib/jenkins/xenrc file as described in README.md</description>
-  <keepDependencies>false</keepDependencies>
-  <properties>
-    <hudson.model.ParametersDefinitionProperty>
-      <parameterDefinitions>
-        <hudson.model.StringParameterDefinition>
-          <name>RC</name>
-          <description></description>
-          <defaultValue></defaultValue>
-        </hudson.model.StringParameterDefinition>
-      </parameterDefinitions>
-    </hudson.model.ParametersDefinitionProperty>
-  </properties>
-  <scm class="hudson.plugins.git.GitSCM">
-    <configVersion>2</configVersion>
-    <userRemoteConfigs>
-      <hudson.plugins.git.UserRemoteConfig>
-        <name>origin</name>
-        <refspec>+refs/heads/*:refs/remotes/origin/*</refspec>
-        <url>git://github.com/cloudbuilders/devstack.git</url>
-      </hudson.plugins.git.UserRemoteConfig>
-    </userRemoteConfigs>
-    <branches>
-      <hudson.plugins.git.BranchSpec>
-        <name>master</name>
-      </hudson.plugins.git.BranchSpec>
-    </branches>
-    <recursiveSubmodules>false</recursiveSubmodules>
-    <doGenerateSubmoduleConfigurations>false</doGenerateSubmoduleConfigurations>
-    <authorOrCommitter>false</authorOrCommitter>
-    <clean>false</clean>
-    <wipeOutWorkspace>false</wipeOutWorkspace>
-    <pruneBranches>false</pruneBranches>
-    <remotePoll>false</remotePoll>
-    <buildChooser class="hudson.plugins.git.util.DefaultBuildChooser"/>
-    <gitTool>Default</gitTool>
-    <submoduleCfg class="list"/>
-    <relativeTargetDir></relativeTargetDir>
-    <excludedRegions></excludedRegions>
-    <excludedUsers></excludedUsers>
-    <gitConfigName></gitConfigName>
-    <gitConfigEmail></gitConfigEmail>
-    <skipTag>false</skipTag>
-    <scmName></scmName>
-  </scm>
-  <canRoam>true</canRoam>
-  <disabled>false</disabled>
-  <blockBuildWhenDownstreamBuilding>false</blockBuildWhenDownstreamBuilding>
-  <blockBuildWhenUpstreamBuilding>false</blockBuildWhenUpstreamBuilding>
-  <triggers class="vector"/>
-  <concurrentBuild>false</concurrentBuild>
-  <axes>
-    <hudson.matrix.TextAxis>
-      <name>ADAPTER</name>
-      <values>
-        <string>euca</string>
-        <string>floating_ips</string>
-      </values>
-    </hudson.matrix.TextAxis>
-  </axes>
-  <builders>
-    <hudson.tasks.Shell>
-      <command>sed -i &apos;s/) 2&gt;&amp;1 | tee &quot;${LOGFILE}&quot;/)/&apos; stack.sh</command>
-    </hudson.tasks.Shell>
-    <hudson.tasks.Shell>
-      <command>set -o errexit
-cd tools/jenkins
-sudo ./build_configuration.sh $EXECUTOR_NUMBER xs $ADAPTER &quot;$RC&quot;</command>
-    </hudson.tasks.Shell>
-    <hudson.tasks.Shell>
-      <command>#!/bin/bash
-set -o errexit
-set -o xtrace
-
-. localrc
-
-# Unlike kvm, ssh to the xen host to run tests, in case the test instance is launch with a host only network
-ssh root@$XEN_IP &quot;cd devstack &amp;&amp; . localrc &amp;&amp; cd tools/jenkins &amp;&amp; ./run_test.sh $EXECUTOR_NUMBER $ADAPTER &apos;$RC&apos;&quot;
-</command>
-    </hudson.tasks.Shell>
-  </builders>
-  <publishers/>
-  <buildWrappers/>
-  <runSequentially>true</runSequentially>
-</matrix-project>
diff --git a/tools/jenkins/jenkins_home/print_summary.py b/tools/jenkins/jenkins_home/print_summary.py
deleted file mode 100755
index 8be500b..0000000
--- a/tools/jenkins/jenkins_home/print_summary.py
+++ /dev/null
@@ -1,58 +0,0 @@
-#!/usr/bin/python
-
-#    Licensed under the Apache License, Version 2.0 (the "License"); you may
-#    not use this file except in compliance with the License. You may obtain
-#    a copy of the License at
-#
-#         http://www.apache.org/licenses/LICENSE-2.0
-#
-#    Unless required by applicable law or agreed to in writing, software
-#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-#    License for the specific language governing permissions and limitations
-#    under the License.
-
-import json
-import sys
-import urllib
-
-
-def print_usage():
-    print("Usage: %s [jenkins_url (eg. http://50.56.12.202:8080/)]"
-          % sys.argv[0])
-    sys.exit()
-
-
-def fetch_blob(url):
-    return json.loads(urllib.urlopen(url + '/api/json').read())
-
-
-if len(sys.argv) < 2:
-    print_usage()
-
-BASE_URL = sys.argv[1]
-
-root = fetch_blob(BASE_URL)
-results = {}
-for job_url in root['jobs']:
-    job = fetch_blob(job_url['url'])
-    if job.get('activeConfigurations'):
-        (tag, name) = job['name'].split('-')
-        if not results.get(tag):
-            results[tag] = {}
-        if not results[tag].get(name):
-            results[tag][name] = []
-
-        for config_url in job['activeConfigurations']:
-            config = fetch_blob(config_url['url'])
-
-            log_url = ''
-            if config.get('lastBuild'):
-                log_url = config['lastBuild']['url'] + 'console'
-
-            results[tag][name].append({'test': config['displayName'],
-                                       'status': config['color'],
-                                       'logUrl': log_url,
-                                       'healthReport': config['healthReport']})
-
-print(json.dumps(results))
diff --git a/tools/jenkins/run_test.sh b/tools/jenkins/run_test.sh
deleted file mode 100755
index d2b8284..0000000
--- a/tools/jenkins/run_test.sh
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/bin/bash
-
-EXECUTOR_NUMBER=$1
-ADAPTER=$2
-RC=$3
-
-function usage {
-    echo "Usage: $0 - Run a test"
-    echo ""
-    echo "$0 [EXECUTOR_NUMBER] [ADAPTER] [RC (optional)]"
-    exit 1
-}
-
-# Validate inputs
-if [[ "$EXECUTOR_NUMBER" = "" || "$ADAPTER" = "" ]]; then
-    usage
-fi
-
-# Execute configuration script
-cd adapters && ./$ADAPTER.sh $EXECUTOR_NUMBER $ADAPTER "$RC"
diff --git a/tools/xen/functions b/tools/xen/functions
index ab0be84..4317796 100644
--- a/tools/xen/functions
+++ b/tools/xen/functions
@@ -93,7 +93,7 @@
     echo $pbd_path
 }
 
-function find_ip_by_name() {
+function find_ip_by_name {
     local guest_name="$1"
     local interface="$2"
 
@@ -121,7 +121,7 @@
     done
 }
 
-function _vm_uuid() {
+function _vm_uuid {
     local vm_name_label
 
     vm_name_label="$1"
@@ -129,14 +129,14 @@
     xe vm-list name-label="$vm_name_label" --minimal
 }
 
-function _create_new_network() {
+function _create_new_network {
     local name_label
     name_label=$1
 
     xe network-create name-label="$name_label"
 }
 
-function _multiple_networks_with_name() {
+function _multiple_networks_with_name {
     local name_label
     name_label=$1
 
@@ -144,21 +144,21 @@
     xe network-list name-label="$name_label" --minimal | grep -q ","
 }
 
-function _network_exists() {
+function _network_exists {
     local name_label
     name_label=$1
 
     ! [ -z "$(xe network-list name-label="$name_label" --minimal)" ]
 }
 
-function _bridge_exists() {
+function _bridge_exists {
     local bridge
     bridge=$1
 
     ! [ -z "$(xe network-list bridge="$bridge" --minimal)" ]
 }
 
-function _network_uuid() {
+function _network_uuid {
     local bridge_or_net_name
     bridge_or_net_name=$1
 
@@ -169,7 +169,7 @@
     fi
 }
 
-function add_interface() {
+function add_interface {
     local vm_name_label
     local bridge_or_network_name
 
@@ -185,7 +185,7 @@
     xe vif-create network-uuid=$net vm-uuid=$vm device=$device_number
 }
 
-function setup_network() {
+function setup_network {
     local bridge_or_net_name
     bridge_or_net_name=$1
 
@@ -204,7 +204,7 @@
     fi
 }
 
-function bridge_for() {
+function bridge_for {
     local bridge_or_net_name
     bridge_or_net_name=$1
 
@@ -215,29 +215,28 @@
     fi
 }
 
-function xenapi_ip_on() {
+function xenapi_ip_on {
     local bridge_or_net_name
     bridge_or_net_name=$1
 
     ifconfig $(bridge_for "$bridge_or_net_name") | grep "inet addr" | cut -d ":" -f2 | sed "s/ .*//"
 }
 
-function xenapi_is_listening_on() {
+function xenapi_is_listening_on {
     local bridge_or_net_name
     bridge_or_net_name=$1
 
     ! [ -z $(xenapi_ip_on "$bridge_or_net_name") ]
 }
 
-function parameter_is_specified() {
+function parameter_is_specified {
     local parameter_name
     parameter_name=$1
 
     compgen -v | grep "$parameter_name"
 }
 
-function append_kernel_cmdline()
-{
+function append_kernel_cmdline {
     local vm_name_label
     local kernel_args
 
@@ -252,8 +251,7 @@
     xe vm-param-set PV-args="$pv_args $kernel_args" uuid=$vm
 }
 
-function destroy_all_vifs_of()
-{
+function destroy_all_vifs_of {
     local vm_name_label
 
     vm_name_label="$1"
@@ -268,11 +266,11 @@
     unset IFS
 }
 
-function have_multiple_hosts() {
+function have_multiple_hosts {
     xe host-list --minimal | grep -q ","
 }
 
-function attach_network() {
+function attach_network {
     local bridge_or_net_name
 
     bridge_or_net_name="$1"
@@ -286,7 +284,7 @@
     xe network-attach uuid=$net host-uuid=$host
 }
 
-function set_vm_memory() {
+function set_vm_memory {
     local vm_name_label
     local memory
 
@@ -305,7 +303,7 @@
         uuid=$vm
 }
 
-function max_vcpus() {
+function max_vcpus {
     local vm_name_label
 
     vm_name_label="$1"
@@ -337,7 +335,7 @@
     xe vm-param-set uuid=$vm VCPUs-at-startup=$cpu_count
 }
 
-function get_domid() {
+function get_domid {
     local vm_name_label
 
     vm_name_label="$1"
diff --git a/unstack.sh b/unstack.sh
index fe5fc77..0457ef2 100755
--- a/unstack.sh
+++ b/unstack.sh
@@ -162,6 +162,8 @@
     cleanup_trove
 fi
 
+stop_dstat
+
 # Clean up the remainder of the screen processes
 SCREEN=$(which screen)
 if [[ -n "$SCREEN" ]]; then