Merge "XenAPI:  Fix final script to include functions"
diff --git a/README.md b/README.md
index 89e3855..37b960e 100644
--- a/README.md
+++ b/README.md
@@ -2,11 +2,16 @@
 
 # Goals
 
-* To quickly build dev OpenStack environments in a clean Ubuntu or Fedora environment
-* To describe working configurations of OpenStack (which code branches work together?  what do config files look like for those branches?)
-* To make it easier for developers to dive into OpenStack so that they can productively contribute without having to understand every part of the system at once
+* To quickly build dev OpenStack environments in a clean Ubuntu or Fedora
+  environment
+* To describe working configurations of OpenStack (which code branches
+  work together?  what do config files look like for those branches?)
+* To make it easier for developers to dive into OpenStack so that they can
+  productively contribute without having to understand every part of the
+  system at once
 * To make it easy to prototype cross-project features
-* To provide an environment for the OpenStack CI testing on every commit to the projects
+* To provide an environment for the OpenStack CI testing on every commit
+  to the projects
 
 Read more at http://devstack.org.
 
@@ -42,12 +47,14 @@
 
     ./stack.sh
 
-When the script finishes executing, you should be able to access OpenStack endpoints, like so:
+When the script finishes executing, you should be able to access OpenStack
+endpoints, like so:
 
 * Horizon: http://myhost/
 * Keystone: http://myhost:5000/v2.0/
 
-We also provide an environment file that you can use to interact with your cloud via CLI:
+We also provide an environment file that you can use to interact with your
+cloud via CLI:
 
     # source openrc file to load your environment with OpenStack CLI creds
     . openrc
@@ -63,7 +70,12 @@
 
 # DevStack Execution Environment
 
-DevStack runs rampant over the system it runs on, installing things and uninstalling other things.  Running this on a system you care about is a recipe for disappointment, or worse.  Alas, we're all in the virtualization business here, so run it in a VM.  And take advantage of the snapshot capabilities of your hypervisor of choice to reduce testing cycle times.  You might even save enough time to write one more feature before the next feature freeze...
+DevStack runs rampant over the system it runs on, installing things and
+uninstalling other things.  Running this on a system you care about is a recipe
+for disappointment, or worse.  Alas, we're all in the virtualization business
+here, so run it in a VM.  And take advantage of the snapshot capabilities
+of your hypervisor of choice to reduce testing cycle times.  You might even save
+enough time to write one more feature before the next feature freeze...
 
 ``stack.sh`` needs to have root access for a lot of tasks, but uses ``sudo``
 for all of those tasks.  However, it needs to be not-root for most of its
@@ -93,7 +105,8 @@
 
 # Database Backend
 
-Multiple database backends are available. The available databases are defined in the lib/databases directory.
+Multiple database backends are available. The available databases are defined
+in the lib/databases directory.
 `mysql` is the default database, choose a different one by putting the
 following in the `localrc` section:
 
@@ -124,7 +137,7 @@
 `APACHE_ENABLED_SERVICES` in your ``localrc`` section.  Remember to
 enable these services at first as above.
 
-    APACHE_ENABLED_SERVICES+=keystone,swift
+    APACHE_ENABLED_SERVICES+=key,swift
 
 # Swift
 
@@ -235,10 +248,14 @@
 (e.g. linuxbridge).
 
     Variable Name                    Notes
-    -------------------------------------------------------------------------------------
-    Q_AGENT                          This specifies which agent to run with the ML2 Plugin (either `openvswitch` or `linuxbridge`).
-    Q_ML2_PLUGIN_MECHANISM_DRIVERS   The ML2 MechanismDrivers to load. The default is none. Note, ML2 will work with the OVS and LinuxBridge agents by default.
-    Q_ML2_PLUGIN_TYPE_DRIVERS        The ML2 TypeDrivers to load. Defaults to all available TypeDrivers.
+    ----------------------------------------------------------------------------
+    Q_AGENT                          This specifies which agent to run with the
+                                     ML2 Plugin (either `openvswitch` or `linuxbridge`).
+    Q_ML2_PLUGIN_MECHANISM_DRIVERS   The ML2 MechanismDrivers to load. The default
+                                     is none. Note, ML2 will work with the OVS
+                                     and LinuxBridge agents by default.
+    Q_ML2_PLUGIN_TYPE_DRIVERS        The ML2 TypeDrivers to load. Defaults to
+                                     all available TypeDrivers.
     Q_ML2_PLUGIN_GRE_TYPE_OPTIONS    GRE TypeDriver options. Defaults to none.
     Q_ML2_PLUGIN_VXLAN_TYPE_OPTIONS  VXLAN TypeDriver options. Defaults to none.
     Q_ML2_PLUGIN_VLAN_TYPE_OPTIONS   VLAN TypeDriver options. Defaults to none.
@@ -262,14 +279,16 @@
 
 # Tempest
 
-If tempest has been successfully configured, a basic set of smoke tests can be run as follows:
+If tempest has been successfully configured, a basic set of smoke
+tests can be run as follows:
 
     $ cd /opt/stack/tempest
     $ nosetests tempest/scenario/test_network_basic_ops.py
 
 # DevStack on Xenserver
 
-If you would like to use Xenserver as the hypervisor, please refer to the instructions in `./tools/xen/README.md`.
+If you would like to use Xenserver as the hypervisor, please refer
+to the instructions in `./tools/xen/README.md`.
 
 # Additional Projects
 
@@ -283,8 +302,10 @@
 
 # Multi-Node Setup
 
-A more interesting setup involves running multiple compute nodes, with Neutron networks connecting VMs on different compute nodes.
-You should run at least one "controller node", which should have a `stackrc` that includes at least:
+A more interesting setup involves running multiple compute nodes, with Neutron
+networks connecting VMs on different compute nodes.
+You should run at least one "controller node", which should have a `stackrc`
+that includes at least:
 
     disable_service n-net
     enable_service q-svc
@@ -299,7 +320,8 @@
 
     SCHEDULER=nova.scheduler.simple.SimpleScheduler
 
-You can then run many compute nodes, each of which should have a `stackrc` which includes the following, with the IP address of the above controller node:
+You can then run many compute nodes, each of which should have a `stackrc`
+which includes the following, with the IP address of the above controller node:
 
     ENABLED_SERVICES=n-cpu,rabbit,g-api,neutron,q-agt
     SERVICE_HOST=[IP of controller node]
@@ -310,22 +332,31 @@
 
 # Cells
 
-Cells is a new scaling option with a full spec at http://wiki.openstack.org/blueprint-nova-compute-cells.
+Cells is a new scaling option with a full spec at:
+http://wiki.openstack.org/blueprint-nova-compute-cells.
 
 To setup a cells environment add the following to your `localrc` section:
 
     enable_service n-cell
 
-Be aware that there are some features currently missing in cells, one notable one being security groups.  The exercises have been patched to disable functionality not supported by cells.
+Be aware that there are some features currently missing in cells, one notable
+one being security groups.  The exercises have been patched to disable
+functionality not supported by cells.
 
 
 # Local Configuration
 
-Historically DevStack has used ``localrc`` to contain all local configuration and customizations. More and more of the configuration variables available for DevStack are passed-through to the individual project configuration files.  The old mechanism for this required specific code for each file and did not scale well.  This is handled now by a master local configuration file.
+Historically DevStack has used ``localrc`` to contain all local configuration
+and customizations. More and more of the configuration variables available for
+DevStack are passed-through to the individual project configuration files.
+The old mechanism for this required specific code for each file and did not
+scale well.  This is handled now by a master local configuration file.
 
 # local.conf
 
-The new config file ``local.conf`` is an extended-INI format that introduces a new meta-section header that provides some additional information such as a phase name and destination config filename:
+The new config file ``local.conf`` is an extended-INI format that introduces
+a new meta-section header that provides some additional information such
+as a phase name and destination config filename:
 
     [[ <phase> | <config-file-name> ]]
 
@@ -339,11 +370,15 @@
 The defined phases are:
 
 * **local** - extracts ``localrc`` from ``local.conf`` before ``stackrc`` is sourced
-* **post-config** - runs after the layer 2 services are configured and before they are started
-* **extra** - runs after services are started and before any files in ``extra.d`` are executed
+* **post-config** - runs after the layer 2 services are configured
+                    and before they are started
+* **extra** - runs after services are started and before any files
+              in ``extra.d`` are executed
 * **post-extra** - runs after files in ``extra.d`` are executed
 
-The file is processed strictly in sequence; meta-sections may be specified more than once but if any settings are duplicated the last to appear in the file will be used.
+The file is processed strictly in sequence; meta-sections may be specified more
+than once but if any settings are duplicated the last to appear in the file
+will be used.
 
     [[post-config|$NOVA_CONF]]
     [DEFAULT]
diff --git a/clean.sh b/clean.sh
index 3707d84..7851da3 100755
--- a/clean.sh
+++ b/clean.sh
@@ -102,7 +102,7 @@
 fi
 
 # Clean out /etc
