Merge "use a more common rst header hiearchy"
diff --git a/files/apts/ironic b/files/apts/ironic
index 45fdecc..f6c7b74 100644
--- a/files/apts/ironic
+++ b/files/apts/ironic
@@ -12,6 +12,7 @@
 qemu
 qemu-kvm
 qemu-utils
+sgabios
 syslinux
 tftpd-hpa
 xinetd
diff --git a/files/rpms/ironic b/files/rpms/ironic
index e646f3a..0a46314 100644
--- a/files/rpms/ironic
+++ b/files/rpms/ironic
@@ -9,6 +9,7 @@
 openssh-clients
 openvswitch
 python-libguestfs
+sgabios
 syslinux
 tftp-server
 xinetd
diff --git a/lib/cinder b/lib/cinder
index eb3cbe8..611e1ca 100644
--- a/lib/cinder
+++ b/lib/cinder
@@ -258,7 +258,7 @@
     fi
 
     if is_service_enabled swift; then
-        iniset $CINDER_CONF DEFAULT backup_swift_url "http://$SERVICE_HOST:8080/v1/AUTH_"
+        iniset $CINDER_CONF DEFAULT backup_swift_url "$SWIFT_SERVICE_PROTOCOL://$SERVICE_HOST:8080/v1/AUTH_"
     fi
 
     if is_service_enabled ceilometer; then
diff --git a/lib/databases/mysql b/lib/databases/mysql
index 7a444a3..bbf2fd0 100644
--- a/lib/databases/mysql
+++ b/lib/databases/mysql
@@ -142,7 +142,7 @@
     fi
     # Install mysql-server
     if is_ubuntu || is_fedora; then
-        if [[ $DISTRO =~ (rhel6) ]]; then
+        if [[ $DISTRO =~ (rhel6|precise) ]]; then
             install_package mysql-server
         else
             install_package mariadb-server
diff --git a/lib/dstat b/lib/dstat
index a2c522c..4ec10dc 100644
--- a/lib/dstat
+++ b/lib/dstat
@@ -1,4 +1,4 @@
-# lib/apache
+# lib/dstat
 # Functions to start and stop dstat
 
 # Dependencies:
@@ -24,7 +24,7 @@
 # start_dstat() - Start running processes, including screen
 function start_dstat {
     # A better kind of sysstat, with the top process per time slice
-    DSTAT_OPTS="-tcmndrylp --top-cpu-adv"
+    DSTAT_OPTS="-tcmndrylpg --top-cpu-adv"
     if [[ -n ${SCREEN_LOGDIR} ]]; then
         screen_it dstat "cd $TOP_DIR; dstat $DSTAT_OPTS | tee $SCREEN_LOGDIR/$DSTAT_FILE"
     else
diff --git a/lib/horizon b/lib/horizon
index 1b53831..9fd1b85 100644
--- a/lib/horizon
+++ b/lib/horizon
@@ -99,6 +99,8 @@
     local local_settings=$HORIZON_DIR/openstack_dashboard/local/local_settings.py
     cp $HORIZON_SETTINGS $local_settings
 
+    _horizon_config_set $local_settings "" COMPRESS_OFFLINE True
+
     _horizon_config_set $local_settings "" OPENSTACK_HOST \"${KEYSTONE_SERVICE_HOST}\"
     _horizon_config_set $local_settings "" OPENSTACK_KEYSTONE_URL "\"${KEYSTONE_SERVICE_PROTOCOL}://${KEYSTONE_SERVICE_HOST}:${KEYSTONE_SERVICE_PORT}/v2.0\""
     if [[ -n "$KEYSTONE_TOKEN_HASH_ALGORITHM" ]]; then
@@ -140,6 +142,17 @@
     # and run_process
     sudo rm -f /var/log/$APACHE_NAME/horizon_*
 
+    # Setup alias for django-admin which could be different depending on distro
+    local django_admin
+    if type -p django-admin > /dev/null; then
+        django_admin=django-admin
+    else
+        django_admin=django-admin.py
+    fi
+
+    DJANGO_SETTINGS_MODULE=openstack_dashboard.settings $django_admin collectstatic --noinput
+    DJANGO_SETTINGS_MODULE=openstack_dashboard.settings $django_admin compress --force
+
 }
 
 # install_django_openstack_auth() - Collect source and prepare
diff --git a/lib/ironic b/lib/ironic
index afe69f2..f2b1fb2 100644
--- a/lib/ironic
+++ b/lib/ironic
@@ -40,6 +40,18 @@
 IRONIC_ROOTWRAP_CONF=$IRONIC_CONF_DIR/rootwrap.conf
 IRONIC_POLICY_JSON=$IRONIC_CONF_DIR/policy.json
 
