Merge "Update create_userrc to openstackclient commands"
diff --git a/README.md b/README.md
index 89e3855..f9a996e 100644
--- a/README.md
+++ b/README.md
@@ -124,7 +124,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
 
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/extras.d/80-opendaylight.sh b/extras.d/80-opendaylight.sh
index c3c85fc..bf99866 100644
--- a/extras.d/80-opendaylight.sh
+++ b/extras.d/80-opendaylight.sh
@@ -47,7 +47,11 @@
         ODL_MGR_PORT=${ODL_MGR_PORT:-6640}
         read ovstbl <<< $(sudo ovs-vsctl get Open_vSwitch . _uuid)
         sudo ovs-vsctl set-manager tcp:$ODL_MGR_IP:$ODL_MGR_PORT
-        sudo ovs-vsctl set Open_vSwitch $ovstbl other_config={"local_ip"="$ODL_LOCAL_IP"}
+        if [[ -n "$OVS_BRIDGE_MAPPINGS" ]] && [[ "$ENABLE_TENANT_VLANS" == "True" ]]; then
+            sudo ovs-vsctl set Open_vSwitch $ovstbl \
+                other_config:bridge_mappings=$OVS_BRIDGE_MAPPINGS
+        fi
+        sudo ovs-vsctl set Open_vSwitch $ovstbl other_config:local_ip=$ODL_LOCAL_IP
     elif [[ "$1" == "stack" && "$2" == "post-extra" ]]; then
         # no-op
         :
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/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/neutron b/files/rpms-suse/neutron
index 462513d..d4841b1 100644
--- a/files/rpms-suse/neutron
+++ b/files/rpms-suse/neutron
@@ -1,5 +1,5 @@
 dnsmasq
-dnsmasq-utils # dist:opensuse-12.3
+dnsmasq-utils # dist:opensuse-12.3,opensuse-13.1
 ebtables
 iptables
 iputils
diff --git a/files/rpms-suse/nova b/files/rpms-suse/nova
index c5a58b9..3e95724 100644
--- a/files/rpms-suse/nova
+++ b/files/rpms-suse/nova
@@ -1,6 +1,6 @@
 curl
 dnsmasq
-dnsmasq-utils # dist:opensuse-12.3
+dnsmasq-utils # dist:opensuse-12.3,opensuse-13.1
 ebtables
 gawk
 genisoimage # required for config_drive
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/functions-common b/functions-common
index 6340c5c..cc90c07 100644
--- a/functions-common
+++ b/functions-common
@@ -1231,9 +1231,9 @@
 
     $xtrace
     $SUDO_PIP PIP_DOWNLOAD_CACHE=${PIP_DOWNLOAD_CACHE:-/var/cache/pip} \
-        HTTP_PROXY=$http_proxy \
-        HTTPS_PROXY=$https_proxy \
-        NO_PROXY=$no_proxy \
+        http_proxy=$http_proxy \
+        https_proxy=$https_proxy \
+        no_proxy=$no_proxy \
         $CMD_PIP install --build=${pip_build_tmp} \
         $PIP_MIRROR_OPT $@ \
         && $SUDO_PIP rm -rf ${pip_build_tmp}
diff --git a/lib/ceilometer b/lib/ceilometer
index 5030b3c..59f572c 100644
--- a/lib/ceilometer
+++ b/lib/ceilometer
@@ -155,10 +155,11 @@
     fi
 
     # the compute and central agents need these credentials in order to
-    # call out to the public nova and glance APIs
-    iniset $CEILOMETER_CONF DEFAULT os_username ceilometer
-    iniset $CEILOMETER_CONF DEFAULT os_password $SERVICE_PASSWORD
-    iniset $CEILOMETER_CONF DEFAULT os_tenant_name $SERVICE_TENANT_NAME
+    # call out to other services' public APIs
+    # the alarm evaluator needs these options to call ceilometer APIs
+    iniset $CEILOMETER_CONF service_credentials os_username ceilometer
+    iniset $CEILOMETER_CONF service_credentials os_password $SERVICE_PASSWORD
+    iniset $CEILOMETER_CONF service_credentials os_tenant_name $SERVICE_TENANT_NAME
 
     iniset $CEILOMETER_CONF keystone_authtoken auth_host $KEYSTONE_AUTH_HOST
     iniset $CEILOMETER_CONF keystone_authtoken auth_port $KEYSTONE_AUTH_PORT