-sudo rm -rf /etc/keystone /etc/glance /etc/nova /etc/cinder /etc/swift
+sudo rm -rf /etc/keystone /etc/glance /etc/nova /etc/cinder /etc/swift /etc/heat /etc/neutron
 
 # Clean out tgt
 sudo rm -f /etc/tgt/conf.d/*
diff --git a/exercises/client-env.sh b/exercises/client-env.sh
index 4e8259c..cc518d9 100755
--- a/exercises/client-env.sh
+++ b/exercises/client-env.sh
@@ -28,7 +28,7 @@
 source $TOP_DIR/functions
 
 # Import configuration
-source $TOP_DIR/openrc
+source $TOP_DIR/openrc admin
 
 # Import exercise configuration
 source $TOP_DIR/exerciserc
diff --git a/files/apts/baremetal b/files/apts/baremetal
index 54e76e0..06ffab6 100644
--- a/files/apts/baremetal
+++ b/files/apts/baremetal
@@ -1,6 +1,5 @@
 busybox
 dnsmasq
-gcc
 ipmitool
 make
 open-iscsi
diff --git a/files/apts/general b/files/apts/general
index 020d84f..d81ec7a 100644
--- a/files/apts/general
+++ b/files/apts/general
@@ -5,6 +5,7 @@
 unzip
 wget
 psmisc
+gcc
 git
 lsof # useful when debugging
 openssh-server
diff --git a/files/apts/glance b/files/apts/glance
index e80f447..b5d8c77 100644
--- a/files/apts/glance
+++ b/files/apts/glance
@@ -1,4 +1,3 @@
-gcc
 libffi-dev
 libmysqlclient-dev  # testonly
 libpq-dev           # testonly
diff --git a/files/apts/ironic b/files/apts/ironic
index a749ad7..b77a6b1 100644
--- a/files/apts/ironic
+++ b/files/apts/ironic
@@ -1,3 +1,4 @@
+iptables
 libguestfs0
 libvirt-bin
 openssh-client
diff --git a/files/apts/swift b/files/apts/swift
index 0c27b5b..080ecdb 100644
--- a/files/apts/swift
+++ b/files/apts/swift
@@ -1,5 +1,4 @@
 curl
-gcc
 libffi-dev
 memcached
 python-configobj
diff --git a/files/apts/trema b/files/apts/trema
index 09cb7c6..f685ca5 100644
--- a/files/apts/trema
+++ b/files/apts/trema
@@ -1,5 +1,4 @@
 # Trema
-gcc
 make
 ruby1.8
 rubygems1.8
diff --git a/files/patches/unittest2-discover.patch b/files/patches/unittest2-discover.patch
new file mode 100644
index 0000000..347300d
--- /dev/null
+++ b/files/patches/unittest2-discover.patch
@@ -0,0 +1,16 @@
+diff -r b2efb7df637b discover.py
+--- a/discover.py	Thu Mar 24 00:31:02 2011 -0400
++++ b/discover.py	Thu Nov 28 12:02:19 2013 +0000
+@@ -82,7 +82,11 @@
+     """
+     testMethodPrefix = 'test'
+     sortTestMethodsUsing = cmp
+-    suiteClass = unittest.TestSuite
++    try:
++        import unittest2
++        suiteClass = unittest2.TestSuite
++    except ImportError:
++        suiteClass = unittest.TestSuite
+     _top_level_dir = None
+ 
+     def loadTestsFromTestCase(self, testCaseClass):
diff --git a/files/rpms-suse/general b/files/rpms-suse/general
index ff27a3a..82cb09d 100644
--- a/files/rpms-suse/general
+++ b/files/rpms-suse/general
@@ -3,6 +3,7 @@
 ca-certificates-mozilla
 curl
 euca2ools
+gcc
 git-core
 iputils
 libopenssl-devel # to rebuild pyOpenSSL if needed
diff --git a/files/rpms-suse/glance b/files/rpms-suse/glance
index d9844e9..edd1564 100644
--- a/files/rpms-suse/glance
+++ b/files/rpms-suse/glance
@@ -1,4 +1,3 @@
-gcc
 libxml2-devel
 python-PasteDeploy
 python-Routes
diff --git a/files/rpms-suse/swift b/files/rpms-suse/swift
index f3c95aa..4b14098 100644
--- a/files/rpms-suse/swift
+++ b/files/rpms-suse/swift
@@ -1,5 +1,4 @@
 curl
-gcc
 memcached
 python-PasteDeploy
 python-WebOb
diff --git a/files/rpms/general b/files/rpms/general
index 99be725..c940de6 100644
--- a/files/rpms/general
+++ b/files/rpms/general
@@ -2,13 +2,13 @@
 curl
 dbus
 euca2ools # only for testing client
-gcc # dist:rhel6 [2]
+gcc
 git-core
 openssh-server
 openssl
 openssl-devel # to rebuild pyOpenSSL if needed
-libxml2-devel # dist:rhel6 [2]
-libxslt-devel # dist:rhel6 [2]
+libxml2-devel
+libxslt-devel
 psmisc
 pylint
 python-setuptools
@@ -28,7 +28,3 @@
 # but others have versioned (<=0.7).  So if a later version (0.7.1)
 # gets installed in response to an unversioned dependency, it breaks.
 # This pre-installs a compatible 0.6(ish) version from RHEL
-
-# [2] : RHEL6 rpm versions of python-lxml is old, and has to be
-# removed.  Several tools rely on it, so we install the dependencies
-# pip needs to build it here (see tools/install_prereqs.sh)
diff --git a/files/rpms/glance b/files/rpms/glance
index f959c22..fc07fa7 100644
--- a/files/rpms/glance
+++ b/files/rpms/glance
@@ -1,4 +1,3 @@
-gcc
 libffi-devel
 libxml2-devel       # testonly
 libxslt-devel       # testonly
diff --git a/files/rpms/horizon b/files/rpms/horizon
index 38d349d..92afed2 100644
--- a/files/rpms/horizon
+++ b/files/rpms/horizon
@@ -1,5 +1,4 @@
 Django
-gcc
 httpd # NOPRIME
 mod_wsgi  # NOPRIME
 pylint
diff --git a/files/rpms/ironic b/files/rpms/ironic
index 54b9829..6534095 100644
--- a/files/rpms/ironic
+++ b/files/rpms/ironic
@@ -1,6 +1,8 @@
+iptables
 libguestfs
 libvirt
 libvirt-python
+net-tools
 openssh-clients
 openvswitch
 python-libguestfs
diff --git a/files/rpms/swift b/files/rpms/swift
index ec53424..938d2c8 100644
--- a/files/rpms/swift
+++ b/files/rpms/swift
@@ -1,5 +1,4 @@
 curl
-gcc
 libffi-devel
 memcached
 python-configobj
diff --git a/lib/ceilometer b/lib/ceilometer
index 5476773..59f572c 100644
--- a/lib/ceilometer
+++ b/lib/ceilometer
@@ -237,7 +237,7 @@
 # start_ceilometer() - Start running processes, including screen
 function start_ceilometer {
     if [[ "$VIRT_DRIVER" = 'libvirt' ]]; then
-        screen_it ceilometer-acompute "cd ; sg $LIBVIRT_GROUP \"ceilometer-agent-compute --config-file $CEILOMETER_CONF\""
+        screen_it ceilometer-acompute "cd ; sg $LIBVIRT_GROUP 'ceilometer-agent-compute --config-file $CEILOMETER_CONF'"
     fi
     if [[ "$VIRT_DRIVER" = 'vsphere' ]]; then
         screen_it ceilometer-acompute "cd ; ceilometer-agent-compute --config-file $CEILOMETER_CONF"
diff --git a/lib/databases/mysql b/lib/databases/mysql
index 0a96cf8..ea22d14 100644
--- a/lib/databases/mysql
+++ b/lib/databases/mysql
@@ -47,6 +47,7 @@
 }
 
 function configure_database_mysql {
+    local slow_log
     echo_summary "Configuring and starting MySQL"
 
     if is_ubuntu; then
@@ -92,7 +93,11 @@
 
     if [[ "$DATABASE_QUERY_LOGGING" == "True" ]]; then
         echo_summary "Enabling MySQL query logging"
-
+        if is_fedora && ! [[ $DISTRO =~ (rhel6) ]]; then
+            slow_log=/var/log/mariadb/mariadb-slow.log
+        else
+            slow_log=/var/log/mysql/mysql-slow.log
+        fi
         sudo sed -e '/log.slow.queries/d' \
             -e '/long.query.time/d' \
             -e '/log.queries.not.using.indexes/d' \
@@ -102,7 +107,7 @@
         # 0 seconds) and log all non-indexed queries
         sudo bash -c "source $TOP_DIR/functions && \
             iniset $MY_CONF mysqld slow-query-log 1 && \
-            iniset $MY_CONF mysqld slow-query-log-file /var/log/mysql/mysql-slow.log && \
+            iniset $MY_CONF mysqld slow-query-log-file $slow_log && \
             iniset $MY_CONF mysqld long-query-time 0 && \
             iniset $MY_CONF mysqld log-queries-not-using-indexes 1"
 
diff --git a/lib/horizon b/lib/horizon
index 90a2bc5..9ce4853 100644
--- a/lib/horizon
+++ b/lib/horizon
@@ -45,7 +45,10 @@
     local option=$3
     local value=$4
 
-    if grep -q "^$section" $file; then
+    if [ -z "$section" ]; then
+        sed -e "/^$option/d" -i $local_settings
+        echo -e "\n$option=$value" >> $file
+    elif grep -q "^$section" $file; then
         line=$(sed -ne "/^$section/,/^}/ { /^ *'$option':/ p; }" $file)
         if [ -n "$line" ]; then
             sed -i -e "/^$section/,/^}/ s/^\( *'$option'\) *:.*$/\1: $value,/" $file
@@ -103,6 +106,13 @@
         _horizon_config_set $local_settings OPENSTACK_NEUTRON_NETWORK enable_vpn True
     fi
 
+    _horizon_config_set $local_settings "" OPENSTACK_HOST \"${KEYSTONE_SERVICE_HOST}\"
+    _horizon_config_set $local_settings "" OPENSTACK_KEYSTONE_URL "\"${KEYSTONE_SERVICE_PROTOCOL}://%s:${KEYSTONE_SERVICE_PORT}/v2.0\" % OPENSTACK_HOST"
+
+    if [ -f $SSL_BUNDLE_FILE ]; then
+        _horizon_config_set $local_settings "" OPENSTACK_SSL_CACERT \"${SSL_BUNDLE_FILE}\"
+    fi
+
     # Create an empty directory that apache uses as docroot
     sudo mkdir -p $HORIZON_DIR/.blackhole
 
diff --git a/lib/ironic b/lib/ironic
index 757b83e..389040c 100644
--- a/lib/ironic
+++ b/lib/ironic
@@ -53,18 +53,24 @@
 IRONIC_VM_SSH_ADDRESS=${IRONIC_VM_SSH_ADDRESS:-$HOST_IP}
 IRONIC_VM_COUNT=${IRONIC_VM_COUNT:-1}
 IRONIC_VM_SPECS_CPU=${IRONIC_VM_SPECS_CPU:-1}
-# NOTE(agordeev): both ubuntu and fedora deploy images won't work with 256MB of RAM.
-#                 System halts and throws kernel panic during initramfs unpacking.
-#                 Ubuntu needs at least 384MB, but fedora requires 448.
-#                 So placing 512 here to satisfy both.
-IRONIC_VM_SPECS_RAM=${IRONIC_VM_SPECS_RAM:-512}
+# NOTE(adam_g): Kernels 3.12 and newer user tmpfs by default for initramfs.
+#               DIB produced ramdisks tend to be ~250MB but tmpfs will only allow
+#               use of 50% of available memory before ENOSPC.  Set minimum 1GB
+#               for nodes to avoid (LP: #1311987) and ensure consistency across
+#               older and newer kernels.
+IRONIC_VM_SPECS_RAM=${IRONIC_VM_SPECS_RAM:-1024}
 IRONIC_VM_SPECS_DISK=${IRONIC_VM_SPECS_DISK:-10}
+IRONIC_VM_EPHEMERAL_DISK=${IRONIC_VM_EPHEMERAL_DISK:-0}
 IRONIC_VM_EMULATOR=${IRONIC_VM_EMULATOR:-/usr/bin/qemu-system-x86_64}
 IRONIC_VM_NETWORK_BRIDGE=${IRONIC_VM_NETWORK_BRIDGE:-brbm}
 IRONIC_VM_NETWORK_RANGE=${IRONIC_VM_NETWORK_RANGE:-192.0.2.0/24}
 IRONIC_VM_MACS_CSV_FILE=${IRONIC_VM_MACS_CSV_FILE:-$IRONIC_DATA_DIR/ironic_macs.csv}
 IRONIC_AUTHORIZED_KEYS_FILE=${IRONIC_AUTHORIZED_KEYS_FILE:-$HOME/.ssh/authorized_keys}
 
+# By default, baremetal VMs will console output to file.
+IRONIC_VM_LOG_CONSOLE=${IRONIC_VM_LOG_CONSOLE:-True}
+IRONIC_VM_LOG_DIR=${IRONIC_VM_LOG_DIR:-$IRONIC_DATA_DIR/logs/}
+
 DIB_DIR=${DIB_DIR:-$DEST/diskimage-builder}
 
 # Use DIB to create deploy ramdisk and kernel.
@@ -186,6 +192,9 @@
     iniset $IRONIC_CONF_FILE pxe tftp_server $HOST_IP
     iniset $IRONIC_CONF_FILE pxe tftp_root $IRONIC_TFTPBOOT_DIR
     iniset $IRONIC_CONF_FILE pxe tftp_master_path $IRONIC_TFTPBOOT_DIR/master_images
+    if [[ "$IRONIC_VM_LOG_CONSOLE" == "True" ]] ; then
+        iniset $IRONIC_CONF_FILE pxe pxe_append_params "nofb nomodeset vga=normal console=ttyS0"
+    fi
 }
 
 # create_ironic_cache_dir() - Part of the init_ironic() process
@@ -315,9 +324,15 @@
 function create_bridge_and_vms {
     # Call libvirt setup scripts in a new shell to ensure any new group membership
     sudo su $STACK_USER -c "$IRONIC_SCRIPTS_DIR/setup-network"
+    if [[ "$IRONIC_VM_LOG_CONSOLE" == "True" ]] ; then
+        LOG_ARG="$IRONIC_VM_LOG_DIR"
+    else
+        LOG_ARG=""
+    fi
     sudo su $STACK_USER -c "$IRONIC_SCRIPTS_DIR/create-nodes \
         $IRONIC_VM_SPECS_CPU $IRONIC_VM_SPECS_RAM $IRONIC_VM_SPECS_DISK \
-        amd64 $IRONIC_VM_COUNT $IRONIC_VM_NETWORK_BRIDGE $IRONIC_VM_EMULATOR" >> $IRONIC_VM_MACS_CSV_FILE
+        amd64 $IRONIC_VM_COUNT $IRONIC_VM_NETWORK_BRIDGE $IRONIC_VM_EMULATOR \
+        $LOG_ARG" >> $IRONIC_VM_MACS_CSV_FILE
 }
 
 function enroll_vms {
@@ -355,7 +370,8 @@
     done < $IRONIC_VM_MACS_CSV_FILE
 
     # create the nova flavor
-    nova flavor-create baremetal auto $IRONIC_VM_SPECS_RAM $IRONIC_VM_SPECS_DISK $IRONIC_VM_SPECS_CPU
+    adjusted_disk=$(($IRONIC_VM_SPECS_DISK - $IRONIC_VM_EPHEMERAL_DISK))
+    nova flavor-create --ephemeral $IRONIC_VM_EPHEMERAL_DISK baremetal auto $IRONIC_VM_SPECS_RAM $adjusted_disk $IRONIC_VM_SPECS_CPU
     nova flavor-key baremetal set "cpu_arch"="x86_64" "baremetal:deploy_kernel_id"="$IRONIC_DEPLOY_KERNEL_ID" "baremetal:deploy_ramdisk_id"="$IRONIC_DEPLOY_RAMDISK_ID"
 
     # intentional sleep to make sure the tag has been set to port
@@ -379,11 +395,16 @@
     neutron port-delete $PORT_ID
 }
 
-function configure_tftpd {
-    # enable tftp natting for allowing connections to SERVICE_HOST's tftp server
+function configure_iptables {
+    # enable tftp natting for allowing connections to HOST_IP's tftp server
     sudo modprobe nf_conntrack_tftp
     sudo modprobe nf_nat_tftp
+    # nodes boot from TFTP and callback to the API server listening on $HOST_IP
+    sudo iptables -I INPUT -d $HOST_IP -p udp --dport 69 -j ACCEPT || true
+    sudo iptables -I INPUT -d $HOST_IP -p tcp --dport 6385 -j ACCEPT || true
+}
 
+function configure_tftpd {
     if is_ubuntu; then
         PXEBIN=/usr/lib/syslinux/pxelinux.0
     elif is_fedora; then
@@ -506,6 +527,7 @@
     create_bridge_and_vms
     enroll_vms
     configure_tftpd
+    configure_iptables
 
     # restart nova-compute to ensure its resource tracking is up to
     # date with newly enrolled nodes
@@ -525,6 +547,10 @@
     sudo su $STACK_USER -c "$IRONIC_SCRIPTS_DIR/cleanup-nodes $IRONIC_VM_COUNT $IRONIC_VM_NETWORK_BRIDGE"
     sudo rm -rf /etc/xinetd.d/tftp /etc/init/tftpd-hpa.override
     restart_service xinetd
+    sudo iptables -D INPUT -d $HOST_IP -p udp --dport 69 -j ACCEPT || true
+    sudo iptables -D INPUT -d $HOST_IP -p tcp --dport 6385 -j ACCEPT || true
+    sudo rmmod nf_conntrack_tftp || true
+    sudo rmmod nf_nat_tftp || true
 }
 
 # Restore xtrace + pipefail
diff --git a/lib/keystone b/lib/keystone
index b31cc57..f8e92f4 100644
--- a/lib/keystone
+++ b/lib/keystone
@@ -253,11 +253,17 @@
     fi
 
     # Format logging
-    if [ "$LOG_COLOR" == "True" ] && [ "$SYSLOG" == "False" ]; then
+    if [ "$LOG_COLOR" == "True" ] && [ "$SYSLOG" == "False" ] &&  ! is_apache_enabled_service key ; then
         setup_colorized_logging $KEYSTONE_CONF DEFAULT
     fi
 
     if is_apache_enabled_service key; then
+        iniset $KEYSTONE_CONF DEFAULT debug "True"
+        # Eliminate the %(asctime)s.%(msecs)03d from the log format strings
+        iniset $KEYSTONE_CONF DEFAULT logging_context_format_string "%(process)d %(levelname)s %(name)s [%(request_id)s %(user_identity)s] %(instance)s%(message)s"
+        iniset $KEYSTONE_CONF DEFAULT logging_default_format_string "%(process)d %(levelname)s %(name)s [-] %(instance)s%(message)s"
+        iniset $KEYSTONE_CONF DEFAULT logging_debug_format_suffix "%(funcName)s %(pathname)s:%(lineno)d"
+        iniset $KEYSTONE_CONF DEFAULT logging_exception_prefix "%(process)d TRACE %(name)s %(instance)s"
         _config_keystone_apache_wsgi
     fi
 }
@@ -450,6 +456,8 @@
 function stop_keystone {
     # Kill the Keystone screen window
     screen_stop key
+    # Cleanup the WSGI files and VHOST
+    _cleanup_keystone_apache_wsgi
 }
 
 
diff --git a/lib/neutron b/lib/neutron
index 9e1e787..15cfa8e 100644
--- a/lib/neutron
+++ b/lib/neutron
@@ -316,7 +316,7 @@
     # set NOVA_VIF_DRIVER and optionally set options in nova_conf
     neutron_plugin_create_nova_conf
 
-    iniset $NOVA_CONF DEFAULT libvirt_vif_driver "$NOVA_VIF_DRIVER"
+    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"
diff --git a/lib/neutron_plugins/cisco b/lib/neutron_plugins/cisco
index 7f7c049..dccf400 100644
--- a/lib/neutron_plugins/cisco
+++ b/lib/neutron_plugins/cisco
@@ -183,6 +183,15 @@
         ovs_neutron_plugin_configure_common
         Q_PLUGIN_EXTRA_CONF_PATH=etc/neutron/plugins/cisco
         Q_PLUGIN_EXTRA_CONF_FILES=(cisco_plugins.ini)
+        # Copy extra config files to /etc so that they can be modified
+        # later according to Cisco-specific localrc settings.
+        mkdir -p /$Q_PLUGIN_EXTRA_CONF_PATH
+        local f
+        local extra_conf_file
+        for (( f=0; $f < ${#Q_PLUGIN_EXTRA_CONF_FILES[@]}; f+=1 )); do
+            extra_conf_file=$Q_PLUGIN_EXTRA_CONF_PATH/${Q_PLUGIN_EXTRA_CONF_FILES[$f]}
+            cp $NEUTRON_DIR/$extra_conf_file /$extra_conf_file
+        done
     else
         Q_PLUGIN_CONF_PATH=etc/neutron/plugins/cisco
         Q_PLUGIN_CONF_FILENAME=cisco_plugins.ini
diff --git a/lib/neutron_plugins/linuxbridge b/lib/neutron_plugins/linuxbridge
index 96b14f1..113a7df 100644
--- a/lib/neutron_plugins/linuxbridge
+++ b/lib/neutron_plugins/linuxbridge
@@ -15,7 +15,7 @@
 }
 
 function neutron_plugin_configure_service {
-    if [[ "$ENABLE_TENANT_VLANS" = "True" ]]; then
+    if [[ "$ENABLE_TENANT_VLANS" == "True" ]]; then
         iniset /$Q_PLUGIN_CONF_FILE vlans tenant_network_type vlan
     else
         echo "WARNING - The linuxbridge plugin is using local tenant networks, with no connectivity between hosts."
@@ -23,7 +23,7 @@
 
     # Override ``LB_VLAN_RANGES`` and ``LB_INTERFACE_MAPPINGS`` in ``localrc``
     # for more complex physical network configurations.
-    if [[ "$LB_VLAN_RANGES" = "" ]] && [[ "$PHYSICAL_NETWORK" != "" ]]; then
+    if [[ "$LB_VLAN_RANGES" == "" ]] && [[ "$PHYSICAL_NETWORK" != "" ]]; then
         LB_VLAN_RANGES=$PHYSICAL_NETWORK
         if [[ "$TENANT_VLAN_RANGE" != "" ]]; then
             LB_VLAN_RANGES=$LB_VLAN_RANGES:$TENANT_VLAN_RANGE
diff --git a/lib/neutron_plugins/linuxbridge_agent b/lib/neutron_plugins/linuxbridge_agent
index 74799e4..82b5fc9 100644
--- a/lib/neutron_plugins/linuxbridge_agent
+++ b/lib/neutron_plugins/linuxbridge_agent
@@ -35,7 +35,7 @@
     # Setup physical network interface mappings.  Override
     # ``LB_VLAN_RANGES`` and ``LB_INTERFACE_MAPPINGS`` in ``localrc`` for more
     # complex physical network configurations.
-    if [[ "$LB_INTERFACE_MAPPINGS" = "" ]] && [[ "$PHYSICAL_NETWORK" != "" ]] && [[ "$LB_PHYSICAL_INTERFACE" != "" ]]; then
+    if [[ "$LB_INTERFACE_MAPPINGS" == "" ]] && [[ "$PHYSICAL_NETWORK" != "" ]] && [[ "$LB_PHYSICAL_INTERFACE" != "" ]]; then
         LB_INTERFACE_MAPPINGS=$PHYSICAL_NETWORK:$LB_PHYSICAL_INTERFACE
     fi
     if [[ "$LB_INTERFACE_MAPPINGS" != "" ]]; then
diff --git a/lib/neutron_plugins/ml2 b/lib/neutron_plugins/ml2
index db43fcf..9966373 100644
--- a/lib/neutron_plugins/ml2
+++ b/lib/neutron_plugins/ml2
@@ -11,7 +11,7 @@
 # This has to be set here since the agent will set this in the config file
 if [[ "$Q_ML2_TENANT_NETWORK_TYPE" != "" ]]; then
     Q_AGENT_EXTRA_AGENT_OPTS+=(tunnel_types=$Q_ML2_TENANT_NETWORK_TYPE)
-elif [[ "$ENABLE_TENANT_TUNNELS" = "True" ]]; then
+elif [[ "$ENABLE_TENANT_TUNNELS" == "True" ]]; then
     Q_AGENT_EXTRA_AGENT_OPTS+=(tunnel_types=gre)
 fi
 
@@ -60,12 +60,12 @@
 function neutron_plugin_configure_service {
     if [[ "$Q_ML2_TENANT_NETWORK_TYPE" != "" ]]; then
         Q_SRV_EXTRA_OPTS+=(tenant_network_types=$Q_ML2_TENANT_NETWORK_TYPE)
-    elif [[ "$ENABLE_TENANT_TUNNELS" = "True" ]]; then
+    elif [[ "$ENABLE_TENANT_TUNNELS" == "True" ]]; then
         # This assumes you want a simple configuration, and will overwrite
         # Q_SRV_EXTRA_OPTS if set in addition to ENABLE_TENANT_TUNNELS.
         Q_SRV_EXTRA_OPTS+=(tenant_network_types=gre)
         Q_ML2_PLUGIN_GRE_TYPE_OPTIONS=(tunnel_id_ranges=$TENANT_TUNNEL_RANGES)
-    elif [[ "$ENABLE_TENANT_VLANS" = "True" ]]; then
+    elif [[ "$ENABLE_TENANT_VLANS" == "True" ]]; then
         Q_SRV_EXTRA_OPTS+=(tenant_network_types=vlan)
     else
         echo "WARNING - The ml2 plugin is using local tenant networks, with no connectivity between hosts."
@@ -74,7 +74,7 @@
     # Allow for overrding VLAN configuration (for example, to configure provider
     # VLANs) by first checking if Q_ML2_PLUGIN_VLAN_TYPE_OPTIONS is set.
     if [ "$Q_ML2_PLUGIN_VLAN_TYPE_OPTIONS" == "" ]; then
-        if [[ "$ML2_VLAN_RANGES" = "" ]] && [[ "$PHYSICAL_NETWORK" != "" ]]; then
+        if [[ "$ML2_VLAN_RANGES" == "" ]] && [[ "$PHYSICAL_NETWORK" != "" ]]; then
             ML2_VLAN_RANGES=$PHYSICAL_NETWORK
             if [[ "$TENANT_VLAN_RANGE" != "" ]]; then
                 ML2_VLAN_RANGES=$ML2_VLAN_RANGES:$TENANT_VLAN_RANGE
diff --git a/lib/neutron_plugins/ofagent_agent b/lib/neutron_plugins/ofagent_agent
index 6610ea3..b8321f3 100644
--- a/lib/neutron_plugins/ofagent_agent
+++ b/lib/neutron_plugins/ofagent_agent
@@ -46,7 +46,7 @@
     fi
 
     # Enable tunnel networks if selected
-    if [[ "$OVS_ENABLE_TUNNELING" = "True" ]]; then
+    if [[ "$OVS_ENABLE_TUNNELING" == "True" ]]; then
         # Verify tunnels are supported
         # REVISIT - also check kernel module support for GRE and patch ports
         OVS_VERSION=`ovs-vsctl --version | head -n 1 | grep -E -o "[0-9]+\.[0-9]+"`
@@ -60,7 +60,7 @@
     # Setup physical network bridge mappings.  Override
     # ``OVS_VLAN_RANGES`` and ``OVS_BRIDGE_MAPPINGS`` in ``localrc`` for more
     # complex physical network configurations.
-    if [[ "$OVS_BRIDGE_MAPPINGS" = "" ]] && [[ "$PHYSICAL_NETWORK" != "" ]] && [[ "$OVS_PHYSICAL_BRIDGE" != "" ]]; then
+    if [[ "$OVS_BRIDGE_MAPPINGS" == "" ]] && [[ "$PHYSICAL_NETWORK" != "" ]] && [[ "$OVS_PHYSICAL_BRIDGE" != "" ]]; then
         OVS_BRIDGE_MAPPINGS=$PHYSICAL_NETWORK:$OVS_PHYSICAL_BRIDGE
 
         # Configure bridge manually with physical interface as port for multi-node
diff --git a/lib/neutron_plugins/openvswitch b/lib/neutron_plugins/openvswitch
index c644fed..fc81092 100644
--- a/lib/neutron_plugins/openvswitch
+++ b/lib/neutron_plugins/openvswitch
@@ -15,10 +15,10 @@
 }
 
 function neutron_plugin_configure_service {
-    if [[ "$ENABLE_TENANT_TUNNELS" = "True" ]]; then
+    if [[ "$ENABLE_TENANT_TUNNELS" == "True" ]]; then
         iniset /$Q_PLUGIN_CONF_FILE ovs tenant_network_type gre
         iniset /$Q_PLUGIN_CONF_FILE ovs tunnel_id_ranges $TENANT_TUNNEL_RANGES
-    elif [[ "$ENABLE_TENANT_VLANS" = "True" ]]; then
+    elif [[ "$ENABLE_TENANT_VLANS" == "True" ]]; then
         iniset /$Q_PLUGIN_CONF_FILE ovs tenant_network_type vlan
     else
         echo "WARNING - The openvswitch plugin is using local tenant networks, with no connectivity between hosts."
@@ -26,7 +26,7 @@
 
     # Override ``OVS_VLAN_RANGES`` and ``OVS_BRIDGE_MAPPINGS`` in ``localrc``
     # for more complex physical network configurations.
-    if [[ "$OVS_VLAN_RANGES" = "" ]] && [[ "$PHYSICAL_NETWORK" != "" ]]; then
+    if [[ "$OVS_VLAN_RANGES" == "" ]] && [[ "$PHYSICAL_NETWORK" != "" ]]; then
         OVS_VLAN_RANGES=$PHYSICAL_NETWORK
         if [[ "$TENANT_VLAN_RANGE" != "" ]]; then
             OVS_VLAN_RANGES=$OVS_VLAN_RANGES:$TENANT_VLAN_RANGE
@@ -37,7 +37,7 @@
     fi
 
     # Enable tunnel networks if selected
-    if [[ $OVS_ENABLE_TUNNELING = "True" ]]; then
+    if [[ $OVS_ENABLE_TUNNELING == "True" ]]; then
         iniset /$Q_PLUGIN_CONF_FILE ovs enable_tunneling True
     fi
 
diff --git a/lib/neutron_plugins/openvswitch_agent b/lib/neutron_plugins/openvswitch_agent
index 33ca17a..fbc013f 100644
--- a/lib/neutron_plugins/openvswitch_agent
+++ b/lib/neutron_plugins/openvswitch_agent
@@ -9,9 +9,9 @@
 
 function neutron_plugin_create_nova_conf {
     _neutron_ovs_base_configure_nova_vif_driver
-    if [ "$VIRT_DRIVER" = 'xenserver' ]; then
-        iniset $NOVA_CONF DEFAULT xenapi_vif_driver nova.virt.xenapi.vif.XenAPIOpenVswitchDriver
-        iniset $NOVA_CONF DEFAULT xenapi_ovs_integration_bridge $XEN_INTEGRATION_BRIDGE
+    if [ "$VIRT_DRIVER" == 'xenserver' ]; then
+        iniset $NOVA_CONF xenserver vif_driver nova.virt.xenapi.vif.XenAPIOpenVswitchDriver
+        iniset $NOVA_CONF xenserver ovs_integration_bridge $XEN_INTEGRATION_BRIDGE
         # Disable nova's firewall so that it does not conflict with neutron
         iniset $NOVA_CONF DEFAULT firewall_driver nova.virt.firewall.NoopFirewallDriver
     fi
@@ -40,7 +40,7 @@
     _neutron_ovs_base_configure_firewall_driver
 
     # Setup agent for tunneling
-    if [[ "$OVS_ENABLE_TUNNELING" = "True" ]]; then
+    if [[ "$OVS_ENABLE_TUNNELING" == "True" ]]; then
         # Verify tunnels are supported
         # REVISIT - also check kernel module support for GRE and patch ports
         OVS_VERSION=`ovs-vsctl --version | head -n 1 | grep -E -o "[0-9]+\.[0-9]+"`
@@ -54,7 +54,7 @@
     # Setup physical network bridge mappings.  Override
     # ``OVS_VLAN_RANGES`` and ``OVS_BRIDGE_MAPPINGS`` in ``localrc`` for more
     # complex physical network configurations.
-    if [[ "$OVS_BRIDGE_MAPPINGS" = "" ]] && [[ "$PHYSICAL_NETWORK" != "" ]] && [[ "$OVS_PHYSICAL_BRIDGE" != "" ]]; then
+    if [[ "$OVS_BRIDGE_MAPPINGS" == "" ]] && [[ "$PHYSICAL_NETWORK" != "" ]] && [[ "$OVS_PHYSICAL_BRIDGE" != "" ]]; then
         OVS_BRIDGE_MAPPINGS=$PHYSICAL_NETWORK:$OVS_PHYSICAL_BRIDGE
 
         # Configure bridge manually with physical interface as port for multi-node
@@ -65,7 +65,7 @@
     fi
     AGENT_BINARY="$NEUTRON_BIN_DIR/neutron-openvswitch-agent"
 
-    if [ "$VIRT_DRIVER" = 'xenserver' ]; then
+    if [ "$VIRT_DRIVER" == 'xenserver' ]; then
         # Make a copy of our config for domU
         sudo cp /$Q_PLUGIN_CONF_FILE "/$Q_PLUGIN_CONF_FILE.domu"
 
diff --git a/lib/neutron_plugins/plumgrid b/lib/neutron_plugins/plumgrid
index 67080f4..178bca7 100644
--- a/lib/neutron_plugins/plumgrid
+++ b/lib/neutron_plugins/plumgrid
@@ -24,14 +24,16 @@
     PLUMGRID_ADMIN=${PLUMGRID_ADMIN:-username}
     PLUMGRID_PASSWORD=${PLUMGRID_PASSWORD:-password}
     PLUMGRID_TIMEOUT=${PLUMGRID_TIMEOUT:-70}
+    PLUMGRID_DRIVER=${PLUMGRID_DRIVER:-neutron.plugins.plumgrid.drivers.fake_plumlib.Plumlib}
 }
 
 function neutron_plugin_configure_service {
-    iniset /$Q_PLUGIN_CONF_FILE PLUMgridDirector director_server $PLUMGRID_DIRECTOR_IP
-    iniset /$Q_PLUGIN_CONF_FILE PLUMgridDirector director_server_port $PLUMGRID_DIRECTOR_PORT
-    iniset /$Q_PLUGIN_CONF_FILE PLUMgridDirector username $PLUMGRID_ADMIN
-    iniset /$Q_PLUGIN_CONF_FILE PLUMgridDirector password $PLUMGRID_PASSWORD
-    iniset /$Q_PLUGIN_CONF_FILE PLUMgridDirector servertimeout $PLUMGRID_TIMEOUT
+    iniset /$Q_PLUGIN_CONF_FILE plumgriddirector director_server $PLUMGRID_DIRECTOR_IP
+    iniset /$Q_PLUGIN_CONF_FILE plumgriddirector director_server_port $PLUMGRID_DIRECTOR_PORT
+    iniset /$Q_PLUGIN_CONF_FILE plumgriddirector username $PLUMGRID_ADMIN
+    iniset /$Q_PLUGIN_CONF_FILE plumgriddirector password $PLUMGRID_PASSWORD
+    iniset /$Q_PLUGIN_CONF_FILE plumgriddirector servertimeout $PLUMGRID_TIMEOUT
+    iniset /$Q_PLUGIN_CONF_FILE plumgriddirector driver $PLUMGRID_DRIVER
 }
 
 function neutron_plugin_configure_debug_command {
diff --git a/lib/nova_plugins/functions-libvirt b/lib/nova_plugins/functions-libvirt
index 1f2b239..f435456 100644
--- a/lib/nova_plugins/functions-libvirt
+++ b/lib/nova_plugins/functions-libvirt
@@ -28,6 +28,23 @@
         install_package libvirt-python
         install_package python-libguestfs
     fi
+
+    # workaround for
+    # https://bugzilla.redhat.com/show_bug.cgi?id=1098376; if we see
+    # the empty Xen proc file then remove the xen/libxl plugin
+    # shared-libraries (yum remove would uninstall libvirt due to
+    # dependencies, so let's avoid that...)
+    if is_fedora && [ -f /proc/xen/capabilities ] && \
+        [ $(stat -c '%s' /proc/xen/capabilities) -eq 0 ]; then
+        sudo rm -f /usr/lib64/libvirt/connection-driver/libvirt_driver_libxl.so
+        sudo rm -f /usr/lib64/libvirt/connection-driver/libvirt_driver_xen.so
+
+        # another bug requires these to be restarted to avoid
+        # potential hang of libvirtd
+        # https://bugzilla.redhat.com/show_bug.cgi?id=1098866
+        sudo service dbus restart
+        sudo service firewalld restart
+    fi
 }
 
 # Configures the installed libvirt system so that is accessible by
diff --git a/lib/nova_plugins/hypervisor-baremetal b/lib/nova_plugins/hypervisor-baremetal
index 2da1097..1d4d414 100644
--- a/lib/nova_plugins/hypervisor-baremetal
+++ b/lib/nova_plugins/hypervisor-baremetal
@@ -49,7 +49,7 @@
     iniset $NOVA_CONF DEFAULT scheduler_host_manager nova.scheduler.baremetal_host_manager.BaremetalHostManager
     iniset $NOVA_CONF DEFAULT ram_allocation_ratio 1.0
     iniset $NOVA_CONF DEFAULT reserved_host_memory_mb 0
-    iniset $NOVA_CONF baremetal instance_type_extra_specs cpu_arch:$BM_CPU_ARCH
+    iniset $NOVA_CONF baremetal flavor_extra_specs cpu_arch:$BM_CPU_ARCH
     iniset $NOVA_CONF baremetal driver $BM_DRIVER
     iniset $NOVA_CONF baremetal power_manager $BM_POWER_MANAGER
     iniset $NOVA_CONF baremetal tftp_root /tftpboot
diff --git a/lib/nova_plugins/hypervisor-libvirt b/lib/nova_plugins/hypervisor-libvirt
index a868330..259bf15 100644
--- a/lib/nova_plugins/hypervisor-libvirt
+++ b/lib/nova_plugins/hypervisor-libvirt
@@ -41,7 +41,7 @@
     configure_libvirt
     iniset $NOVA_CONF libvirt virt_type "$LIBVIRT_TYPE"
     iniset $NOVA_CONF libvirt cpu_mode "none"
-    iniset $NOVA_CONF DEFAULT use_usb_tablet "False"
+    iniset $NOVA_CONF libvirt use_usb_tablet "False"
     iniset $NOVA_CONF DEFAULT default_ephemeral_format "ext4"
     iniset $NOVA_CONF DEFAULT compute_driver "libvirt.LibvirtDriver"
     LIBVIRT_FIREWALL_DRIVER=${LIBVIRT_FIREWALL_DRIVER:-"nova.virt.libvirt.firewall.IptablesFirewallDriver"}
diff --git a/lib/sahara b/lib/sahara
index 55131f9..d56cf1b 100644
--- a/lib/sahara
+++ b/lib/sahara
@@ -166,7 +166,7 @@
 
 # start_sahara() - Start running processes, including screen
 function start_sahara {
-    screen_it sahara "cd $SAHARA_DIR && $SAHARA_BIN_DIR/sahara-api --config-file $SAHARA_CONF_FILE"
+    screen_it sahara "cd $SAHARA_DIR && $SAHARA_BIN_DIR/sahara-all --config-file $SAHARA_CONF_FILE"
 }
 
 # stop_sahara() - Stop running processes
diff --git a/lib/swift b/lib/swift
index 6db779a..1e24c2c 100644
--- a/lib/swift
+++ b/lib/swift
@@ -103,6 +103,10 @@
 # trace through the logs when looking for its use.
 SWIFT_LOG_TOKEN_LENGTH=${SWIFT_LOG_TOKEN_LENGTH:-12}
 
+# Set ``SWIFT_MAX_HEADER_SIZE`` to configure the maximun length of headers in
+# Swift API
+SWIFT_MAX_HEADER_SIZE=${SWIFT_MAX_HEADER_SIZE:-16384}
+
 # Set ``OBJECT_PORT_BASE``, ``CONTAINER_PORT_BASE``, ``ACCOUNT_PORT_BASE``
 # Port bases used in port number calclution for the service "nodes"
 # The specified port number will be used, the additinal ports calculated by
@@ -404,6 +408,7 @@
 
     cp ${SWIFT_DIR}/etc/swift.conf-sample ${SWIFT_CONF_DIR}/swift.conf
     iniset ${SWIFT_CONF_DIR}/swift.conf swift-hash swift_hash_path_suffix ${SWIFT_HASH}
+    iniset ${SWIFT_CONF_DIR}/swift.conf swift-constraints max_header_size ${SWIFT_MAX_HEADER_SIZE}
 
     for node_number in ${SWIFT_REPLICAS_SEQ}; do
         swift_node_config=${SWIFT_CONF_DIR}/object-server/${node_number}.conf
diff --git a/lib/tempest b/lib/tempest
index 81eeba3..e899443 100644
--- a/lib/tempest
+++ b/lib/tempest
@@ -76,7 +76,6 @@
     local num_images
     local image_uuid
     local image_uuid_alt
-    local errexit
     local password
     local line
     local flavors
@@ -89,14 +88,6 @@
     local boto_instance_type="m1.tiny"
     local ssh_connect_method="fixed"
 
-    # TODO(afazekas):
-    # sudo python setup.py deploy
-
-    # This function exits on an error so that errors don't compound and you see
-    # only the first error that occurred.
-    errexit=$(set +o | grep errexit)
-    set -o errexit
-
     # Save IFS
     ifs=$IFS
 
@@ -383,8 +374,6 @@
 
     # Restore IFS
     IFS=$ifs
-    #Restore errexit
-    $errexit
 }
 
 # create_tempest_accounts() - Set up common required tempest accounts
@@ -414,6 +403,7 @@
 # install_tempest() - Collect source and prepare
 function install_tempest {
     git_clone $TEMPEST_REPO $TEMPEST_DIR $TEMPEST_BRANCH
+    pip_install "tox<1.7"
 }
 
 # init_tempest() - Initialize ec2 images
diff --git a/lib/trove b/lib/trove
index 42d2219..8631470 100644
--- a/lib/trove
+++ b/lib/trove
@@ -21,8 +21,11 @@
 
 # Defaults
 # --------
-
-NETWORK_GATEWAY=${NETWORK_GATEWAY:-10.0.0.1}
+if is_service_enabled neutron; then
+    TROVE_HOST_GATEWAY=${PUBLIC_NETWORK_GATEWAY:-172.24.4.1}
+else
+    TROVE_HOST_GATEWAY=${NETWORK_GATEWAY:-10.0.0.1}
+fi
 
 # Set up default configuration
 TROVE_DIR=$DEST/trove
@@ -152,7 +155,7 @@
     iniset $TROVE_CONF_DIR/trove.conf DEFAULT swift_url http://$SERVICE_HOST:8080/v1/AUTH_
 
     iniset $TROVE_LOCAL_CONF_DIR/trove-guestagent.conf.sample DEFAULT rabbit_password $RABBIT_PASSWORD
-    sed -i "s/localhost/$NETWORK_GATEWAY/g" $TROVE_LOCAL_CONF_DIR/trove-guestagent.conf.sample
+    sed -i "s/localhost/$TROVE_HOST_GATEWAY/g" $TROVE_LOCAL_CONF_DIR/trove-guestagent.conf.sample
 
     setup_trove_logging $TROVE_CONF_DIR/trove.conf
     setup_trove_logging $TROVE_LOCAL_CONF_DIR/trove-guestagent.conf.sample
diff --git a/stack.sh b/stack.sh
index dff6bd3..8fb57c4 100755
--- a/stack.sh
+++ b/stack.sh
@@ -150,7 +150,7 @@
 fi
 
 # Look for obsolete stuff
-if [[ ,${ENABLED_SERVICES} =~ ,"swift" ]]; then
+if [[ ,${ENABLED_SERVICES}, =~ ,"swift", ]]; then
     echo "FATAL: 'swift' is not supported as a service name"
     echo "FATAL: Use the actual swift service names to enable tham as required:"
     echo "FATAL: s-proxy s-object s-container s-account"
@@ -410,7 +410,7 @@
             echo "Invalid chars in password.  Try again:"
         done
         if [ ! $pw ]; then
-            pw=`openssl rand -hex 10`
+            pw=$(cat /dev/urandom | tr -cd 'a-f0-9' | head -c 20)
         fi
         eval "$var=$pw"
         echo "$var=$pw" >> $localrc
@@ -494,14 +494,18 @@
     done
 }
 
+function kill_spinner {
+    if [ ! -z "$LAST_SPINNER_PID" ]; then
+        kill >/dev/null 2>&1 $LAST_SPINNER_PID
+        printf "\b\b\bdone\n" >&3
+    fi
+}
+
 # Echo text to the log file, summary log file and stdout
 # echo_summary "something to say"
 function echo_summary {
     if [[ -t 3 && "$VERBOSE" != "True" ]]; then
-        kill >/dev/null 2>&1 $LAST_SPINNER_PID
-        if [ ! -z "$LAST_SPINNER_PID" ]; then
-            printf "\b\b\bdone\n" >&3
-        fi
+        kill_spinner
         echo -n -e $@ >&6
         spinner &
         LAST_SPINNER_PID=$!
@@ -539,10 +543,11 @@
 
     # Redirect output according to config
 
-    # Copy stdout to fd 3
+    # Set fd 3 to a copy of stdout. So we can set fd 1 without losing
+    # stdout later.
     exec 3>&1
     if [[ "$VERBOSE" == "True" ]]; then
-        # Redirect stdout/stderr to tee to write the log file
+        # Set fd 1 and 2 to write the log file
         exec 1> >( awk -v logfile=${LOGFILE} '
                 /((set \+o$)|xtrace)/ { next }
                 {
@@ -555,7 +560,7 @@
                     print
                     fflush("")
                 }' ) 2>&1
-        # Set up a second fd for output
+        # Set fd 6 to summary log file
         exec 6> >( tee "${SUMFILE}" )
     else
         # Set fd 1 and 2 to primary logfile
@@ -570,7 +575,8 @@
     ln -sf $SUMFILE $LOGDIR/$LOGFILENAME.summary
 else
     # Set up output redirection without log files
-    # Copy stdout to fd 3
+    # Set fd 3 to a copy of stdout. So we can set fd 1 without losing
+    # stdout later.
     exec 3>&1
     if [[ "$VERBOSE" != "True" ]]; then
         # Throw away stdout and stderr
@@ -612,6 +618,10 @@
         echo "exit_trap: cleaning up child processes"
         kill 2>&1 $jobs
     fi
+
+    # Kill the last spinner process
+    kill_spinner
+
     exit $r
 }
 
diff --git a/tools/create_userrc.sh b/tools/create_userrc.sh
index 47da334..5c1c329 100755
--- a/tools/create_userrc.sh
+++ b/tools/create_userrc.sh
@@ -34,7 +34,7 @@
 -P include password to the rc files; with -A it assume all users password is the same
 -A try with all user
 -u <username> create files just for the specified user
--C <tanent_name> create user and tenant, the specifid tenant will be the user's tenant
+-C <tenant_name> create user and tenant, the specifid tenant will be the user's tenant
 -r <name> when combined with -C and the (-u) user exists it will be the user's tenant role in the (-C)tenant (default: Member)
 -p <userpass> password for the user
 --os-username <username>
@@ -62,8 +62,8 @@
 
 # The services users usually in the service tenant.
 # rc files for service users, is out of scope.
-# Supporting different tanent for services is out of scope.
-SKIP_TENANT=",service," # tenant names are between commas(,)
+# Supporting different tenant for services is out of scope.
+SKIP_TENANT="service"
 MODE=""
 ROLE=Member
 USER_NAME=""
@@ -126,15 +126,15 @@
 
 export -n SERVICE_TOKEN SERVICE_ENDPOINT OS_SERVICE_TOKEN OS_SERVICE_ENDPOINT
 
-EC2_URL=http://localhost:8773/service/Cloud
-S3_URL=http://localhost:3333
+EC2_URL=`openstack endpoint show ec2 | grep " ec2.publicURL " | cut -d " " -f4`
+if [[ -z $EC2_URL ]]; then
+    EC2_URL=http://localhost:8773/service/Cloud
+fi
 
-ec2=`keystone endpoint-get --service ec2 | awk '/\|[[:space:]]*ec2.publicURL/ {print $4}'`
-[ -n "$ec2" ] && EC2_URL=$ec2
-
-s3=`keystone endpoint-get --service s3 | awk '/\|[[:space:]]*s3.publicURL/ {print $4}'`
-[ -n "$s3" ] && S3_URL=$s3
-
+S3_URL=`openstack endpoint show s3 | grep " s3.publicURL " | cut -d " " -f4`
+if [[ -z $S3_URL ]]; then
+    S3_URL=http://localhost:3333
+fi
 
 mkdir -p "$ACCOUNT_DIR"
 ACCOUNT_DIR=`readlink -f "$ACCOUNT_DIR"`
@@ -158,13 +158,13 @@
     local user_passwd=$5
 
     # The admin user can see all user's secret AWS keys, it does not looks good
-    local line=`keystone ec2-credentials-list --user_id $user_id | grep -E "^\\|[[:space:]]*($tenant_name|$tenant_id)[[:space:]]*\\|" | head -n 1`
+    local line=`openstack ec2 credentials list --user $user_id | grep " $tenant_id "`
     if [ -z "$line" ]; then
-        keystone ec2-credentials-create --user-id $user_id --tenant-id $tenant_id 1>&2
-        line=`keystone ec2-credentials-list --user_id $user_id | grep -E "^\\|[[:space:]]*($tenant_name|$tenant_id)[[:space:]]*\\|" | head -n 1`
+        openstack ec2 credentials create --user $user_id --project $tenant_id 1>&2
+        line=`openstack ec2 credentials list --user $user_id | grep " $tenant_id "`
     fi
     local ec2_access_key ec2_secret_key
-    read ec2_access_key ec2_secret_key <<<  `echo $line | awk '{print $4 " " $6 }'`
+    read ec2_access_key ec2_secret_key <<<  `echo $line | awk '{print $2 " " $4 }'`
     mkdir -p "$ACCOUNT_DIR/$tenant_name"
     local rcfile="$ACCOUNT_DIR/$tenant_name/$user_name"
     # The certs subject part are the tenant ID "dash" user ID, but the CN should be the first part of the DN
@@ -212,41 +212,35 @@
 }
 
 #admin users expected
-function create_or_get_tenant {
-    local tenant_name=$1
-    local tenant_id=`keystone tenant-list | awk '/\|[[:space:]]*'"$tenant_name"'[[:space:]]*\|.*\|/ {print $2}'`
-    if [ -n "$tenant_id" ]; then
-        echo $tenant_id
-    else
-        keystone tenant-create --name "$tenant_name" | awk '/\|[[:space:]]*id[[:space:]]*\|.*\|/ {print $4}'
+function create_or_get_project {
+    local name=$1
+    local id
+    eval $(openstack project show -f shell -c id $name)
+    if [[ -z $id ]]; then
+        eval $(openstack project create -f shell -c id $name)
     fi
+    echo $id
 }
 
 function create_or_get_role {
-    local role_name=$1
-    local role_id=`keystone role-list| awk '/\|[[:space:]]*'"$role_name"'[[:space:]]*\|/ {print $2}'`
-    if [ -n "$role_id" ]; then
-        echo $role_id
-    else
-        keystone role-create --name "$role_name" |awk '/\|[[:space:]]*id[[:space:]]*\|.*\|/ {print $4}'
+    local name=$1
+    local id
+    eval $(openstack role show -f shell -c id $name)
+    if [[ -z $id ]]; then
+        eval $(openstack role create -f shell -c id $name)
     fi
+    echo $id
 }
 
 # Provides empty string when the user does not exists
 function get_user_id {
-    local user_name=$1
-    keystone user-list | awk '/^\|[^|]*\|[[:space:]]*'"$user_name"'[[:space:]]*\|.*\|/ {print $2}'
+    openstack user list | grep " $1 " | cut -d " " -f2
 }
 
 if [ $MODE != "create" ]; then
-# looks like I can't ask for all tenant related to a specified  user
-    for tenant_id_at_name in `keystone tenant-list | awk 'BEGIN {IGNORECASE = 1} /true[[:space:]]*\|$/ {print  $2 "@" $4}'`; do
-        read tenant_id tenant_name <<< `echo "$tenant_id_at_name" | sed 's/@/ /'`
-        if echo $SKIP_TENANT| grep -q ",$tenant_name,"; then
-            continue;
-        fi
-        for user_id_at_name in `keystone user-list --tenant-id $tenant_id | awk 'BEGIN {IGNORECASE = 1} /true[[:space:]]*\|[^|]*\|$/ {print  $2 "@" $4}'`; do
-            read user_id user_name <<< `echo "$user_id_at_name" | sed 's/@/ /'`
+# looks like I can't ask for all tenant related to a specified user
+    openstack project list --long --quote none -f csv | grep ',True' | grep -v "${SKIP_TENANT}" | while IFS=, read tenant_id tenant_name desc enabled; do
+        openstack user list --project $tenant_id --long --quote none -f csv | grep ',True' | while IFS=, read user_id user_name project email enabled; do
             if [ $MODE = one -a "$user_name" != "$USER_NAME" ]; then
                 continue;
             fi
@@ -263,18 +257,16 @@
     done
 else
     tenant_name=$TENANT
-    tenant_id=`create_or_get_tenant "$TENANT"`
+    tenant_id=$(create_or_get_project "$TENANT")
     user_name=$USER_NAME
     user_id=`get_user_id $user_name`
     if [ -z "$user_id" ]; then
-        #new user
-        user_id=`keystone user-create --name "$user_name" --tenant-id "$tenant_id" --pass "$USER_PASS" --email "$user_name@example.com" | awk '/\|[[:space:]]*id[[:space:]]*\|.*\|/ {print $4}'`
-        #The password is in the cmd line. It is not a good thing
+        eval $(openstack user create "$user_name" --project "$tenant_id" --password "$USER_PASS" --email "$user_name@example.com" -f shell -c id)
+        user_id=$id
         add_entry "$user_id" "$user_name" "$tenant_id" "$tenant_name" "$USER_PASS"
     else
-        #new role
-        role_id=`create_or_get_role "$ROLE"`
-        keystone user-role-add --user-id "$user_id" --tenant-id "$tenant_id" --role-id "$role_id"
+        role_id=$(create_or_get_role "$ROLE")
+        openstack role add "$role_id" --user "$user_id" --project "$tenant_id"
         add_entry "$user_id" "$user_name" "$tenant_id" "$tenant_name" "$USER_PASS"
     fi
 fi
diff --git a/tools/fixup_stuff.sh b/tools/fixup_stuff.sh
index 7833278..e6a6a79 100755
--- a/tools/fixup_stuff.sh
+++ b/tools/fixup_stuff.sh
@@ -145,4 +145,11 @@
     # work unmolested.
     sudo ln -sf /usr/bin/nosetests1.1 /usr/local/bin/nosetests
 
+    # workaround for https://code.google.com/p/unittest-ext/issues/detail?id=79
+    install_package python-unittest2 patch
+    pip_install discover
+    (cd /usr/lib/python2.6/site-packages/; sudo patch <"$FILES/patches/unittest2-discover.patch" || echo 'Assume already applied')
+    # Make sure the discover.pyc is up to date
+    sudo rm /usr/lib/python2.6/site-packages/discover.pyc || true
+    sudo python -c 'import discover'
 fi
diff --git a/tools/ironic/scripts/configure-vm b/tools/ironic/scripts/configure-vm
index 9936b76..4c42c49 100755
--- a/tools/ironic/scripts/configure-vm
+++ b/tools/ironic/scripts/configure-vm
@@ -9,6 +9,25 @@
                            'templates')
 
 
+CONSOLE_LOG = """
+    <serial type='file'>
+      <source path='%(console_log)s'/>
+      <target port='0'/>
+      <alias name='serial0'/>
+    </serial>
+    <serial type='pty'>
+      <source path='/dev/pts/49'/>
+      <target port='1'/>
+      <alias name='serial1'/>
+    </serial>
+    <console type='file'>
+      <source path='%(console_log)s'/>
+      <target type='serial' port='0'/>
+      <alias name='serial0'/>
+    </console>
+"""
+
+
 def main():
     parser = argparse.ArgumentParser(
         description="Configure a kvm virtual machine for the seed image.")
@@ -30,6 +49,8 @@
                         help='The libvirt network name to use')
     parser.add_argument('--libvirt-nic-driver', default='e1000',
                         help='The libvirt network driver to use')
+    parser.add_argument('--console-log',
+                        help='File to log console')
     parser.add_argument('--emulator', default=None,
                         help='Path to emulator bin for vm template')
     args = parser.parse_args()
@@ -44,6 +65,7 @@
         'cpus': args.cpus,
         'bootdev': args.bootdev,
         'network': args.network,
+        'nicdriver': args.libvirt_nic_driver,
         'emulator': args.emulator,
     }
 
@@ -55,22 +77,13 @@
         elif os.path.exists("/usr/bin/qemu-kvm"):  # Redhat
             params['emulator'] = "/usr/bin/qemu-kvm"
 
-    nicparams = {
-        'nicdriver': args.libvirt_nic_driver,
-        'network': args.network,
-    }
-
-    params['bm_network'] = """
-<!-- neutron friendly 'bare metal' network -->
-<interface type='network'>
-  <source network='%(network)s'/>
-  <virtualport type='openvswitch'/>
-  <model type='%(nicdriver)s'/>
-  <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/>
-</interface>""" % nicparams
-
+    if args.console_log:
+        params['console_log'] = CONSOLE_LOG % {'console_log': args.console_log}
+    else:
+        params['console_log'] = ''
     libvirt_template = source_template % params
     conn = libvirt.open("qemu:///system")
+
     a = conn.defineXML(libvirt_template)
     print ("Created machine %s with UUID %s" % (args.name, a.UUIDString()))
 
diff --git a/tools/ironic/scripts/create-nodes b/tools/ironic/scripts/create-nodes
index d81113a..140bffe 100755
--- a/tools/ironic/scripts/create-nodes
+++ b/tools/ironic/scripts/create-nodes
@@ -4,7 +4,7 @@
 
 # Creates baremetal poseur nodes for ironic testing purposes
 
-set -exu
+set -ex
 
 # Keep track of the devstack directory
 TOP_DIR=$(cd $(dirname "$0")/.. && pwd)
@@ -24,6 +24,7 @@
 TOTAL=$(($5 - 1))
 BRIDGE=$6
 EMULATOR=$7
+LOGDIR=$8
 
 LIBVIRT_NIC_DRIVER=${LIBVIRT_NIC_DRIVER:-"e1000"}
 LIBVIRT_STORAGE_POOL=${LIBVIRT_STORAGE_POOL:-"default"}
@@ -43,6 +44,10 @@
   virsh pool-start $LIBVIRT_STORAGE_POOL >&2
 fi
 
+if [ -n "$LOGDIR" ] ; then
+  mkdir -p "$LOGDIR"
+fi
+
 PREALLOC=
 if [ -f /etc/debian_version ]; then
     PREALLOC="--prealloc-metadata"
@@ -51,6 +56,11 @@
 DOMS=""
 for idx in $(seq 0 $TOTAL) ; do
     NAME="baremetal${BRIDGE}_${idx}"
+    if [ -n "$LOGDIR" ] ; then
+      VM_LOGGING="--console-log $LOGDIR/${NAME}_console.log"
+    else
+      VM_LOGGING=""
+    fi
     DOMS="$DOMS $NAME"
     VOL_NAME="baremetal${BRIDGE}-${idx}.qcow2"
     (virsh list --all | grep -q $NAME) && continue
@@ -62,7 +72,10 @@
     # Pre-touch the VM to set +C, as it can only be set on empty files.
     sudo touch "$volume_path"
     sudo chattr +C "$volume_path" || true
-    $TOP_DIR/scripts/configure-vm --bootdev network --name $NAME --image "$volume_path" --arch $ARCH --cpus $CPU --memory $MEM --libvirt-nic-driver $LIBVIRT_NIC_DRIVER --emulator $EMULATOR --network $BRIDGE >&2
+    $TOP_DIR/scripts/configure-vm \
+      --bootdev network --name $NAME --image "$volume_path" \
+      --arch $ARCH --cpus $CPU --memory $MEM --libvirt-nic-driver $LIBVIRT_NIC_DRIVER \
+      --emulator $EMULATOR --network $BRIDGE $VM_LOGGING >&2
 done
 
 for dom in $DOMS ; do
diff --git a/tools/ironic/templates/tftpd-xinetd.template b/tools/ironic/templates/tftpd-xinetd.template
index 7b9b0f8..5f3d03f 100644
--- a/tools/ironic/templates/tftpd-xinetd.template
+++ b/tools/ironic/templates/tftpd-xinetd.template
@@ -8,4 +8,7 @@
   server          = /usr/sbin/in.tftpd
   server_args     = -v -v -v -v -v --map-file %TFTPBOOT_DIR%/map-file %TFTPBOOT_DIR%
   disable         = no
+  # This is a workaround for Fedora, where TFTP will listen only on
+  # IPv6 endpoint, if IPv4 flag is not used.
+  flags           = IPv4
 }
diff --git a/tools/ironic/templates/vm.xml b/tools/ironic/templates/vm.xml
index b18dec0..4f40334 100644
--- a/tools/ironic/templates/vm.xml
+++ b/tools/ironic/templates/vm.xml
@@ -27,14 +27,19 @@
     <controller type='ide' index='0'>
       <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/>
     </controller>
-    %(network)s
-    %(bm_network)s
+    <interface type='network'>
+      <source network='%(network)s'/>
+      <virtualport type='openvswitch'/>
+      <model type='%(nicdriver)s'/>
+      <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/>
+    </interface>
     <input type='mouse' bus='ps2'/>
     <graphics type='vnc' port='-1' autoport='yes'/>
     <video>
       <model type='cirrus' vram='9216' heads='1'/>
       <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/>
     </video>
+    %(console_log)s
     <memballoon model='virtio'>
       <address type='pci' domain='0x0000' bus='0x00' slot='0x07' function='0x0'/>
     </memballoon>