+# Deploy to hardware platform
+IRONIC_HW_NODE_CPU=${IRONIC_HW_NODE_CPU:-1}
+IRONIC_HW_NODE_RAM=${IRONIC_HW_NODE_RAM:-512}
+IRONIC_HW_NODE_DISK=${IRONIC_HW_NODE_DISK:-10}
+IRONIC_HW_EPHEMERAL_DISK=${IRONIC_HW_EPHEMERAL_DISK:-0}
+# The file is composed of multiple lines, each line includes four field
+# separated by white space: IPMI address, MAC address, IPMI username
+# and IPMI password.
+# An example:
+#   192.168.110.107 00:1e:67:57:50:4c root otc123
+IRONIC_IPMIINFO_FILE=${IRONIC_IPMIINFO_FILE:-$IRONIC_DATA_DIR/hardware_info}
+
 # Set up defaults for functional / integration testing
 IRONIC_SCRIPTS_DIR=${IRONIC_SCRIPTS_DIR:-$TOP_DIR/tools/ironic/scripts}
 IRONIC_TEMPLATES_DIR=${IRONIC_TEMPLATES_DIR:-$TOP_DIR/tools/ironic/templates}
@@ -51,6 +63,7 @@
 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_TFTPSERVER_IP=${IRONIC_TFTPSERVER_IP:-$HOST_IP}
 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}
@@ -80,7 +93,7 @@
 IRONIC_AGENT_RAMDISK_URL=${IRONIC_AGENT_RAMDISK_URL:-http://tarballs.openstack.org/ironic-python-agent/coreos/files/coreos_production_pxe_image-oem.cpio.gz}
 
 # Which deploy driver to use - valid choices right now
-# are 'pxe_ssh' and 'agent_ssh'.
+# are 'pxe_ssh', 'pxe_ipmitool', 'agent_ssh' and 'agent_ipmitool'.
 IRONIC_DEPLOY_DRIVER=${IRONIC_DEPLOY_DRIVER:-pxe_ssh}
 
 #TODO(agordeev): replace 'ubuntu' with host distro name getting
@@ -91,7 +104,8 @@
 
 # Ironic connection info.  Note the port must be specified.
 IRONIC_SERVICE_PROTOCOL=http
-IRONIC_HOSTPORT=${IRONIC_HOSTPORT:-$SERVICE_HOST:6385}
+IRONIC_SERVICE_PORT=${IRONIC_SERVICE_PORT:-6385}
+IRONIC_HOSTPORT=${IRONIC_HOSTPORT:-$SERVICE_HOST:$IRONIC_SERVICE_PORT}
 
 # Tell Tempest this project is present
 TEMPEST_SERVICES+=,ironic
@@ -133,6 +147,16 @@
     return 1
 }
 
+function is_ironic_hardware {
+    is_ironic_enabled && [[ -n "${IRONIC_DEPLOY_DRIVER##*_ssh}" ]] && return 0
+    return 1
+}
+
+function is_deployed_by_agent {
+    [[ -z "${IRONIC_DEPLOY_DRIVER%%agent*}" ]] && return 0
+    return 1
+}
+
 # install_ironic() - Collect source and prepare
 function install_ironic {
     # make sure all needed service were enabled
@@ -147,6 +171,14 @@
     if [[ "$IRONIC_IPXE_ENABLED" == "True" ]] ; then
         install_apache_wsgi
     fi
+
+    if [[ "$IRONIC_VM_LOG_CONSOLE" == "True" ]] && is_ubuntu; then
+        # Ubuntu packaging+apparmor issue prevents libvirt from loading
+        # the ROM from /usr/share/misc.  Workaround by installing it directly
+        # to a directory that it can read from. (LP: #1393548)
+        sudo rm -rf /usr/share/qemu/sgabios.bin
+        sudo cp /usr/share/misc/sgabios.bin /usr/share/qemu/sgabios.bin
+    fi
 }
 
 # install_ironicclient() - Collect sources and prepare
@@ -183,7 +215,7 @@
 # cleanup_ironic() - Remove residual data files, anything left over from previous
 # runs that would need to clean up.
 function cleanup_ironic {
-    sudo rm -rf $IRONIC_AUTH_CACHE_DIR
+    sudo rm -rf $IRONIC_AUTH_CACHE_DIR $IRONIC_CONF_DIR
 }
 
 # configure_ironic_dirs() - Create all directories required by Ironic and
@@ -251,6 +283,7 @@
     iniset $IRONIC_CONF_FILE DEFAULT policy_file $IRONIC_POLICY_JSON
     configure_auth_token_middleware $IRONIC_CONF_FILE ironic $IRONIC_AUTH_CACHE_DIR/api
     iniset_rpc_backend ironic $IRONIC_CONF_FILE DEFAULT