@@ -236,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 50c0fb6..389040c 100644
--- a/lib/ironic
+++ b/lib/ironic
@@ -42,29 +42,35 @@
 IRONIC_SCRIPTS_DIR=${IRONIC_SCRIPTS_DIR:-$TOP_DIR/tools/ironic/scripts}
 IRONIC_TEMPLATES_DIR=${IRONIC_TEMPLATES_DIR:-$TOP_DIR/tools/ironic/templates}
 IRONIC_BAREMETAL_BASIC_OPS=$(trueorfalse False $IRONIC_BAREMETAL_BASIC_OPS)
-IRONIC_DRIVERS_WHITELIST=${IRONIC_DRIVERS_WHITELIST:-fake,pxe_ssh}
+IRONIC_ENABLED_DRIVERS=${IRONIC_ENABLED_DRIVERS:-fake,pxe_ssh,pxe_ipmitool}
 IRONIC_SSH_USERNAME=${IRONIC_SSH_USERNAME:-`whoami`}
 IRONIC_SSH_KEY_DIR=${IRONIC_SSH_KEY_DIR:-$IRONIC_DATA_DIR/ssh_keys}
 IRONIC_SSH_KEY_FILENAME=${IRONIC_SSH_KEY_FILENAME:-ironic_key}
 IRONIC_KEY_FILE=$IRONIC_SSH_KEY_DIR/$IRONIC_SSH_KEY_FILENAME
 IRONIC_SSH_VIRT_TYPE=${IRONIC_SSH_VIRT_TYPE:-virsh}
 IRONIC_TFTPBOOT_DIR=${IRONIC_TFTPBOOT_DIR:-$IRONIC_DATA_DIR/tftpboot}
-IRONIC_VM_SSH_PORT=${IRONIC_VM_SSH_PORT:-2222}
+IRONIC_VM_SSH_PORT=${IRONIC_VM_SSH_PORT:-22}
 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.
@@ -170,13 +176,25 @@
 function configure_ironic_conductor {
     cp $IRONIC_DIR/etc/ironic/rootwrap.conf $IRONIC_ROOTWRAP_CONF
     cp -r $IRONIC_DIR/etc/ironic/rootwrap.d $IRONIC_CONF_DIR
+    IRONIC_ROOTWRAP=$(get_rootwrap_location ironic)
+    ROOTWRAP_ISUDOER_CMD="$IRONIC_ROOTWRAP $IRONIC_CONF_DIR/rootwrap.conf *"
+
+    # Set up the rootwrap sudoers for ironic
+    TEMPFILE=`mktemp`
+    echo "$STACK_USER ALL=(root) NOPASSWD: $ROOTWRAP_ISUDOER_CMD" >$TEMPFILE
+    chmod 0440 $TEMPFILE
+    sudo chown root:root $TEMPFILE
+    sudo mv $TEMPFILE /etc/sudoers.d/ironic-rootwrap
 
     iniset $IRONIC_CONF_FILE DEFAULT rootwrap_config $IRONIC_ROOTWRAP_CONF
-    iniset $IRONIC_CONF_FILE DEFAULT drivers_whitelist $IRONIC_DRIVERS_WHITELIST
+    iniset $IRONIC_CONF_FILE DEFAULT enabled_drivers $IRONIC_ENABLED_DRIVERS
     iniset $IRONIC_CONF_FILE conductor api_url http://$HOST_IP:6385
     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
@@ -306,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 {
@@ -346,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
@@ -370,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
@@ -423,31 +453,10 @@
     fi
 }
 
-function configure_ironic_sshd {
-    # Ensure sshd server accepts connections from localhost only
-
-    SSH_CONFIG=/etc/ssh/sshd_config
-    HOST_PORT=$IRONIC_VM_SSH_ADDRESS:$IRONIC_VM_SSH_PORT
-    if ! sudo grep ListenAddress $SSH_CONFIG | grep $HOST_PORT; then
-        echo "ListenAddress $HOST_PORT" | sudo tee -a $SSH_CONFIG
-    fi
-
-    SSH_SERVICE_NAME=sshd
-    if is_ubuntu; then
-        SSH_SERVICE_NAME=ssh
-    fi
-
-    restart_service $SSH_SERVICE_NAME
-    # to ensure ssh service is up and running
-    sleep 3
-    ironic_ssh_check $IRONIC_SSH_KEY_DIR/$IRONIC_SSH_KEY_FILENAME $IRONIC_VM_SSH_ADDRESS $IRONIC_VM_SSH_PORT $IRONIC_SSH_USERNAME 10
-
-}
-
 function configure_ironic_auxiliary {
     configure_ironic_dirs
     configure_ironic_ssh_keypair
-    configure_ironic_sshd
+    ironic_ssh_check $IRONIC_SSH_KEY_DIR/$IRONIC_SSH_KEY_FILENAME $IRONIC_VM_SSH_ADDRESS $IRONIC_VM_SSH_PORT $IRONIC_SSH_USERNAME 10
 }
 
 # build deploy kernel+ramdisk, then upload them to glance
@@ -518,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
@@ -537,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/marconi b/lib/marconi
index fd1c351..473c8cd 100644
--- a/lib/marconi
+++ b/lib/marconi
@@ -42,7 +42,7 @@
 MARCONI_BIN_DIR=$(get_python_exec_prefix)
 
 # Set up database backend
-MARCONI_BACKEND=${MARCONI_BACKEND:-mongodb}
+MARCONI_BACKEND=${MARCONI_BACKEND:-sqlite}
 
 
 # Set Marconi repository
@@ -109,8 +109,8 @@
     if [ "$MARCONI_BACKEND" = 'mysql' ] || [ "$MARCONI_BACKEND" = 'postgresql' ] ; then
         iniset $MARCONI_CONF drivers storage sqlalchemy
         iniset $MARCONI_CONF 'drivers:storage:sqlalchemy' uri `database_connection_url marconi`
-    else
-        iniset $MARCONI_CONF drivers storage mongodb
+    elif [ "$MARCONI_BACKEND" = 'mongodb' ] ; then
+        iniset $MARCONI_CONF  drivers storage mongodb
         iniset $MARCONI_CONF 'drivers:storage:mongodb' uri mongodb://localhost:27017/marconi
         configure_mongodb
         cleanup_marconi
@@ -154,7 +154,7 @@
 
 # start_marconi() - Start running processes, including screen
 function start_marconi {
-    screen_it marconi-server "marconi-server --config-file $MARCONI_CONF"
+    screen_it marconi-server "marconi-server --config-file $MARCONI_CONF --daemon"
     echo "Waiting for Marconi to start..."
     if ! timeout $SERVICE_TIMEOUT sh -c "while ! wget --no-proxy -q -O- $MARCONI_SERVICE_PROTOCOL://$MARCONI_SERVICE_HOST:$MARCONI_SERVICE_PORT/v1/health; do sleep 1; done"; then
         die $LINENO "Marconi did not start"
diff --git a/lib/neutron b/lib/neutron
index b7c9464..15cfa8e 100644
--- a/lib/neutron
+++ b/lib/neutron
@@ -127,6 +127,10 @@
 # See _configure_neutron_common() for details about setting it up
 declare -a Q_PLUGIN_EXTRA_CONF_FILES
 
+# List of (optional) config files for VPN device drivers to use with
+# the neutron-q-vpn agent
+declare -a Q_VPN_EXTRA_CONF_FILES
+
 
 Q_RR_CONF_FILE=$NEUTRON_CONF_DIR/rootwrap.conf
 if [[ "$Q_USE_ROOTWRAP" == "False" ]]; then
@@ -312,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"
@@ -493,9 +497,10 @@
 
     if is_service_enabled q-fwaas; then
         L3_CONF_FILES="$L3_CONF_FILES --config-file $Q_FWAAS_CONF_FILE"
+        VPN_CONF_FILES="$VPN_CONF_FILES --config-file $Q_FWAAS_CONF_FILE"
     fi
     if is_service_enabled q-vpn; then
-        screen_it q-vpn "cd $NEUTRON_DIR && $AGENT_VPN_BINARY $L3_CONF_FILES"
+        screen_it q-vpn "cd $NEUTRON_DIR && $AGENT_VPN_BINARY $VPN_CONF_FILES"
     else
         screen_it q-l3 "cd $NEUTRON_DIR && python $AGENT_L3_BINARY $L3_CONF_FILES"
     fi
@@ -658,6 +663,7 @@
 }
 
 function _configure_neutron_l3_agent {
+    local cfg_file
     Q_L3_ENABLED=True
     # for l3-agent, only use per tenant router if we have namespaces
     Q_L3_ROUTER_PER_TENANT=$Q_USE_NAMESPACE
@@ -669,6 +675,15 @@
         Q_FWAAS_CONF_FILE=$NEUTRON_CONF_DIR/fwaas_driver.ini
     fi
 
+    if is_service_enabled q-vpn; then
+        Q_VPN_CONF_FILE=$NEUTRON_CONF_DIR/vpn_agent.ini
+        cp $NEUTRON_DIR/etc/vpn_agent.ini $Q_VPN_CONF_FILE
+        VPN_CONF_FILES="--config-file $NEUTRON_CONF --config-file=$Q_L3_CONF_FILE --config-file=$Q_VPN_CONF_FILE"
+        for cfg_file in ${Q_VPN_EXTRA_CONF_FILES[@]}; do
+            VPN_CONF_FILES+=" --config-file $cfg_file"
+        done
+    fi
+
     cp $NEUTRON_DIR/etc/l3_agent.ini $Q_L3_CONF_FILE
 
     iniset $Q_L3_CONF_FILE DEFAULT verbose True
diff --git a/lib/neutron_plugins/brocade b/lib/neutron_plugins/brocade
index 4443fa7..e4cc754 100644
--- a/lib/neutron_plugins/brocade
+++ b/lib/neutron_plugins/brocade
@@ -24,6 +24,30 @@
     Q_PLUGIN_CLASS="neutron.plugins.brocade.NeutronPlugin.BrocadePluginV2"
 }
 
+function neutron_plugin_configure_service {
+
+    if [[ "$BROCADE_SWITCH_OS_VERSION" != "" ]]; then
+        iniset /$Q_PLUGIN_CONF_FILE switch osversion $BROCADE_SWITCH_OS_VERSION
+    fi
+
+    if [[ "$BROCADE_SWITCH_OS_TYPE" != "" ]]; then
+        iniset /$Q_PLUGIN_CONF_FILE switch ostype $BROCADE_SWITCH_OS_TYPE
+    fi
+
+    if [[ "$BROCADE_SWITCH_PASSWORD" != "" ]]; then
+        iniset /$Q_PLUGIN_CONF_FILE switch password $BROCADE_SWITCH_PASSWORD
+    fi
+
+    if [[ "$BROCADE_SWITCH_USERNAME" != "" ]]; then
+        iniset /$Q_PLUGIN_CONF_FILE switch username $BROCADE_SWITCH_USERNAME
+    fi
+
+    if [[ "$BROCADE_SWITCH_IPADDR" != "" ]]; then
+        iniset /$Q_PLUGIN_CONF_FILE switch address $BROCADE_SWITCH_IPADDR
+    fi
+
+}
+
 function neutron_plugin_configure_debug_command {
     iniset $NEUTRON_TEST_CONFIG_FILE DEFAULT external_network_bridge
 }
diff --git a/lib/neutron_plugins/openvswitch_agent b/lib/neutron_plugins/openvswitch_agent
index 33ca17a..3604a50 100644
--- a/lib/neutron_plugins/openvswitch_agent
+++ b/lib/neutron_plugins/openvswitch_agent
@@ -10,8 +10,8 @@
 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
+        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
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 b/lib/nova
index 47e4afc..c51d584 100644
--- a/lib/nova
+++ b/lib/nova
@@ -303,6 +303,10 @@
                 sudo chown -R $STACK_USER $NOVA_INSTANCES_PATH
             fi
         fi
+        if is_suse; then
+            # iscsid is not started by default
+            start_service iscsid
+        fi
     fi
 
     # Rebuild the config file from scratch
@@ -428,7 +432,6 @@
     iniset $NOVA_CONF DEFAULT default_floating_pool "$PUBLIC_NETWORK_NAME"
     iniset $NOVA_CONF DEFAULT s3_host "$SERVICE_HOST"
     iniset $NOVA_CONF DEFAULT s3_port "$S3_SERVICE_PORT"
-    iniset $NOVA_CONF DEFAULT osapi_compute_extension "nova.api.openstack.compute.contrib.standard_extensions"
     iniset $NOVA_CONF DEFAULT my_ip "$HOST_IP"
     iniset $NOVA_CONF DEFAULT osapi_compute_workers "4"
     iniset $NOVA_CONF DEFAULT ec2_workers "4"
@@ -468,9 +471,6 @@
 
     iniset $NOVA_CONF keystone_authtoken signing_dir $NOVA_AUTH_CACHE_DIR
 
-    if is_service_enabled cinder; then
-        iniset $NOVA_CONF DEFAULT volume_api_class "nova.volume.cinder.API"
-    fi
     if [ -n "$NOVA_STATE_PATH" ]; then
         iniset $NOVA_CONF DEFAULT state_path "$NOVA_STATE_PATH"
         iniset $NOVA_CONF DEFAULT lock_path "$NOVA_STATE_PATH"
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 053df3c..259bf15 100644
--- a/lib/nova_plugins/hypervisor-libvirt
+++ b/lib/nova_plugins/hypervisor-libvirt
@@ -39,9 +39,9 @@
 # configure_nova_hypervisor - Set config files, create data dirs, etc
 function configure_nova_hypervisor {
     configure_libvirt
-    iniset $NOVA_CONF DEFAULT libvirt_type "$LIBVIRT_TYPE"
-    iniset $NOVA_CONF DEFAULT libvirt_cpu_mode "none"
-    iniset $NOVA_CONF DEFAULT use_usb_tablet "False"
+    iniset $NOVA_CONF libvirt virt_type "$LIBVIRT_TYPE"
+    iniset $NOVA_CONF libvirt cpu_mode "none"
+    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 cb86710..d56cf1b 100644
--- a/lib/sahara
+++ b/lib/sahara
@@ -35,6 +35,8 @@
 
 SAHARA_AUTH_CACHE_DIR=${SAHARA_AUTH_CACHE_DIR:-/var/cache/sahara}
 
+SAHARA_ENABLED_PLUGINS=${SAHARA_ENABLED_PLUGINS:-vanilla,hdp,fake}
+
 # Support entry points installation of console scripts
 if [[ -d $SAHARA_DIR/bin ]]; then
     SAHARA_BIN_DIR=$SAHARA_DIR/bin
@@ -109,15 +111,18 @@
     rm -rf $SAHARA_AUTH_CACHE_DIR/*
 
     # Set obsolete keystone auth configs for backward compatibility
-    iniset $SAHARA_CONF_FILE DEFAULT os_auth_host $KEYSTONE_SERVICE_HOST
-    iniset $SAHARA_CONF_FILE DEFAULT os_auth_port $KEYSTONE_SERVICE_PORT
-    iniset $SAHARA_CONF_FILE DEFAULT os_auth_protocol $KEYSTONE_SERVICE_PROTOCOL
+    iniset $SAHARA_CONF_FILE DEFAULT os_auth_host $KEYSTONE_AUTH_HOST
+    iniset $SAHARA_CONF_FILE DEFAULT os_auth_port $KEYSTONE_AUTH_PORT
+    iniset $SAHARA_CONF_FILE DEFAULT os_auth_protocol $KEYSTONE_AUTH_PROTOCOL
     iniset $SAHARA_CONF_FILE DEFAULT os_admin_password $SERVICE_PASSWORD
     iniset $SAHARA_CONF_FILE DEFAULT os_admin_username sahara
     iniset $SAHARA_CONF_FILE DEFAULT os_admin_tenant_name $SERVICE_TENANT_NAME
 
     # Set actual keystone auth configs
     iniset $SAHARA_CONF_FILE keystone_authtoken auth_uri $KEYSTONE_SERVICE_PROTOCOL://$KEYSTONE_SERVICE_HOST:$KEYSTONE_SERVICE_PORT/
+    iniset $SAHARA_CONF_FILE keystone_authtoken auth_host $KEYSTONE_AUTH_HOST
+    iniset $SAHARA_CONF_FILE keystone_authtoken auth_port $KEYSTONE_AUTH_PORT
+    iniset $SAHARA_CONF_FILE keystone_authtoken auth_protocol $KEYSTONE_AUTH_PROTOCOL
     iniset $SAHARA_CONF_FILE keystone_authtoken admin_tenant_name $SERVICE_TENANT_NAME
     iniset $SAHARA_CONF_FILE keystone_authtoken admin_user sahara
     iniset $SAHARA_CONF_FILE keystone_authtoken admin_password $SERVICE_PASSWORD
@@ -127,6 +132,8 @@
     iniset $SAHARA_CONF_FILE DEFAULT verbose True
     iniset $SAHARA_CONF_FILE DEFAULT debug $ENABLE_DEBUG_LOG_LEVEL
 
+    iniset $SAHARA_CONF_FILE DEFAULT plugins $SAHARA_ENABLED_PLUGINS
+
     iniset $SAHARA_CONF_FILE database connection `database_connection_url sahara`
 
     if is_service_enabled neutron; then
@@ -159,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 3e183ff..6db779a 100644
--- a/lib/swift
+++ b/lib/swift
@@ -453,10 +453,13 @@
     rm -rf ${swift_log_dir}
     mkdir -p ${swift_log_dir}/hourly
     sudo chown -R ${STACK_USER}:adm ${swift_log_dir}
-    sed "s,%SWIFT_LOGDIR%,${swift_log_dir}," $FILES/swift/rsyslog.conf | sudo \
-        tee /etc/rsyslog.d/10-swift.conf
-    # restart syslog to take the changes
-    sudo killall -HUP rsyslogd
+
+    if [[ $SYSLOG != "False" ]]; then
+        sed "s,%SWIFT_LOGDIR%,${swift_log_dir}," $FILES/swift/rsyslog.conf | sudo \
+            tee /etc/rsyslog.d/10-swift.conf
+        # restart syslog to take the changes
+        sudo killall -HUP rsyslogd
+    fi
 
     if is_apache_enabled_service swift; then
         _config_swift_apache_wsgi
diff --git a/lib/tempest b/lib/tempest
index 5122695..e899443 100644
--- a/lib/tempest
+++ b/lib/tempest
@@ -28,7 +28,6 @@
 # - ``DEFAULT_INSTANCE_TYPE``
 # - ``DEFAULT_INSTANCE_USER``
 # - ``CINDER_MULTI_LVM_BACKEND``
-# - ``HEAT_CREATE_TEST_IMAGE``
 #
 # ``stack.sh`` calls the entry points in this order:
 #
@@ -77,7 +76,6 @@
     local num_images
     local image_uuid
     local image_uuid_alt
-    local errexit
     local password
     local line
     local flavors
@@ -90,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
 
@@ -384,8 +374,6 @@
 
     # Restore IFS
     IFS=$ifs
-    #Restore errexit
-    $errexit
 }
 
 # create_tempest_accounts() - Set up common required tempest accounts
@@ -415,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/stack.sh b/stack.sh
index dff6bd3..19d47d6 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"
@@ -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/stackrc b/stackrc
index f6403cc..822403e 100644
--- a/stackrc
+++ b/stackrc
@@ -330,8 +330,8 @@
         esac
         ;;
     vsphere)
-        DEFAULT_IMAGE_NAME=${DEFAULT_IMAGE_NAME:-debian-2.6.32-i686}
-        IMAGE_URLS=${IMAGE_URLS:-"http://partnerweb.vmware.com/programs/vmdkimage/cirros-0.3.0-i386-disk.vmdk"};;
+        DEFAULT_IMAGE_NAME=${DEFAULT_IMAGE_NAME:-cirros-0.3.2-i386-disk.vmdk}
+        IMAGE_URLS=${IMAGE_URLS:-"http://partnerweb.vmware.com/programs/vmdkimage/cirros-0.3.2-i386-disk.vmdk"};;
     xenserver)
         DEFAULT_IMAGE_NAME=${DEFAULT_IMAGE_NAME:-cirros-0.3.0-x86_64-disk}
         IMAGE_URLS=${IMAGE_URLS:-"https://github.com/downloads/citrix-openstack/warehouse/cirros-0.3.0-x86_64-disk.vhd.tgz"};;
@@ -340,22 +340,24 @@
         IMAGE_URLS=${IMAGE_URLS:-"http://download.cirros-cloud.net/0.3.1/cirros-0.3.1-x86_64-uec.tar.gz"};;
 esac
 
-# if heat is enabled, bring in a linux image with cfn enabled
-# TODO(sdague) this next block can be removed after nodepool has the 64bit image in it's cache
-HEAT_FETCHED_TEST_IMAGE=${HEAT_FETCHED_TEST_IMAGE:-""}
-if [[ "$HEAT_FETCHED_TEST_IMAGE" == "Fedora-i386-20-20131211.1-sda" ]]; then
-    HEAT_CFN_IMAGE_URL="https://dl.fedoraproject.org/pub/fedora/linux/releases/20/Images/i386/$HEAT_FETCHED_TEST_IMAGE.qcow2"
-    IMAGE_URLS+=",https://dl.fedoraproject.org/pub/fedora/linux/releases/20/Images/i386/$HEAT_FETCHED_TEST_IMAGE.qcow2"
-elif [[ "$HEAT_FETCHED_TEST_IMAGE" == "Fedora-x86_64-20-20131211.1-sda" ]]; then
-    HEAT_CFN_IMAGE_URL="https://download.fedoraproject.org/pub/fedora/linux/releases/20/Images/x86_64/Fedora-x86_64-20-20131211.1-sda.qcow2"
-    IMAGE_URLS+=",https://download.fedoraproject.org/pub/fedora/linux/releases/20/Images/x86_64/Fedora-x86_64-20-20131211.1-sda.qcow2"
+# Use 64bit fedora image if heat is enabled
+if [[ "$ENABLED_SERVICES" =~ 'h-api' ]]; then
+    case "$VIRT_DRIVER" in
+        libvirt|baremetal|ironic)
+            HEAT_CFN_IMAGE_URL=${HEAT_CFN_IMAGE_URL:-"https://dl.fedoraproject.org/pub/fedora/linux/releases/20/Images/x86_64/Fedora-x86_64-20-20131211.1-sda.qcow2"}
+            IMAGE_URLS+=",$HEAT_CFN_IMAGE_URL"
+            ;;
+        *)
+            ;;
+    esac
 fi
-
-# Uncomment after nodepool changes land
-#if [[ "$ENABLED_SERVICES" =~ 'h-api' ]]; then
-#    HEAT_CFN_IMAGE_URL=${HEAT_CFN_IMAGE_URL:-"https://download.fedoraproject.org/pub/fedora/linux/releases/20/Images/x86_64/Fedora-x86_64-20-20131211.1-sda.qcow2"}
-#    IMAGE_URLS+=",$HEAT_CFN_IMAGE_URL"
-#fi
+# Staging Area for New Images, have them here for at least 24hrs for nodepool
+# to cache them otherwise the failure rates in the gate are too high
+PRECACHE_IMAGES=$(trueorfalse False $PRECACHE_IMAGES)
+if [[ "$PRECACHE_IMAGES" == "True" ]]; then
+    # staging in update for nodepool
+    IMAGE_URLS+=",https://dl.fedoraproject.org/pub/fedora/linux/updates/20/Images/x86_64/Fedora-x86_64-20-20140407-sda.qcow2"
+fi
 
 # 10Gb default volume backing file size
 VOLUME_BACKING_FILE_SIZE=${VOLUME_BACKING_FILE_SIZE:-10250M}
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/image_list.sh b/tools/image_list.sh
index fa6b92e..f9a4e2f 100755
--- a/tools/image_list.sh
+++ b/tools/image_list.sh
@@ -12,6 +12,7 @@
 # Extra variables to trigger getting additional images.
 ENABLED_SERVICES=h-api
 HEAT_FETCHED_TEST_IMAGE="Fedora-i386-20-20131211.1-sda"
+PRECACHE_IMAGES=True
 
 # Loop over all the virt drivers and collect all the possible images
 ALL_IMAGES=""
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>