+    iniset $IRONIC_CONF_FILE api port $IRONIC_SERVICE_PORT
 
     cp -p $IRONIC_DIR/etc/ironic/policy.json $IRONIC_POLICY_JSON
 }
@@ -272,14 +305,14 @@
 
     iniset $IRONIC_CONF_FILE DEFAULT rootwrap_config $IRONIC_ROOTWRAP_CONF
     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 conductor api_url $IRONIC_SERVICE_PROTOCOL://$HOST_IP:$IRONIC_SERVICE_PORT
+    iniset $IRONIC_CONF_FILE pxe tftp_server $IRONIC_TFTPSERVER_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
-    if [[ "$IRONIC_DEPLOY_DRIVER" == "agent_ssh" ]] ; then
+    if is_deployed_by_agent; then
         if [[ "$SWIFT_ENABLE_TEMPURLS" == "True" ]] ; then
             iniset $IRONIC_CONF_FILE glance swift_temp_url_key $SWIFT_TEMPURL_KEY
         else
@@ -393,7 +426,7 @@
 function start_ironic_api {
     run_process ir-api "$IRONIC_BIN_DIR/ironic-api --config-file=$IRONIC_CONF_FILE"
     echo "Waiting for ir-api ($IRONIC_HOSTPORT) to start..."
-    if ! timeout $SERVICE_TIMEOUT sh -c "while ! wget --no-proxy -q -O- http://$IRONIC_HOSTPORT; do sleep 1; done"; then
+    if ! timeout $SERVICE_TIMEOUT sh -c "while ! wget --no-proxy -q -O- $IRONIC_SERVICE_PROTOCOL://$IRONIC_HOSTPORT; do sleep 1; done"; then
         die $LINENO "ir-api did not start"
     fi
 }
@@ -475,46 +508,81 @@
     create_ovs_taps
 }
 
-function enroll_vms {
+function enroll_nodes {
     local chassis_id=$(ironic chassis-create -d "ironic test chassis" | grep " uuid " | get_field 2)
     local idx=0
 
     if [[ "$IRONIC_DEPLOY_DRIVER" == "pxe_ssh" ]] ; then
         local _IRONIC_DEPLOY_KERNEL_KEY=pxe_deploy_kernel
         local _IRONIC_DEPLOY_RAMDISK_KEY=pxe_deploy_ramdisk
-    elif [[ "$IRONIC_DEPLOY_DRIVER" == "agent_ssh" ]] ; then
+    elif is_deployed_by_agent; then
         local _IRONIC_DEPLOY_KERNEL_KEY=deploy_kernel
         local _IRONIC_DEPLOY_RAMDISK_KEY=deploy_ramdisk
     fi
 
-    while read MAC; do
-
-        local node_id=$(ironic node-create --chassis_uuid $chassis_id \
-            --driver $IRONIC_DEPLOY_DRIVER \
+    if ! is_ironic_hardware; then
+        local ironic_node_cpu=$IRONIC_VM_SPECS_CPU
+        local ironic_node_ram=$IRONIC_VM_SPECS_RAM
+        local ironic_node_disk=$IRONIC_VM_SPECS_DISK
+        local ironic_ephemeral_disk=$IRONIC_VM_EPHEMERAL_DISK
+        local ironic_hwinfo_file=$IRONIC_VM_MACS_CSV_FILE
+        local node_options="\
             -i $_IRONIC_DEPLOY_KERNEL_KEY=$IRONIC_DEPLOY_KERNEL_ID \
             -i $_IRONIC_DEPLOY_RAMDISK_KEY=$IRONIC_DEPLOY_RAMDISK_ID \
             -i ssh_virt_type=$IRONIC_SSH_VIRT_TYPE \
             -i ssh_address=$IRONIC_VM_SSH_ADDRESS \
             -i ssh_port=$IRONIC_VM_SSH_PORT \
             -i ssh_username=$IRONIC_SSH_USERNAME \
-            -i ssh_key_filename=$IRONIC_SSH_KEY_DIR/$IRONIC_SSH_KEY_FILENAME \
-            -p cpus=$IRONIC_VM_SPECS_CPU \
-            -p memory_mb=$IRONIC_VM_SPECS_RAM \
-            -p local_gb=$IRONIC_VM_SPECS_DISK \
+            -i ssh_key_filename=$IRONIC_SSH_KEY_DIR/$IRONIC_SSH_KEY_FILENAME"
+    else
+        local ironic_node_cpu=$IRONIC_HW_NODE_CPU
+        local ironic_node_ram=$IRONIC_HW_NODE_RAM
+        local ironic_node_disk=$IRONIC_HW_NODE_DISK
+        local ironic_ephemeral_disk=$IRONIC_HW_EPHEMERAL_DISK
+        if [[ -z "${IRONIC_DEPLOY_DRIVER##*_ipmitool}" ]]; then
+            local ironic_hwinfo_file=$IRONIC_IPMIINFO_FILE
+        fi
+    fi
+
+    while read hardware_info; do
+        if ! is_ironic_hardware; then
+            local mac_address=$hardware_info
+        elif [[ -z "${IRONIC_DEPLOY_DRIVER##*_ipmitool}" ]]; then
+            local ipmi_address=$(echo $hardware_info |awk  '{print $1}')
+            local mac_address=$(echo $hardware_info |awk '{print $2}')
+            local ironic_ipmi_username=$(echo $hardware_info |awk '{print $3}')
+            local ironic_ipmi_passwd=$(echo $hardware_info |awk '{print $4}')
+            # Currently we require all hardware platform have same CPU/RAM/DISK info
+            # in future, this can be enhanced to support different type, and then
+            # we create the bare metal flavor with minimum value
+            local node_options="-i ipmi_address=$ipmi_address -i ipmi_password=$ironic_ipmi_passwd\
+                -i ipmi_username=$ironic_ipmi_username"
+            if is_deployed_by_agent; then
+                node_options+=" -i $_IRONIC_DEPLOY_KERNEL_KEY=$IRONIC_DEPLOY_KERNEL_ID"
+                node_options+=" -i $_IRONIC_DEPLOY_RAMDISK_KEY=$IRONIC_DEPLOY_RAMDISK_ID"
+            fi
+        fi
+
+        local node_id=$(ironic node-create --chassis_uuid $chassis_id \
+            --driver $IRONIC_DEPLOY_DRIVER \
+            -p cpus=$ironic_node_cpu\
+            -p memory_mb=$ironic_node_ram\
+            -p local_gb=$ironic_node_disk\
             -p cpu_arch=x86_64 \
+            $node_options \
             | grep " uuid " | get_field 2)
 
-        ironic port-create --address $MAC --node_uuid $node_id
+        ironic port-create --address $mac_address --node_uuid $node_id
 
         idx=$((idx+1))
-    done < $IRONIC_VM_MACS_CSV_FILE
+    done < $ironic_hwinfo_file
 
     # create the nova flavor
     # NOTE(adam_g): Attempting to use an autogenerated UUID for flavor id here uncovered
     # bug (LP: #1333852) in Trove.  This can be changed to use an auto flavor id when the
     # bug is fixed in Juno.
-    local adjusted_disk=$(($IRONIC_VM_SPECS_DISK - $IRONIC_VM_EPHEMERAL_DISK))
-    nova flavor-create --ephemeral $IRONIC_VM_EPHEMERAL_DISK baremetal 551 $IRONIC_VM_SPECS_RAM $adjusted_disk $IRONIC_VM_SPECS_CPU
+    local adjusted_disk=$(($ironic_node_disk - $ironic_ephemeral_disk))
+    nova flavor-create --ephemeral $ironic_ephemeral_disk baremetal 551 $ironic_node_ram $adjusted_disk $ironic_node_cpu
 
     # TODO(lucasagomes): Remove the 'baremetal:deploy_kernel_id'
     # and 'baremetal:deploy_ramdisk_id' parameters
@@ -529,8 +597,8 @@
     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 $IRONIC_HOSTPORT -j ACCEPT || true
-    if [ "$IRONIC_DEPLOY_DRIVER" == "agent_ssh" ]; then
+    sudo iptables -I INPUT -d $HOST_IP -p tcp --dport $IRONIC_SERVICE_PORT -j ACCEPT || true
+    if is_deployed_by_agent; then
         # agent ramdisk gets instance image from swift
         sudo iptables -I INPUT -d $HOST_IP -p tcp --dport ${SWIFT_DEFAULT_BIND_PORT:-8080} -j ACCEPT || true
     fi
@@ -606,8 +674,8 @@
     fi
 
     if [ -z "$IRONIC_DEPLOY_KERNEL" -o -z "$IRONIC_DEPLOY_RAMDISK" ]; then
-        local IRONIC_DEPLOY_KERNEL_PATH=$TOP_DIR/files/ir-deploy.kernel
-        local IRONIC_DEPLOY_RAMDISK_PATH=$TOP_DIR/files/ir-deploy.initramfs
+        local IRONIC_DEPLOY_KERNEL_PATH=$TOP_DIR/files/ir-deploy-$IRONIC_DEPLOY_DRIVER.kernel
+        local IRONIC_DEPLOY_RAMDISK_PATH=$TOP_DIR/files/ir-deploy-$IRONIC_DEPLOY_DRIVER.initramfs
     else
         local IRONIC_DEPLOY_KERNEL_PATH=$IRONIC_DEPLOY_KERNEL
         local IRONIC_DEPLOY_RAMDISK_PATH=$IRONIC_DEPLOY_RAMDISK
@@ -618,17 +686,17 @@
         if [ "$IRONIC_BUILD_DEPLOY_RAMDISK" = "True" ]; then
             # we can build them only if we're not offline
             if [ "$OFFLINE" != "True" ]; then
-                if [ "$IRONIC_DEPLOY_DRIVER" == "agent_ssh" ]; then
+                if is_deployed_by_agent; then
                     build_ipa_coreos_ramdisk $IRONIC_DEPLOY_KERNEL_PATH $IRONIC_DEPLOY_RAMDISK_PATH
                 else
                     ramdisk-image-create $IRONIC_DEPLOY_FLAVOR \
-                        -o $TOP_DIR/files/ir-deploy
+                        -o $TOP_DIR/files/ir-deploy-$IRONIC_DEPLOY_DRIVER
                 fi
             else
                 die $LINENO "Deploy kernel+ramdisk files don't exist and cannot be build in OFFLINE mode"
             fi
         else
-            if [ "$IRONIC_DEPLOY_DRIVER" == "agent_ssh" ]; then
+            if is_deployed_by_agent; then
                 # download the agent image tarball
                 wget "$IRONIC_AGENT_KERNEL_URL" -O $IRONIC_DEPLOY_KERNEL_PATH
                 wget "$IRONIC_AGENT_RAMDISK_URL" -O $IRONIC_DEPLOY_RAMDISK_PATH
@@ -662,11 +730,15 @@
 
 function prepare_baremetal_basic_ops {
     upload_baremetal_ironic_deploy
-    create_bridge_and_vms
-    enroll_vms
+    if ! is_ironic_hardware; then
+        create_bridge_and_vms
+    fi
+    enroll_nodes
     configure_tftpd
     configure_iptables
-    configure_ironic_auxiliary
+    if ! is_ironic_hardware; then
+        configure_ironic_auxiliary
+    fi
 }
 
 function cleanup_baremetal_basic_ops {
@@ -687,8 +759,8 @@
     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
-    if [ "$IRONIC_DEPLOY_DRIVER" == "agent_ssh" ]; then
+    sudo iptables -D INPUT -d $HOST_IP -p tcp --dport $IRONIC_SERVICE_PORT -j ACCEPT || true
+    if is_deployed_by_agent; then
         # agent ramdisk gets instance image from swift
         sudo iptables -D INPUT -d $HOST_IP -p tcp --dport ${SWIFT_DEFAULT_BIND_PORT:-8080} -j ACCEPT || true
     fi
diff --git a/lib/neutron b/lib/neutron
index 8295a73..1d4fe1b 100644
--- a/lib/neutron
+++ b/lib/neutron
@@ -523,7 +523,7 @@
         die_if_not_set $LINENO PHYSICAL_NETWORK "You must specify the PHYSICAL_NETWORK"
         die_if_not_set $LINENO PROVIDER_NETWORK_TYPE "You must specifiy the PROVIDER_NETWORK_TYPE"
         NET_ID=$(neutron net-create $PHYSICAL_NETWORK --tenant_id $TENANT_ID --provider:network_type $PROVIDER_NETWORK_TYPE --provider:physical_network "$PHYSICAL_NETWORK" ${SEGMENTATION_ID:+--provider:segmentation_id $SEGMENTATION_ID} --shared | grep ' id ' | get_field 2)
-        SUBNET_ID=$(neutron subnet-create --tenant_id $TENANT_ID --ip_version 4 ${ALLOCATION_POOL:+--allocation-pool $ALLOCATION_POOL} --name $PROVIDER_SUBNET_NAME $NET_ID $FIXED_RANGE | grep ' id ' | get_field 2)
+        SUBNET_ID=$(neutron subnet-create --tenant_id $TENANT_ID --ip_version 4 ${ALLOCATION_POOL:+--allocation-pool $ALLOCATION_POOL} --name $PROVIDER_SUBNET_NAME --gateway $NETWORK_GATEWAY $NET_ID $FIXED_RANGE | grep ' id ' | get_field 2)
         SUBNET_V6_ID=$(neutron subnet-create --tenant_id $TENANT_ID --ip_version 6 --ipv6-address-mode slaac --gateway $V6_NETWORK_GATEWAY --name $PROVIDER_SUBNET_NAME_V6 $NET_ID $FIXED_RANGE_V6 | grep 'id' | get_field 2)
         sudo ip link set $OVS_PHYSICAL_BRIDGE up
         sudo ip link set br-int up
@@ -678,6 +678,13 @@
         sudo ip link set $OVS_PHYSICAL_BRIDGE up
         sudo ip link set br-int up
         sudo ip link set $PUBLIC_INTERFACE up
+        if is_ironic_hardware; then
+            for IP in $(ip addr show dev $PUBLIC_INTERFACE | grep ' inet ' | awk '{print $2}'); do
+                sudo ip addr del $IP dev $PUBLIC_INTERFACE
+                sudo ip addr add $IP dev $OVS_PHYSICAL_BRIDGE
+            done
+            sudo route add -net $FIXED_RANGE gw $NETWORK_GATEWAY dev $OVS_PHYSICAL_BRIDGE
+        fi
     fi
 
     if is_service_enabled q-vpn; then
@@ -729,6 +736,14 @@
 # cleanup_neutron() - Remove residual data files, anything left over from previous
 # runs that a clean run would need to clean up
 function cleanup_neutron {
+    if [[ is_provider_network && is_ironic_hardware ]]; then
+        for IP in $(ip addr show dev $OVS_PHYSICAL_BRIDGE | grep ' inet ' | awk '{print $2}'); do
+            sudo ip addr del $IP dev $OVS_PHYSICAL_BRIDGE
+            sudo ip addr add $IP dev $PUBLIC_INTERFACE
+        done
+        sudo route del -net $FIXED_RANGE gw $NETWORK_GATEWAY dev $OVS_PHYSICAL_BRIDGE
+    fi
+
     if is_neutron_ovs_base_plugin; then
         neutron_ovs_base_cleanup
     fi
@@ -770,7 +785,7 @@
 
     iniset $NEUTRON_CONF database connection `database_connection_url $Q_DB_NAME`
     iniset $NEUTRON_CONF DEFAULT state_path $DATA_DIR/neutron
-
+    iniset $NEUTRON_CONF DEFAULT use_syslog $SYSLOG
     # If addition config files are set, make sure their path name is set as well
     if [[ ${#Q_PLUGIN_EXTRA_CONF_FILES[@]} > 0 && $Q_PLUGIN_EXTRA_CONF_PATH == '' ]]; then
         die $LINENO "Neutron additional plugin config not set.. exiting"
diff --git a/lib/nova_plugins/hypervisor-ironic b/lib/nova_plugins/hypervisor-ironic
index 4004cc9..4209503 100644
--- a/lib/nova_plugins/hypervisor-ironic
+++ b/lib/nova_plugins/hypervisor-ironic
@@ -47,7 +47,7 @@
     iniset $NOVA_CONF ironic admin_password $ADMIN_PASSWORD
     iniset $NOVA_CONF ironic admin_url $KEYSTONE_AUTH_URI/v2.0
     iniset $NOVA_CONF ironic admin_tenant_name demo
-    iniset $NOVA_CONF ironic api_endpoint http://$SERVICE_HOST:6385/v1
+    iniset $NOVA_CONF ironic api_endpoint $IRONIC_SERVICE_PROTOCOL://$IRONIC_HOSTPORT/v1
 }
 
 # install_nova_hypervisor() - Install external components
diff --git a/lib/oslo b/lib/oslo
index a20aa14..d00580b 100644
--- a/lib/oslo
+++ b/lib/oslo
@@ -23,6 +23,7 @@
 GITDIR["cliff"]=$DEST/cliff
 GITDIR["oslo.config"]=$DEST/oslo.config
 GITDIR["oslo.concurrency"]=$DEST/oslo.concurrency
+GITDIR["oslo.context"]=$DEST/oslo.context
 GITDIR["oslo.db"]=$DEST/oslo.db
 GITDIR["oslo.i18n"]=$DEST/oslo.i18n
 GITDIR["oslo.log"]=$DEST/oslo.log
diff --git a/lib/tempest b/lib/tempest
index 9e025a1..d3fb9fb 100644
--- a/lib/tempest
+++ b/lib/tempest
@@ -45,7 +45,7 @@
 # --------
 
 # Set up default directories
-GITDIR["tempest_lib"]=$DEST/tempest-lib
+GITDIR["tempest-lib"]=$DEST/tempest-lib
 
 TEMPEST_DIR=$DEST/tempest
 TEMPEST_CONFIG_DIR=${TEMPEST_CONFIG_DIR:-$TEMPEST_DIR/etc}
@@ -247,6 +247,7 @@
         fi
     fi
 
+    iniset $TEMPEST_CONF DEFAULT use_syslog $SYSLOG
     # Oslo
     iniset $TEMPEST_CONFIG DEFAULT lock_path $TEMPEST_STATE_PATH
     mkdir -p $TEMPEST_STATE_PATH
@@ -303,6 +304,7 @@
     iniset $TEMPEST_CONFIG compute-feature-enabled change_password False
     iniset $TEMPEST_CONFIG compute-feature-enabled block_migration_for_live_migration ${USE_BLOCK_MIGRATION_FOR_LIVE_MIGRATION:-False}
     iniset $TEMPEST_CONFIG compute-feature-enabled api_extensions ${COMPUTE_API_EXTENSIONS:-"all"}
+    iniset $TEMPEST_CONFIG compute-feature-enabled xml_api_v2 ${TEMPEST_ENABLE_NOVA_XML_API:-True}
     iniset $TEMPEST_CONFIG compute-feature-disabled api_extensions ${DISABLE_COMPUTE_API_EXTENSIONS}
 
     # Compute admin
@@ -446,9 +448,9 @@
 
 # install_tempest_lib() - Collect source, prepare, and install tempest-lib
 function install_tempest_lib {
-    if use_library_from_git "tempest_lib"; then
-        git_clone_by_name "tempest_lib"
-        setup_develop "tempest_lib"
+    if use_library_from_git "tempest-lib"; then
+        git_clone_by_name "tempest-lib"
+        setup_develop "tempest-lib"
     fi
 }
 
diff --git a/run_tests.sh b/run_tests.sh
index bf90332..3ba7e10 100755
--- a/run_tests.sh
+++ b/run_tests.sh
@@ -18,47 +18,18 @@
 PASSES=""
 FAILURES=""
 
-# Check the return code and add the test to PASSES or FAILURES as appropriate
-# pass_fail <result> <expected> <name>
-function pass_fail {
-    local result=$1
-    local expected=$2
-    local test_name=$3
-
-    if [[ $result -ne $expected ]]; then
-        FAILURES="$FAILURES $test_name"
-    else
-        PASSES="$PASSES $test_name"
-    fi
-}
-
-if [[ -n $@ ]]; then
-    FILES=$@
-else
-    LIBS=`find lib -type f | grep -v \.md`
-    SCRIPTS=`find . -type f -name \*\.sh`
-    EXTRA="functions functions-common stackrc openrc exerciserc eucarc"
-    FILES="$SCRIPTS $LIBS $EXTRA"
-fi
-
-echo "Running bash8..."
-
-tox -ebashate
-pass_fail $? 0 bash8
-
-
 # Test that no one is trying to land crazy refs as branches
 
-echo "Ensuring we don't have crazy refs"
+for testfile in tests/test_*.sh; do
+    $testfile
+    if [[ $? -eq 0 ]]; then
+        PASSES="$PASSES $testfile"
+    else
+        FAILURES="$FAILURES $testfile"
+    fi
+done
 
-REFS=`grep BRANCH stackrc | grep -v -- '-master'`
-rc=$?
-pass_fail $rc 1 crazy-refs
-if [[ $rc -eq 0 ]]; then
-    echo "Branch defaults must be master. Found:"
-    echo $REFS
-fi
-
+# Summary display now that all is said and done
 echo "====================================================================="
 for script in $PASSES; do
     echo PASS $script
diff --git a/stack.sh b/stack.sh
index 7635f32..93e4541 100755
--- a/stack.sh
+++ b/stack.sh
@@ -209,18 +209,10 @@
     echo 'APT::Acquire::Retries "20";' | sudo tee /etc/apt/apt.conf.d/80retry  >/dev/null
 fi
 
-# upstream Rackspace centos7 images have an issue where cloud-init is
-# installed via pip because there were not official packages when the
-# image was created (fix in the works).  Remove all pip packages
-# before we do anything else
-if [[ $DISTRO = "rhel7" && is_rackspace ]]; then
-    (sudo pip freeze | xargs sudo pip uninstall -y) || true
-fi
-
 # Some distros need to add repos beyond the defaults provided by the vendor
 # to pick up required packages.
 
-if [[ is_fedora && $DISTRO == "rhel6" ]]; then
+if is_fedora && [ $DISTRO == "rhel6" ]; then
     # Installing Open vSwitch on RHEL requires enabling the RDO repo.
     RHEL6_RDO_REPO_RPM=${RHEL6_RDO_REPO_RPM:-"http://rdo.fedorapeople.org/openstack-icehouse/rdo-release-icehouse.rpm"}
     RHEL6_RDO_REPO_ID=${RHEL6_RDO_REPO_ID:-"openstack-icehouse"}
@@ -231,7 +223,7 @@
     fi
 fi
 
-if [[ is_fedora && ( $DISTRO == "rhel6" || $DISTRO == "rhel7" ) ]]; then
+if is_fedora && [[ $DISTRO == "rhel6" || $DISTRO == "rhel7" ]]; then
     # RHEL requires EPEL for many Open Stack dependencies
 
     # note we always remove and install latest -- some environments
@@ -355,7 +347,7 @@
     echo $@ >&3
 }
 
-if [[ is_fedora && $DISTRO == "rhel6" ]]; then
+if is_fedora && [ $DISTRO == "rhel6" ]; then
     # poor old python2.6 doesn't have argparse by default, which
     # outfilter.py uses
     is_package_installed python-argparse || install_package python-argparse
diff --git a/stackrc b/stackrc
index b1a9e20..e0e886d 100644
--- a/stackrc
+++ b/stackrc
@@ -216,8 +216,8 @@
 TEMPEST_BRANCH=${TEMPEST_BRANCH:-master}
 
 # TODO(sdague): this should end up as a library component like below
-GITREPO["tempest_lib"]=${TEMPEST_LIB_REPO:-${GIT_BASE}/openstack/tempest-lib.git}
-GITBRANCH["tempest_lib"]=${TEMPEST_LIB_BRANCH:-master}
+GITREPO["tempest-lib"]=${TEMPEST_LIB_REPO:-${GIT_BASE}/openstack/tempest-lib.git}
+GITBRANCH["tempest-lib"]=${TEMPEST_LIB_BRANCH:-master}
 
 
 ##############
@@ -292,6 +292,10 @@
 GITREPO["oslo.config"]=${OSLOCFG_REPO:-${GIT_BASE}/openstack/oslo.config.git}
 GITBRANCH["oslo.config"]=${OSLOCFG_BRANCH:-master}
 
+# oslo.context
+GITREPO["oslo.context"]=${OSLOCTX_REPO:-${GIT_BASE}/openstack/oslo.context.git}
+GITBRANCH["oslo.context"]=${OSLOCTX_BRANCH:-master}
+
 # oslo.db
 GITREPO["oslo.db"]=${OSLODB_REPO:-${GIT_BASE}/openstack/oslo.db.git}
 GITBRANCH["oslo.db"]=${OSLODB_BRANCH:-master}
diff --git a/tests/test_refs.sh b/tests/test_refs.sh
new file mode 100755
index 0000000..bccca5d
--- /dev/null
+++ b/tests/test_refs.sh
@@ -0,0 +1,24 @@
+#!/bin/bash
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+
+echo "Ensuring we don't have crazy refs"
+
+REFS=`grep BRANCH stackrc | grep -v -- '-master'`
+rc=$?
+if [[ $rc -eq 0 ]]; then
+    echo "Branch defaults must be master. Found:"
+    echo $REFS
+    exit 1
+fi
diff --git a/tools/fixup_stuff.sh b/tools/fixup_stuff.sh
index b8beb01..ca46533 100755
--- a/tools/fixup_stuff.sh
+++ b/tools/fixup_stuff.sh
@@ -18,7 +18,6 @@
 #   - (re)start messagebus daemon
 #   - remove distro packages python-crypto and python-lxml
 #   - pre-install hgtools to work around a bug in RHEL6 distribute
-#   - install nose 1.1 from EPEL
 
 # If TOP_DIR is set we're being sourced rather than running stand-alone
 # or in a sub-shell
@@ -179,14 +178,6 @@
     # Note we do this before the track-depends in ``stack.sh``.
     pip_install hgtools
 
-
-    # RHEL6's version of ``python-nose`` is incompatible with Tempest.
-    # Install nose 1.1 (Tempest-compatible) from EPEL
-    install_package python-nose1.1
-    # Add a symlink for the new nosetests to allow tox for Tempest to
-    # 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
diff --git a/tools/ironic/scripts/configure-vm b/tools/ironic/scripts/configure-vm
index 4c42c49..378fcb8 100755
--- a/tools/ironic/scripts/configure-vm
+++ b/tools/ironic/scripts/configure-vm
@@ -78,8 +78,10 @@
             params['emulator'] = "/usr/bin/qemu-kvm"
 
     if args.console_log:
+        params['bios_serial'] = "<bios useserial='yes'/>"
         params['console_log'] = CONSOLE_LOG % {'console_log': args.console_log}
     else:
+        params['bios_serial'] = ''
         params['console_log'] = ''
     libvirt_template = source_template % params
     conn = libvirt.open("qemu:///system")
diff --git a/tools/ironic/templates/vm.xml b/tools/ironic/templates/vm.xml
index 4f40334..ae7d685 100644
--- a/tools/ironic/templates/vm.xml
+++ b/tools/ironic/templates/vm.xml
@@ -6,6 +6,7 @@
     <type arch='%(arch)s' machine='pc-1.0'>hvm</type>
     <boot dev='%(bootdev)s'/>
     <bootmenu enable='no'/>
+    %(bios_serial)s
   </os>
   <features>
     <acpi/>