Merge "update create_heat_accounts, don't use os_url and os_token"
diff --git a/clean.sh b/clean.sh
index ae28aa9..fc6f80d 100755
--- a/clean.sh
+++ b/clean.sh
@@ -50,7 +50,6 @@
 source $TOP_DIR/lib/swift
 source $TOP_DIR/lib/heat
 source $TOP_DIR/lib/neutron-legacy
-source $TOP_DIR/lib/ironic
 
 
 # Extras Source
diff --git a/doc/source/guides/neutron.rst b/doc/source/guides/neutron.rst
index 9dcb654..a72b6f9 100644
--- a/doc/source/guides/neutron.rst
+++ b/doc/source/guides/neutron.rst
@@ -383,6 +383,7 @@
         ## Neutron Networking options used to create Neutron Subnets
 
         FIXED_RANGE="203.0.113.0/24"
+        NETWORK_GATEWAY=203.0.113.1
         PROVIDER_SUBNET_NAME="provider_net"
         PROVIDER_NETWORK_TYPE="vlan"
         SEGMENTATION_ID=2010
diff --git a/doc/source/index.rst b/doc/source/index.rst
index ec345c9..2622436 100644
--- a/doc/source/index.rst
+++ b/doc/source/index.rst
@@ -174,7 +174,6 @@
 * `lib/heat <lib/heat.html>`__
 * `lib/horizon <lib/horizon.html>`__
 * `lib/infra <lib/infra.html>`__
-* `lib/ironic <lib/ironic.html>`__
 * `lib/keystone <lib/keystone.html>`__
 * `lib/ldap <lib/ldap.html>`__
 * `lib/neutron-legacy <lib/neutron-legacy.html>`__
@@ -189,7 +188,6 @@
 * `clean.sh <clean.sh.html>`__
 * `run\_tests.sh <run_tests.sh.html>`__
 
-* `extras.d/50-ironic.sh <extras.d/50-ironic.sh.html>`__
 * `extras.d/60-ceph.sh <extras.d/60-ceph.sh.html>`__
 * `extras.d/70-tuskar.sh <extras.d/70-tuskar.sh.html>`__
 * `extras.d/80-tempest.sh <extras.d/80-tempest.sh.html>`__
diff --git a/doc/source/plugin-registry.rst b/doc/source/plugin-registry.rst
index c68d926..7682def 100644
--- a/doc/source/plugin-registry.rst
+++ b/doc/source/plugin-registry.rst
@@ -30,6 +30,8 @@
 +------------------+---------------------------------------------+--------------------+
 |gnocchi           |git://git.openstack.org/openstack/gnocchi    | metric             |
 +------------------+---------------------------------------------+--------------------+
+|ironic            |git://git.openstack.org/openstack/ironic     | baremetal          |
++------------------+---------------------------------------------+--------------------+
 |magnum            |git://git.openstack.org/openstack/magnum     |                    |
 +------------------+---------------------------------------------+--------------------+
 |manila            |git://git.openstack.org/openstack/manila     | file shares        |
diff --git a/extras.d/50-ironic.sh b/extras.d/50-ironic.sh
deleted file mode 100644
index 0ee6a94..0000000
--- a/extras.d/50-ironic.sh
+++ /dev/null
@@ -1,50 +0,0 @@
-# ironic.sh - Devstack extras script to install ironic
-
-# NOTE(jroll) this is used for the transition to a devstack plugin in
-# the ironic tree.
-IRONIC_USING_PLUGIN=$(trueorfalse False IRONIC_USING_PLUGIN)
-if [[ "$IRONIC_USING_PLUGIN" == "True" ]] ; then
-    return 0
-fi
-
-if is_service_enabled ir-api ir-cond; then
-    if [[ "$1" == "source" ]]; then
-        # Initial source
-        source $TOP_DIR/lib/ironic
-    elif [[ "$1" == "stack" && "$2" == "install" ]]; then
-        echo_summary "Installing Ironic"
-        install_ironic
-        install_ironicclient
-        cleanup_ironic
-    elif [[ "$1" == "stack" && "$2" == "post-config" ]]; then
-        echo_summary "Configuring Ironic"
-        configure_ironic
-
-        if is_service_enabled key; then
-            create_ironic_accounts
-        fi
-
-    elif [[ "$1" == "stack" && "$2" == "extra" ]]; then
-        # Initialize ironic
-        init_ironic
-
-        # Start the ironic API and ironic taskmgr components
-        echo_summary "Starting Ironic"
-        start_ironic
-
-        if [[ "$IRONIC_BAREMETAL_BASIC_OPS" = "True" ]]; then
-            prepare_baremetal_basic_ops
-        fi
-    fi
-
-    if [[ "$1" == "unstack" ]]; then
-        stop_ironic
-        if [[ "$IRONIC_BAREMETAL_BASIC_OPS" = "True" ]]; then
-            cleanup_baremetal_basic_ops
-        fi
-    fi
-
-    if [[ "$1" == "clean" ]]; then
-        cleanup_ironic
-    fi
-fi
diff --git a/files/apache-ironic.template b/files/apache-ironic.template
deleted file mode 100644
index 8864194..0000000
--- a/files/apache-ironic.template
+++ /dev/null
@@ -1,12 +0,0 @@
-Listen %PUBLICPORT%
-
-<VirtualHost *:%PUBLICPORT%>
-    DocumentRoot "%HTTPROOT%"
-    <Directory "%HTTPROOT%">
-        Options Indexes FollowSymLinks
-        AllowOverride None
-        Order allow,deny
-        Allow from all
-        Require all granted
-    </Directory>
-</VirtualHost>
diff --git a/files/debs/ironic b/files/debs/ironic
deleted file mode 100644
index 4d5a6aa..0000000
--- a/files/debs/ironic
+++ /dev/null
@@ -1,19 +0,0 @@
-docker.io
-ipmitool
-iptables
-ipxe
-libguestfs0
-libvirt-bin
-open-iscsi
-openssh-client
-openvswitch-datapath-dkms
-openvswitch-switch
-python-libguestfs
-python-libvirt
-qemu
-qemu-kvm
-qemu-utils
-sgabios
-syslinux
-tftpd-hpa
-xinetd
diff --git a/files/debs/keystone b/files/debs/keystone
index 0795167..370e4aa 100644
--- a/files/debs/keystone
+++ b/files/debs/keystone
@@ -1,6 +1,5 @@
 libkrb5-dev
 libldap2-dev
 libsasl2-dev
-python-mysql.connector
 python-mysqldb
 sqlite3
diff --git a/files/debs/neutron b/files/debs/neutron
index 85145d3..e53cc68 100644
--- a/files/debs/neutron
+++ b/files/debs/neutron
@@ -8,7 +8,6 @@
 libmysqlclient-dev
 mysql-server #NOPRIME
 postgresql-server-dev-all
-python-mysql.connector
 python-mysqldb
 rabbitmq-server # NOPRIME
 radvd # NOPRIME
diff --git a/files/debs/nova b/files/debs/nova
index fe57fc4..58dad41 100644
--- a/files/debs/nova
+++ b/files/debs/nova
@@ -15,7 +15,6 @@
 mysql-server # NOPRIME
 parted
 pm-utils
-python-mysql.connector
 python-mysqldb
 qemu # dist:wheezy,jessie NOPRIME
 qemu-kvm # NOPRIME
diff --git a/files/rpms/ironic b/files/rpms/ironic
deleted file mode 100644
index 2bf8bb3..0000000
--- a/files/rpms/ironic
+++ /dev/null
@@ -1,14 +0,0 @@
-docker-io
-ipmitool
-iptables
-ipxe-bootimgs
-libguestfs
-libvirt
-libvirt-python
-net-tools
-openssh-clients
-openvswitch
-sgabios
-syslinux
-tftp-server
-xinetd
diff --git a/files/rpms/neutron b/files/rpms/neutron
index 9683475..2e49a0c 100644
--- a/files/rpms/neutron
+++ b/files/rpms/neutron
@@ -4,7 +4,6 @@
 ebtables
 iptables
 iputils
-mysql-connector-python
 mysql-devel
 MySQL-python
 mysql-server # NOPRIME
diff --git a/files/rpms/nova b/files/rpms/nova
index 00e7596..4db9a06 100644
--- a/files/rpms/nova
+++ b/files/rpms/nova
@@ -15,7 +15,6 @@
 libvirt-python # NOPRIME
 libxml2-python
 m2crypto
-mysql-connector-python
 mysql-devel
 MySQL-python
 mysql-server # NOPRIME
diff --git a/functions-common b/functions-common
index b15c3d7..e8f8b10 100644
--- a/functions-common
+++ b/functions-common
@@ -980,6 +980,15 @@
             -c URL -f value)
 }
 
+# check if we are using ironic with hardware
+# TODO(jroll) this is a kludge left behind when ripping ironic code
+# out of tree, as it is used by nova and neutron.
+# figure out a way to refactor nova/neutron code to eliminate this
+function is_ironic_hardware {
+    is_service_enabled ironic && [[ -n "${IRONIC_DEPLOY_DRIVER##*_ssh}" ]] && return 0
+    return 1
+}
+
 
 # Package Functions
 # =================
@@ -1790,7 +1799,7 @@
             # white listed elements in tree. We want these to move out
             # over time as well, but they are in tree, so we need to
             # manage that.
-            local exceptions="50-ironic.sh 60-ceph.sh 80-tempest.sh"
+            local exceptions="60-ceph.sh 80-tempest.sh"
             local extra
             extra=$(basename $extra_plugin_file_name)
             if [[ ! ( $exceptions =~ "$extra" ) ]]; then
@@ -1978,7 +1987,6 @@
         [[ ${service} == n-cpu-* && ${ENABLED_SERVICES} =~ "n-cpu" ]] && enabled=0
         [[ ${service} == "nova" && ${ENABLED_SERVICES} =~ "n-" ]] && enabled=0
         [[ ${service} == "glance" && ${ENABLED_SERVICES} =~ "g-" ]] && enabled=0
-        [[ ${service} == "ironic" && ${ENABLED_SERVICES} =~ "ir-" ]] && enabled=0
         [[ ${service} == "neutron" && ${ENABLED_SERVICES} =~ "q-" ]] && enabled=0
         [[ ${service} == "trove" && ${ENABLED_SERVICES} =~ "tr-" ]] && enabled=0
         [[ ${service} == "swift" && ${ENABLED_SERVICES} =~ "s-" ]] && enabled=0
diff --git a/lib/cinder b/lib/cinder
index 569f3ab..5bd940b 100644
--- a/lib/cinder
+++ b/lib/cinder
@@ -305,6 +305,8 @@
     if is_service_enabled tls-proxy; then
         # Set the service port for a proxy to take the original
         iniset $CINDER_CONF DEFAULT osapi_volume_listen_port $CINDER_SERVICE_PORT_INT
+
+        iniset $CINDER_CONF DEFAULT public_endpoint $CINDER_SERVICE_PROTOCOL://$CINDER_SERVICE_HOST:$CINDER_SERVICE_PORT
     fi
 
     if [ "$SYSLOG" != "False" ]; then
diff --git a/lib/glance b/lib/glance
index 4f95975..19e7937 100644
--- a/lib/glance
+++ b/lib/glance
@@ -169,6 +169,9 @@
         iniset $GLANCE_API_CONF DEFAULT bind_port $GLANCE_SERVICE_PORT_INT
         iniset $GLANCE_API_CONF DEFAULT public_endpoint $GLANCE_SERVICE_PROTOCOL://$GLANCE_HOSTPORT
         iniset $GLANCE_REGISTRY_CONF DEFAULT bind_port $GLANCE_REGISTRY_PORT_INT
+
+        iniset $GLANCE_API_CONF keystone_authtoken identity_uri $KEYSTONE_AUTH_URI
+        iniset $GLANCE_REGISTRY_CONF keystone_authtoken identity_uri $KEYSTONE_AUTH_URI
     fi
 
     # Register SSL certificates if provided
diff --git a/lib/heat b/lib/heat
index ff196f4..6301230 100644
--- a/lib/heat
+++ b/lib/heat
@@ -56,6 +56,10 @@
 HEAT_TEMPLATES_DIR=$HEAT_CONF_DIR/templates
 HEAT_API_HOST=${HEAT_API_HOST:-$HOST_IP}
 HEAT_API_PORT=${HEAT_API_PORT:-8004}
+HEAT_SERVICE_USER=${HEAT_SERVICE_USER:-heat}
+HEAT_TRUSTEE_USER=${HEAT_TRUSTEE_USER:-$HEAT_SERVICE_USER}
+HEAT_TRUSTEE_PASSWORD=${HEAT_TRUSTEE_PASSWORD:-$SERVICE_PASSWORD}
+HEAT_TRUSTEE_DOMAIN=${HEAT_TRUSTEE_DOMAIN:-default}
 
 # Support entry points installation of console scripts
 HEAT_BIN_DIR=$(get_python_exec_prefix)
@@ -73,7 +77,7 @@
     fi
 else
     HEAT_STACK_DOMAIN=$(trueorfalse True HEAT_STACK_DOMAIN)
-    HEAT_DEFERRED_AUTH=${HEAT_DEFERRED_AUTH:-trusts}
+    HEAT_DEFERRED_AUTH=${HEAT_DEFERRED_AUTH:-}
 fi
 HEAT_PLUGIN_DIR=${HEAT_PLUGIN_DIR:-$DATA_DIR/heat/plugins}
 ENABLE_HEAT_PLUGINS=${ENABLE_HEAT_PLUGINS:-}
@@ -134,30 +138,39 @@
         setup_colorized_logging $HEAT_CONF DEFAULT tenant user
     fi
 
-    iniset $HEAT_CONF DEFAULT deferred_auth_method $HEAT_DEFERRED_AUTH
+    if [ ! -z "$HEAT_DEFERRED_AUTH" ]; then
+        iniset $HEAT_CONF DEFAULT deferred_auth_method $HEAT_DEFERRED_AUTH
+    fi
 
     if [ "$HEAT_USE_MOD_WSGI" == "True" ]; then
         _config_heat_apache_wsgi
     fi
 
-    # NOTE(jamielennox): heat re-uses specific values from the
-    # keystone_authtoken middleware group and so currently fails when using the
-    # auth plugin setup. This should be fixed in heat.  Heat is also the only
-    # service that requires the auth_uri to include a /v2.0. Remove this custom
-    # setup when bug #1300246 is resolved.
-    iniset $HEAT_CONF keystone_authtoken auth_uri $KEYSTONE_SERVICE_URI/v2.0
     if [[ "$HEAT_STANDALONE" = "True" ]]; then
         iniset $HEAT_CONF paste_deploy flavor standalone
         iniset $HEAT_CONF clients_heat url "http://$HEAT_API_HOST:$HEAT_API_PORT/v1/%(tenant_id)s"
     else
         iniset $HEAT_CONF keystone_authtoken identity_uri $KEYSTONE_AUTH_URI
-        iniset $HEAT_CONF keystone_authtoken admin_user heat
+        iniset $HEAT_CONF keystone_authtoken admin_user $HEAT_SERVICE_USER
         iniset $HEAT_CONF keystone_authtoken admin_password $SERVICE_PASSWORD
         iniset $HEAT_CONF keystone_authtoken admin_tenant_name $SERVICE_TENANT_NAME
         iniset $HEAT_CONF keystone_authtoken cafile $SSL_BUNDLE_FILE
         iniset $HEAT_CONF keystone_authtoken signing_dir $HEAT_AUTH_CACHE_DIR
     fi
 
+    # If HEAT_DEFERRED_AUTH is unset or explicitly set to trusts, configure
+    # the section for the client plugin associated with the trustee
+    if [ -z "$HEAT_DEFERRED_AUTH" -o "trusts" == "$HEAT_DEFERRED_AUTH" ]; then
+        iniset $HEAT_CONF trustee auth_plugin password
+        iniset $HEAT_CONF trustee auth_url $KEYSTONE_AUTH_URI
+        iniset $HEAT_CONF trustee username $HEAT_TRUSTEE_USER
+        iniset $HEAT_CONF trustee password $HEAT_TRUSTEE_PASSWORD
+        iniset $HEAT_CONF trustee user_domain_id $HEAT_TRUSTEE_DOMAIN
+    fi
+
+    # clients_keystone
+    iniset $HEAT_CONF clients_keystone auth_uri $KEYSTONE_AUTH_URI
+
     # ec2authtoken
     iniset $HEAT_CONF ec2authtoken auth_uri $KEYSTONE_SERVICE_URI/v2.0
 
diff --git a/lib/ironic b/lib/ironic
deleted file mode 100644
index dd4f8bf..0000000
--- a/lib/ironic
+++ /dev/null
@@ -1,874 +0,0 @@
-#!/bin/bash
-#
-# lib/ironic
-# Functions to control the configuration and operation of the **Ironic** service
-
-# Dependencies:
-#
-# - ``functions`` file
-# - ``DEST``, ``DATA_DIR``, ``STACK_USER`` must be defined
-# - ``SERVICE_{TENANT_NAME|PASSWORD}`` must be defined
-# - ``SERVICE_HOST``
-# - ``KEYSTONE_TOKEN_FORMAT`` must be defined
-
-# ``stack.sh`` calls the entry points in this order:
-#
-# - install_ironic
-# - install_ironicclient
-# - init_ironic
-# - start_ironic
-# - stop_ironic
-# - cleanup_ironic
-
-# Save trace and pipefail settings
-_XTRACE_IRONIC=$(set +o | grep xtrace)
-_PIPEFAIL_IRONIC=$(set +o | grep pipefail)
-set +o xtrace
-set +o pipefail
-
-# NOTE(jroll) this is used for the transition to a devstack plugin in
-# the ironic tree.
-IRONIC_USING_PLUGIN=$(trueorfalse False IRONIC_USING_PLUGIN)
-if [[ "$IRONIC_USING_PLUGIN" == "True" ]] ; then
-    return 0
-fi
-
-# Defaults
-# --------
-
-# Set up default directories
-GITDIR["python-ironicclient"]=$DEST/python-ironicclient
-GITDIR["ironic-lib"]=$DEST/ironic-lib
-
-IRONIC_DIR=$DEST/ironic
-IRONIC_PYTHON_AGENT_DIR=$DEST/ironic-python-agent
-IRONIC_DATA_DIR=$DATA_DIR/ironic
-IRONIC_STATE_PATH=/var/lib/ironic
-IRONIC_AUTH_CACHE_DIR=${IRONIC_AUTH_CACHE_DIR:-/var/cache/ironic}
-IRONIC_CONF_DIR=${IRONIC_CONF_DIR:-/etc/ironic}
-IRONIC_CONF_FILE=$IRONIC_CONF_DIR/ironic.conf
-IRONIC_ROOTWRAP_CONF=$IRONIC_CONF_DIR/rootwrap.conf
-IRONIC_POLICY_JSON=$IRONIC_CONF_DIR/policy.json
-
-# Deploy callback timeout can be changed from its default (1800), if required.
-IRONIC_CALLBACK_TIMEOUT=${IRONIC_CALLBACK_TIMEOUT:-}
-
-# 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.
-#
-#   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_NODE_UUID=${IRONIC_NODE_UUID:-`uuidgen`}
-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_ENABLED_DRIVERS=${IRONIC_ENABLED_DRIVERS:-fake,pxe_ssh,pxe_ipmitool}
-IRONIC_SSH_USERNAME=${IRONIC_SSH_USERNAME:-`whoami`}
-IRONIC_SSH_TIMEOUT=${IRONIC_SSH_TIMEOUT:-15}
-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_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}
-IRONIC_VM_SPECS_CPU=${IRONIC_VM_SPECS_CPU:-1}
-IRONIC_VM_SPECS_RAM=${IRONIC_VM_SPECS_RAM:-512}
-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/}
-
-# Use DIB to create deploy ramdisk and kernel.
-IRONIC_BUILD_DEPLOY_RAMDISK=$(trueorfalse True IRONIC_BUILD_DEPLOY_RAMDISK)
-# If not use DIB, these files are used as deploy ramdisk/kernel.
-# (The value must be an absolute path)
-IRONIC_DEPLOY_RAMDISK=${IRONIC_DEPLOY_RAMDISK:-}
-IRONIC_DEPLOY_KERNEL=${IRONIC_DEPLOY_KERNEL:-}
-IRONIC_DEPLOY_ELEMENT=${IRONIC_DEPLOY_ELEMENT:-deploy-ironic}
-
-IRONIC_AGENT_KERNEL_URL=${IRONIC_AGENT_KERNEL_URL:-http://tarballs.openstack.org/ironic-python-agent/coreos/files/coreos_production_pxe.vmlinuz}
-IRONIC_AGENT_RAMDISK_URL=${IRONIC_AGENT_RAMDISK_URL:-http://tarballs.openstack.org/ironic-python-agent/coreos/files/coreos_production_pxe_image-oem.cpio.gz}
-
-# Which deploy driver to use - valid choices right now
-# 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
-IRONIC_DEPLOY_FLAVOR=${IRONIC_DEPLOY_FLAVOR:-ubuntu $IRONIC_DEPLOY_ELEMENT}
-
-# Support entry points installation of console scripts
-IRONIC_BIN_DIR=$(get_python_exec_prefix)
-
-# Ironic connection info.  Note the port must be specified.
-IRONIC_SERVICE_PROTOCOL=http
-IRONIC_SERVICE_PORT=${IRONIC_SERVICE_PORT:-6385}
-IRONIC_HOSTPORT=${IRONIC_HOSTPORT:-$SERVICE_HOST:$IRONIC_SERVICE_PORT}
-
-# Enable iPXE
-IRONIC_IPXE_ENABLED=$(trueorfalse False IRONIC_IPXE_ENABLED)
-IRONIC_HTTP_DIR=${IRONIC_HTTP_DIR:-$IRONIC_DATA_DIR/httpboot}
-IRONIC_HTTP_SERVER=${IRONIC_HTTP_SERVER:-$HOST_IP}
-IRONIC_HTTP_PORT=${IRONIC_HTTP_PORT:-8088}
-
-# NOTE(lucasagomes): This flag is used to differentiate the nodes that
-# uses IPA as their deploy ramdisk from nodes that uses the agent_* drivers
-# (which also uses IPA but depends on Swift Temp URLs to work). At present,
-# all drivers that uses the iSCSI approach for their deployment supports
-# using both, IPA or bash ramdisks for the deployment. In the future we
-# want to remove the support for the bash ramdisk in favor of IPA, once
-# we get there this flag can be removed, and all conditionals that uses
-# it should just run by default.
-IRONIC_DEPLOY_DRIVER_ISCSI_WITH_IPA=$(trueorfalse False IRONIC_DEPLOY_DRIVER_ISCSI_WITH_IPA)
-
-# get_pxe_boot_file() - Get the PXE/iPXE boot file path
-function get_pxe_boot_file {
-    local relpath=syslinux/pxelinux.0
-    if [[ "$IRONIC_IPXE_ENABLED" == "True" ]] ; then
-        relpath=ipxe/undionly.kpxe
-    fi
-
-    local pxe_boot_file
-    if is_ubuntu; then
-        pxe_boot_file=/usr/lib/$relpath
-    elif is_fedora || is_suse; then
-        pxe_boot_file=/usr/share/$relpath
-    fi
-
-    echo $pxe_boot_file
-}
-
-# PXE boot image
-IRONIC_PXE_BOOT_IMAGE=${IRONIC_PXE_BOOT_IMAGE:-$(get_pxe_boot_file)}
-
-
-# Functions
-# ---------
-
-# Test if any Ironic services are enabled
-# is_ironic_enabled
-function is_ironic_enabled {
-    [[ ,${ENABLED_SERVICES} =~ ,"ir-" ]] && return 0
-    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
-}
-
-function is_deployed_with_ipa_ramdisk {
-    is_deployed_by_agent || [[ "$IRONIC_DEPLOY_DRIVER_ISCSI_WITH_IPA" == "True" ]] && return 0
-    return 1
-}
-
-# install_ironic() - Collect source and prepare
-function install_ironic {
-    # make sure all needed service were enabled
-    local req_services="key"
-    if [[ "$VIRT_DRIVER" == "ironic" ]]; then
-        req_services+=" nova glance neutron"
-    fi
-    for srv in $req_services; do
-        if ! is_service_enabled "$srv"; then
-            die $LINENO "$srv should be enabled for Ironic."
-        fi
-    done
-
-    if use_library_from_git "ironic-lib"; then
-        git_clone_by_name "ironic-lib"
-        setup_dev_lib "ironic-lib"
-    fi
-
-    git_clone $IRONIC_REPO $IRONIC_DIR $IRONIC_BRANCH
-    setup_develop $IRONIC_DIR
-
-    if [[ "$IRONIC_IPXE_ENABLED" == "True" ]] ; then
-        install_apache_wsgi
-    fi
-}
-
-# install_ironicclient() - Collect sources and prepare
-function install_ironicclient {
-    if use_library_from_git "python-ironicclient"; then
-        git_clone_by_name "python-ironicclient"
-        setup_dev_lib "python-ironicclient"
-        sudo install -D -m 0644 -o $STACK_USER {${GITDIR["python-ironicclient"]}/tools/,/etc/bash_completion.d/}ironic.bash_completion
-    else
-        # nothing actually "requires" ironicclient, so force instally from pypi
-        pip_install_gr python-ironicclient
-    fi
-}
-
-# _cleanup_ironic_apache_wsgi() - Remove wsgi files, disable and remove apache vhost file
-function _cleanup_ironic_apache_wsgi {
-    sudo rm -rf $IRONIC_HTTP_DIR
-    disable_apache_site ironic
-    sudo rm -f $(apache_site_config_for ironic)
-    restart_apache_server
-}
-
-# _config_ironic_apache_wsgi() - Set WSGI config files of Ironic
-function _config_ironic_apache_wsgi {
-    local ironic_apache_conf
-    ironic_apache_conf=$(apache_site_config_for ironic)
-    sudo cp $FILES/apache-ironic.template $ironic_apache_conf
-    sudo sed -e "
-        s|%PUBLICPORT%|$IRONIC_HTTP_PORT|g;
-        s|%HTTPROOT%|$IRONIC_HTTP_DIR|g;
-    " -i $ironic_apache_conf
-    enable_apache_site ironic
-}
-
-# 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 $IRONIC_CONF_DIR
-}
-
-# configure_ironic_dirs() - Create all directories required by Ironic and
-# associated services.
-function configure_ironic_dirs {
-    sudo install -d -o $STACK_USER $IRONIC_CONF_DIR $STACK_USER $IRONIC_DATA_DIR \
-        $IRONIC_STATE_PATH $IRONIC_TFTPBOOT_DIR $IRONIC_TFTPBOOT_DIR/pxelinux.cfg
-    sudo chown -R $STACK_USER:$LIBVIRT_GROUP $IRONIC_TFTPBOOT_DIR
-
-    if [[ "$IRONIC_IPXE_ENABLED" == "True" ]] ; then
-        sudo install -d -o $STACK_USER -g $LIBVIRT_GROUP $IRONIC_HTTP_DIR
-    fi
-
-    if [ ! -f $IRONIC_PXE_BOOT_IMAGE ]; then
-        die $LINENO "PXE boot file $IRONIC_PXE_BOOT_IMAGE not found."
-    fi
-
-    # Copy PXE binary
-    if [[ "$IRONIC_IPXE_ENABLED" == "True" ]] ; then
-        cp $IRONIC_PXE_BOOT_IMAGE $IRONIC_TFTPBOOT_DIR
-    else
-        # Syslinux >= 5.00 pxelinux.0 binary is not "stand-alone" anymore,
-        # it depends on some c32 modules to work correctly.
-        # More info: http://www.syslinux.org/wiki/index.php/Library_modules
-        cp -aR $(dirname $IRONIC_PXE_BOOT_IMAGE)/*.{c32,0} $IRONIC_TFTPBOOT_DIR
-    fi
-}
-
-# configure_ironic() - Set config files, create data dirs, etc
-function configure_ironic {
-    configure_ironic_dirs
-
-    # Copy over ironic configuration file and configure common parameters.
-    cp $IRONIC_DIR/etc/ironic/ironic.conf.sample $IRONIC_CONF_FILE
-    iniset $IRONIC_CONF_FILE DEFAULT debug True
-    inicomment $IRONIC_CONF_FILE DEFAULT log_file
-    iniset $IRONIC_CONF_FILE database connection `database_connection_url ironic`
-    iniset $IRONIC_CONF_FILE DEFAULT state_path $IRONIC_STATE_PATH
-    iniset $IRONIC_CONF_FILE DEFAULT use_syslog $SYSLOG
-    # Configure Ironic conductor, if it was enabled.
-    if is_service_enabled ir-cond; then
-        configure_ironic_conductor
-    fi
-
-    # Configure Ironic API, if it was enabled.
-    if is_service_enabled ir-api; then
-        configure_ironic_api
-    fi
-
-    # Format logging
-    if [ "$LOG_COLOR" == "True" ] && [ "$SYSLOG" == "False" ]; then
-        setup_colorized_logging $IRONIC_CONF_FILE DEFAULT tenant user
-    fi
-
-    if [[ "$IRONIC_IPXE_ENABLED" == "True" ]]; then
-        _config_ironic_apache_wsgi
-    fi
-}
-
-# configure_ironic_api() - Is used by configure_ironic(). Performs
-# API specific configuration.
-function configure_ironic_api {
-    iniset $IRONIC_CONF_FILE DEFAULT auth_strategy keystone
-    iniset $IRONIC_CONF_FILE oslo_policy policy_file $IRONIC_POLICY_JSON
-
-    # TODO(Yuki Nishiwaki): This is a temporary work-around until Ironic is fixed(bug#1422632).
-    # These codes need to be changed to use the function of configure_auth_token_middleware
-    # after Ironic conforms to the new auth plugin.
-    iniset $IRONIC_CONF_FILE keystone_authtoken identity_uri $KEYSTONE_AUTH_URI
-    iniset $IRONIC_CONF_FILE keystone_authtoken auth_uri $KEYSTONE_SERVICE_URI/v2.0
-    iniset $IRONIC_CONF_FILE keystone_authtoken admin_user ironic
-    iniset $IRONIC_CONF_FILE keystone_authtoken admin_password $SERVICE_PASSWORD
-    iniset $IRONIC_CONF_FILE keystone_authtoken admin_tenant_name $SERVICE_TENANT_NAME
-    iniset $IRONIC_CONF_FILE keystone_authtoken cafile $SSL_BUNDLE_FILE
-    iniset $IRONIC_CONF_FILE keystone_authtoken signing_dir $IRONIC_AUTH_CACHE_DIR/api
-
-    iniset_rpc_backend ironic $IRONIC_CONF_FILE
-    iniset $IRONIC_CONF_FILE api port $IRONIC_SERVICE_PORT
-
-    cp -p $IRONIC_DIR/etc/ironic/policy.json $IRONIC_POLICY_JSON
-}
-
-# configure_ironic_conductor() - Is used by configure_ironic().
-# Sets conductor specific settings.
-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
-    local ironic_rootwrap
-    ironic_rootwrap=$(get_rootwrap_location ironic)
-    local rootwrap_isudoer_cmd="$ironic_rootwrap $IRONIC_CONF_DIR/rootwrap.conf *"
-
-    # Set up the rootwrap sudoers for ironic
-    local tempfile
-    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 enabled_drivers $IRONIC_ENABLED_DRIVERS
-    iniset $IRONIC_CONF_FILE conductor api_url $IRONIC_SERVICE_PROTOCOL://$HOST_IP:$IRONIC_SERVICE_PORT
-    if [[ -n "$IRONIC_CALLBACK_TIMEOUT" ]]; then
-        iniset $IRONIC_CONF_FILE conductor deploy_callback_timeout $IRONIC_CALLBACK_TIMEOUT
-    fi
-    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
-
-    local pxe_params=""
-    if [[ "$IRONIC_VM_LOG_CONSOLE" == "True" ]] ; then
-        pxe_params+="nofb nomodeset vga=normal console=ttyS0"
-        if is_deployed_with_ipa_ramdisk; then
-            pxe_params+=" systemd.journald.forward_to_console=yes"
-        fi
-    fi
-    # When booting with less than 1GB, we need to switch from default tmpfs
-    # to ramfs for ramdisks to decompress successfully.
-    if (is_ironic_hardware && [[ "$IRONIC_HW_NODE_RAM" -lt 1024 ]]) ||
-        (! is_ironic_hardware && [[ "$IRONIC_VM_SPECS_RAM" -lt 1024 ]]); then
-        pxe_params+=" rootfstype=ramfs"
-    fi
-    if [[ -n "$pxe_params" ]]; then
-        iniset $IRONIC_CONF_FILE pxe pxe_append_params "$pxe_params"
-    fi
-
-    # Set these options for scenarios in which the agent fetches the image
-    # directly from glance, and don't set them where the image is pushed
-    # over iSCSI.
-    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
-            die $LINENO "SWIFT_ENABLE_TEMPURLS must be True to use agent_ssh driver in Ironic."
-        fi
-        iniset $IRONIC_CONF_FILE glance swift_endpoint_url http://${HOST_IP}:${SWIFT_DEFAULT_BIND_PORT:-8080}
-        iniset $IRONIC_CONF_FILE glance swift_api_version v1
-        local tenant_id
-        tenant_id=$(get_or_create_project $SERVICE_TENANT_NAME default)
-        iniset $IRONIC_CONF_FILE glance swift_account AUTH_${tenant_id}
-        iniset $IRONIC_CONF_FILE glance swift_container glance
-        iniset $IRONIC_CONF_FILE glance swift_temp_url_duration 3600
-        iniset $IRONIC_CONF_FILE agent heartbeat_timeout 30
-    fi
-
-    # FIXME: this really needs to be tested in the gate.
-    # For now, any test using the agent ramdisk should skip cleaning
-    # because it is too slow to run in the gate.
-    iniset $IRONIC_CONF_FILE agent agent_erase_devices_priority 0
-
-    if [[ "$IRONIC_IPXE_ENABLED" == "True" ]] ; then
-        local pxebin
-        pxebin=`basename $IRONIC_PXE_BOOT_IMAGE`
-        iniset $IRONIC_CONF_FILE pxe ipxe_enabled True
-        iniset $IRONIC_CONF_FILE pxe pxe_config_template '\$pybasedir/drivers/modules/ipxe_config.template'
-        iniset $IRONIC_CONF_FILE pxe pxe_bootfile_name $pxebin
-        iniset $IRONIC_CONF_FILE pxe http_root $IRONIC_HTTP_DIR
-        iniset $IRONIC_CONF_FILE pxe http_url "http://$IRONIC_HTTP_SERVER:$IRONIC_HTTP_PORT"
-    fi
-}
-
-# create_ironic_cache_dir() - Part of the init_ironic() process
-function create_ironic_cache_dir {
-    # Create cache dir
-    sudo mkdir -p $IRONIC_AUTH_CACHE_DIR/api
-    sudo chown $STACK_USER $IRONIC_AUTH_CACHE_DIR/api
-    rm -f $IRONIC_AUTH_CACHE_DIR/api/*
-    sudo mkdir -p $IRONIC_AUTH_CACHE_DIR/registry
-    sudo chown $STACK_USER $IRONIC_AUTH_CACHE_DIR/registry
-    rm -f $IRONIC_AUTH_CACHE_DIR/registry/*
-}
-
-# create_ironic_accounts() - Set up common required ironic accounts
-
-# Tenant               User       Roles
-# ------------------------------------------------------------------
-# service              ironic     admin        # if enabled
-function create_ironic_accounts {
-
-    # Ironic
-    if [[ "$ENABLED_SERVICES" =~ "ir-api" ]]; then
-        # Get ironic user if exists
-
-        # NOTE(Shrews): This user MUST have admin level privileges!
-        create_service_user "ironic" "admin"
-
-        if [[ "$KEYSTONE_CATALOG_BACKEND" = 'sql' ]]; then
-
-            get_or_create_service "ironic" "baremetal" "Ironic baremetal provisioning service"
-            get_or_create_endpoint "baremetal" \
-                "$REGION_NAME" \
-                "$IRONIC_SERVICE_PROTOCOL://$IRONIC_HOSTPORT" \
-                "$IRONIC_SERVICE_PROTOCOL://$IRONIC_HOSTPORT" \
-                "$IRONIC_SERVICE_PROTOCOL://$IRONIC_HOSTPORT"
-        fi
-    fi
-}
-
-
-# init_ironic() - Initialize databases, etc.
-function init_ironic {
-    # Save private network as cleaning network
-    local cleaning_network_uuid
-    cleaning_network_uuid=$(neutron net-list | grep private | get_field 1)
-    iniset $IRONIC_CONF_FILE neutron cleaning_network_uuid ${cleaning_network_uuid}
-
-    # (Re)create  ironic database
-    recreate_database ironic
-
-    # Migrate ironic database
-    $IRONIC_BIN_DIR/ironic-dbsync --config-file=$IRONIC_CONF_FILE
-
-    create_ironic_cache_dir
-}
-
-# _ironic_bm_vm_names() - Generates list of names for baremetal VMs.
-function _ironic_bm_vm_names {
-    local idx
-    local num_vms
-    num_vms=$(($IRONIC_VM_COUNT - 1))
-    for idx in $(seq 0 $num_vms); do
-        echo "baremetal${IRONIC_VM_NETWORK_BRIDGE}_${idx}"
-    done
-}
-
-# start_ironic() - Start running processes, including screen
-function start_ironic {
-    # Start Ironic API server, if enabled.
-    if is_service_enabled ir-api; then
-        start_ironic_api
-    fi
-
-    # Start Ironic conductor, if enabled.
-    if is_service_enabled ir-cond; then
-        start_ironic_conductor
-    fi
-
-    # Start Apache if iPXE is enabled
-    if [[ "$IRONIC_IPXE_ENABLED" == "True" ]] ; then
-        restart_apache_server
-    fi
-}
-
-# start_ironic_api() - Used by start_ironic().
-# Starts Ironic API server.
-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- $IRONIC_SERVICE_PROTOCOL://$IRONIC_HOSTPORT; do sleep 1; done"; then
-        die $LINENO "ir-api did not start"
-    fi
-}
-
-# start_ironic_conductor() - Used by start_ironic().
-# Starts Ironic conductor.
-function start_ironic_conductor {
-    run_process ir-cond "$IRONIC_BIN_DIR/ironic-conductor --config-file=$IRONIC_CONF_FILE"
-    # TODO(romcheg): Find a way to check whether the conductor has started.
-}
-
-# stop_ironic() - Stop running processes
-function stop_ironic {
-    stop_process ir-api
-    stop_process ir-cond
-
-    # Cleanup the WSGI files
-    if [[ "$IRONIC_IPXE_ENABLED" == "True" ]] ; then
-        _cleanup_ironic_apache_wsgi
-    fi
-}
-
-function create_ovs_taps {
-    local ironic_net_id
-    ironic_net_id=$(neutron net-list | grep private | get_field 1)
-
-    # Work around: No netns exists on host until a Neutron port is created.  We
-    # need to create one in Neutron to know what netns to tap into prior to the
-    # first node booting.
-    local port_id
-    port_id=$(neutron port-create private | grep " id " | get_field 2)
-
-    # intentional sleep to make sure the tag has been set to port
-    sleep 10
-
-    local tapdev
-    tapdev=$(sudo ip netns exec qdhcp-${ironic_net_id} ip link list | grep " tap" | cut -d':' -f2 | cut -d'@' -f1 | cut -b2-)
-    local tag_id
-    tag_id=$(sudo ovs-vsctl show |grep ${tapdev} -A1 -m1 | grep tag | cut -d':' -f2 | cut -b2-)
-
-    # make sure veth pair is not existing, otherwise delete its links
-    sudo ip link show ovs-tap1 && sudo ip link delete ovs-tap1
-    sudo ip link show brbm-tap1 && sudo ip link delete brbm-tap1
-    # create veth pair for future interconnection between br-int and brbm
-    sudo ip link add brbm-tap1 type veth peer name ovs-tap1
-    sudo ip link set dev brbm-tap1 up
-    sudo ip link set dev ovs-tap1 up
-
-    sudo ovs-vsctl -- --if-exists del-port ovs-tap1 -- add-port br-int ovs-tap1 tag=$tag_id
-    sudo ovs-vsctl -- --if-exists del-port brbm-tap1 -- add-port $IRONIC_VM_NETWORK_BRIDGE brbm-tap1
-
-    # Remove the port needed only for workaround.
-    neutron port-delete $port_id
-
-    # Finally, share the fixed tenant network across all tenants.  This allows the host
-    # to serve TFTP to a single network namespace via the tap device created above.
-    neutron net-update $ironic_net_id --shared true
-}
-
-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
-        local log_arg="$IRONIC_VM_LOG_DIR"
-    else
-        local log_arg=""
-    fi
-    local vm_name
-    for vm_name in $(_ironic_bm_vm_names); do
-        sudo su $STACK_USER -c "$IRONIC_SCRIPTS_DIR/create-node $vm_name \
-            $IRONIC_VM_SPECS_CPU $IRONIC_VM_SPECS_RAM $IRONIC_VM_SPECS_DISK \
-            amd64 $IRONIC_VM_NETWORK_BRIDGE $IRONIC_VM_EMULATOR \
-            $log_arg" >> $IRONIC_VM_MACS_CSV_FILE
-    done
-    create_ovs_taps
-}
-
-function wait_for_nova_resources {
-    # After nodes have been enrolled, we need to wait for both ironic and
-    # nova's periodic tasks to populate the resource tracker with available
-    # nodes and resources. Wait up to 2 minutes for a given resource before
-    # timing out.
-    local resource=$1
-    local expected_count=$2
-    local i
-    echo_summary "Waiting 2 minutes for Nova resource tracker to pick up $resource >= $expected_count"
-    for i in $(seq 1 120); do
-        if [ $(nova hypervisor-stats | grep " $resource " | get_field 2) -ge $expected_count ]; then
-            return 0
-        fi
-        sleep 1
-    done
-    die $LINENO "Timed out waiting for Nova hypervisor-stats $resource >= $expected_count"
-}
-
-function enroll_nodes {
-    local chassis_id
-    chassis_id=$(ironic chassis-create -d "ironic test chassis" | grep " uuid " | get_field 2)
-
-    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 deploy_kernel=$IRONIC_DEPLOY_KERNEL_ID \
-            -i deploy_ramdisk=$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_KEY_FILE"
-    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
-
-    local total_nodes=0
-    local total_cpus=0
-    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
-            ipmi_address=$(echo $hardware_info |awk  '{print $1}')
-            local mac_address
-            mac_address=$(echo $hardware_info |awk '{print $2}')
-            local ironic_ipmi_username
-            ironic_ipmi_username=$(echo $hardware_info |awk '{print $3}')
-            local ironic_ipmi_passwd
-            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"
-            node_options+=" -i deploy_kernel=$IRONIC_DEPLOY_KERNEL_ID"
-            node_options+=" -i deploy_ramdisk=$IRONIC_DEPLOY_RAMDISK_ID"
-        fi
-
-        # First node created will be used for testing in ironic w/o glance
-        # scenario, so we need to know its UUID.
-        local standalone_node_uuid=""
-        if [ $total_nodes -eq 0 ]; then
-            standalone_node_uuid="--uuid $IRONIC_NODE_UUID"
-        fi
-
-        local node_id
-        node_id=$(ironic node-create $standalone_node_uuid\
-            --chassis_uuid $chassis_id \
-            --driver $IRONIC_DEPLOY_DRIVER \
-            --name node-$total_nodes \
-            -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_address --node $node_id
-
-        total_nodes=$((total_nodes+1))
-        total_cpus=$((total_cpus+$ironic_node_cpu))
-    done < $ironic_hwinfo_file
-
-    local adjusted_disk
-    adjusted_disk=$(($ironic_node_disk - $ironic_ephemeral_disk))
-    nova flavor-create --ephemeral $ironic_ephemeral_disk baremetal auto $ironic_node_ram $adjusted_disk $ironic_node_cpu
-
-    nova flavor-key baremetal set "cpu_arch"="x86_64"
-
-    if [ "$VIRT_DRIVER" == "ironic" ]; then
-        wait_for_nova_resources "count" $total_nodes
-        wait_for_nova_resources "vcpus" $total_cpus
-    fi
-}
-
-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
-    # explicitly allow DHCP - packets are occasionally being dropped here
-    sudo iptables -I INPUT -p udp --dport 67:68 --sport 67:68 -j ACCEPT || true
-    # 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_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
-
-    if [[ "$IRONIC_IPXE_ENABLED" == "True" ]] ; then
-        sudo iptables -I INPUT -d $HOST_IP -p tcp --dport $IRONIC_HTTP_PORT -j ACCEPT || true
-    fi
-}
-
-function configure_tftpd {
-    # stop tftpd and setup serving via xinetd
-    stop_service tftpd-hpa || true
-    [ -f /etc/init/tftpd-hpa.conf ] && echo "manual" | sudo tee /etc/init/tftpd-hpa.override
-    sudo cp $IRONIC_TEMPLATES_DIR/tftpd-xinetd.template /etc/xinetd.d/tftp
-    sudo sed -e "s|%TFTPBOOT_DIR%|$IRONIC_TFTPBOOT_DIR|g" -i /etc/xinetd.d/tftp
-
-    # setup tftp file mapping to satisfy requests at the root (booting) and
-    # /tftpboot/ sub-dir (as per deploy-ironic elements)
-    echo "r ^([^/]) $IRONIC_TFTPBOOT_DIR/\1" >$IRONIC_TFTPBOOT_DIR/map-file
-    echo "r ^(/tftpboot/) $IRONIC_TFTPBOOT_DIR/\2" >>$IRONIC_TFTPBOOT_DIR/map-file
-
-    chmod -R 0755 $IRONIC_TFTPBOOT_DIR
-    restart_service xinetd
-}
-
-function configure_ironic_ssh_keypair {
-    if [[ ! -d $HOME/.ssh ]]; then
-        mkdir -p $HOME/.ssh
-        chmod 700 $HOME/.ssh
-    fi
-    if [[ ! -e $IRONIC_KEY_FILE ]]; then
-        if [[ ! -d $(dirname $IRONIC_KEY_FILE) ]]; then
-            mkdir -p $(dirname $IRONIC_KEY_FILE)
-        fi
-        echo -e 'n\n' | ssh-keygen -q -t rsa -P '' -f $IRONIC_KEY_FILE
-    fi
-    cat $IRONIC_KEY_FILE.pub | tee -a $IRONIC_AUTHORIZED_KEYS_FILE
-}
-
-function ironic_ssh_check {
-    local key_file=$1
-    local floating_ip=$2
-    local port=$3
-    local default_instance_user=$4
-    local active_timeout=$5
-    if ! timeout $active_timeout sh -c "while ! ssh -p $port -o StrictHostKeyChecking=no -i $key_file ${default_instance_user}@$floating_ip echo success; do sleep 1; done"; then
-        die $LINENO "server didn't become ssh-able!"
-    fi
-}
-
-function configure_ironic_auxiliary {
-    configure_ironic_ssh_keypair
-    ironic_ssh_check $IRONIC_KEY_FILE $IRONIC_VM_SSH_ADDRESS $IRONIC_VM_SSH_PORT $IRONIC_SSH_USERNAME $IRONIC_SSH_TIMEOUT
-}
-
-function build_ipa_coreos_ramdisk {
-    echo "Building ironic-python-agent deploy ramdisk"
-    local kernel_path=$1
-    local ramdisk_path=$2
-    git_clone $IRONIC_PYTHON_AGENT_REPO $IRONIC_PYTHON_AGENT_DIR $IRONIC_PYTHON_AGENT_BRANCH
-    cd $IRONIC_PYTHON_AGENT_DIR
-    imagebuild/coreos/build_coreos_image.sh
-    cp imagebuild/coreos/UPLOAD/coreos_production_pxe_image-oem.cpio.gz $ramdisk_path
-    cp imagebuild/coreos/UPLOAD/coreos_production_pxe.vmlinuz $kernel_path
-    sudo rm -rf UPLOAD
-    cd -
-}
-
-# build deploy kernel+ramdisk, then upload them to glance
-# this function sets ``IRONIC_DEPLOY_KERNEL_ID``, ``IRONIC_DEPLOY_RAMDISK_ID``
-function upload_baremetal_ironic_deploy {
-    declare -g IRONIC_DEPLOY_KERNEL_ID IRONIC_DEPLOY_RAMDISK_ID
-    echo_summary "Creating and uploading baremetal images for ironic"
-
-    # install diskimage-builder
-    if [[ $(type -P ramdisk-image-create) == "" ]]; then
-        pip_install_gr "diskimage-builder"
-    fi
-
-    if [ -z "$IRONIC_DEPLOY_KERNEL" -o -z "$IRONIC_DEPLOY_RAMDISK" ]; then
-        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
-    fi
-
-    if [ ! -e "$IRONIC_DEPLOY_RAMDISK_PATH" -o ! -e "$IRONIC_DEPLOY_KERNEL_PATH" ]; then
-        # files don't exist, need to build them
-        if [ "$IRONIC_BUILD_DEPLOY_RAMDISK" = "True" ]; then
-            # we can build them only if we're not offline
-            if [ "$OFFLINE" != "True" ]; then
-                if is_deployed_with_ipa_ramdisk; 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-$IRONIC_DEPLOY_DRIVER
-                fi
-            else
-                die $LINENO "Deploy kernel+ramdisk files don't exist and cannot be build in OFFLINE mode"
-            fi
-        else
-            if is_deployed_with_ipa_ramdisk; 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
-            else
-                die $LINENO "Deploy kernel+ramdisk files don't exist and their building was disabled explicitly by IRONIC_BUILD_DEPLOY_RAMDISK"
-            fi
-        fi
-    fi
-
-    local token
-    token=$(openstack token issue -c id -f value)
-    die_if_not_set $LINENO token "Keystone fail to get token"
-
-    # load them into glance
-    IRONIC_DEPLOY_KERNEL_ID=$(openstack \
-        --os-token $token \
-        --os-url $GLANCE_SERVICE_PROTOCOL://$GLANCE_HOSTPORT \
-        image create \
-        $(basename $IRONIC_DEPLOY_KERNEL_PATH) \
-        --public --disk-format=aki \
-        --container-format=aki \
-        < $IRONIC_DEPLOY_KERNEL_PATH  | grep ' id ' | get_field 2)
-    IRONIC_DEPLOY_RAMDISK_ID=$(openstack \
-        --os-token $token \
-        --os-url $GLANCE_SERVICE_PROTOCOL://$GLANCE_HOSTPORT \
-        image create \
-        $(basename $IRONIC_DEPLOY_RAMDISK_PATH) \
-        --public --disk-format=ari \
-        --container-format=ari \
-        < $IRONIC_DEPLOY_RAMDISK_PATH  | grep ' id ' | get_field 2)
-}
-
-function prepare_baremetal_basic_ops {
-    if ! is_ironic_hardware; then
-        configure_ironic_auxiliary
-    fi
-    upload_baremetal_ironic_deploy
-    if ! is_ironic_hardware; then
-        create_bridge_and_vms
-    fi
-    enroll_nodes
-    configure_tftpd
-    configure_iptables
-}
-
-function cleanup_baremetal_basic_ops {
-    rm -f $IRONIC_VM_MACS_CSV_FILE
-    if [ -f $IRONIC_KEY_FILE ]; then
-        local key
-        key=$(cat $IRONIC_KEY_FILE.pub)
-        # remove public key from authorized_keys
-        grep -v "$key" $IRONIC_AUTHORIZED_KEYS_FILE > temp && mv temp $IRONIC_AUTHORIZED_KEYS_FILE
-        chmod 0600 $IRONIC_AUTHORIZED_KEYS_FILE
-    fi
-    sudo rm -rf $IRONIC_DATA_DIR $IRONIC_STATE_PATH
-
-    local vm_name
-    for vm_name in $(_ironic_bm_vm_names); do
-        sudo su $STACK_USER -c "$IRONIC_SCRIPTS_DIR/cleanup-node $vm_name $IRONIC_VM_NETWORK_BRIDGE"
-    done
-
-    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 $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
-    sudo rmmod nf_conntrack_tftp || true
-    sudo rmmod nf_nat_tftp || true
-}
-
-# Restore xtrace + pipefail
-$_XTRACE_IRONIC
-$_PIPEFAIL_IRONIC
-
-# Tell emacs to use shell-script-mode
-## Local variables:
-## mode: shell-script
-## End:
diff --git a/lib/keystone b/lib/keystone
index 6b4118d..b4b7df9 100644
--- a/lib/keystone
+++ b/lib/keystone
@@ -52,10 +52,6 @@
 KEYSTONE_CONF=$KEYSTONE_CONF_DIR/keystone.conf
 KEYSTONE_PASTE_INI=${KEYSTONE_PASTE_INI:-$KEYSTONE_CONF_DIR/keystone-paste.ini}
 
-# Set up additional extensions, such as oauth1, federation
-# Example of KEYSTONE_EXTENSIONS=oauth1,federation
-KEYSTONE_EXTENSIONS=${KEYSTONE_EXTENSIONS:-}
-
 # Toggle for deploying Keystone under HTTPD + mod_wsgi
 KEYSTONE_USE_MOD_WSGI=${KEYSTONE_USE_MOD_WSGI:-${ENABLE_HTTPD_MOD_WSGI_SERVICES}}
 
@@ -192,8 +188,6 @@
         inidelete $KEYSTONE_PASTE_INI composite:admin \\/v2.0
     fi
 
-    configure_keystone_extensions
-
     # Rewrite stock ``keystone.conf``
 
     if is_service_enabled ldap; then
@@ -231,6 +225,9 @@
         # Set the service ports for a proxy to take the originals
         iniset $KEYSTONE_CONF eventlet_server public_port $KEYSTONE_SERVICE_PORT_INT
         iniset $KEYSTONE_CONF eventlet_server admin_port $KEYSTONE_AUTH_PORT_INT
+
+        iniset $KEYSTONE_CONF DEFAULT public_endpoint $KEYSTONE_SERVICE_URI
+        iniset $KEYSTONE_CONF DEFAULT admin_endpoint $KEYSTONE_AUTH_URI
     fi
 
     iniset $KEYSTONE_CONF DEFAULT admin_token "$SERVICE_TOKEN"
@@ -305,25 +302,6 @@
     iniset $KEYSTONE_CONF fernet_tokens key_repository "$KEYSTONE_CONF_DIR/fernet-keys/"
 }
 
-function configure_keystone_extensions {
-    # Add keystone extension into keystone v3 application pipeline
-    local extension_value
-    local api_v3
-    local extension
-    local api_v3_extension
-    for extension_value in ${KEYSTONE_EXTENSIONS//,/ }; do
-        if [[ -z "${extension_value}" ]]; then
-            continue
-        fi
-        api_v3=$(iniget $KEYSTONE_PASTE_INI pipeline:api_v3 pipeline)
-        extension=$(echo $api_v3 | sed -ne "/${extension_value}/ p;" )
-        if [[ -z $extension ]]; then
-            api_v3_extension=$(echo $api_v3 | sed -ne "s/service_v3/${extension_value}_extension service_v3/p;" )
-            iniset $KEYSTONE_PASTE_INI pipeline:api_v3 pipeline "$api_v3_extension"
-        fi
-    done
-}
-
 # create_keystone_accounts() - Sets up common required keystone accounts
 
 # Tenant               User       Roles
@@ -468,14 +446,6 @@
     # Initialize keystone database
     $KEYSTONE_BIN_DIR/keystone-manage db_sync
 
-    local extension_value
-    for extension_value in ${KEYSTONE_EXTENSIONS//,/ }; do
-        if [[ -z "${extension_value}" ]]; then
-            continue
-        fi
-        $KEYSTONE_BIN_DIR/keystone-manage db_sync --extension "${extension_value}"
-    done
-
     if [[ "$KEYSTONE_TOKEN_FORMAT" == "pki" || "$KEYSTONE_TOKEN_FORMAT" == "pkiz" ]]; then
         # Set up certificates
         rm -rf $KEYSTONE_CONF_DIR/ssl
diff --git a/lib/neutron-legacy b/lib/neutron-legacy
index e0c4676..cc5b75e 100644
--- a/lib/neutron-legacy
+++ b/lib/neutron-legacy
@@ -115,6 +115,9 @@
 # Default provider for load balancer service
 DEFAULT_LB_PROVIDER=LOADBALANCER:Haproxy:neutron_lbaas.services.loadbalancer.drivers.haproxy.plugin_driver.HaproxyOnHostPluginDriver:default
 
+# Default provider for VPN service
+DEFAULT_VPN_PROVIDER=VPN:openswan:neutron_vpnaas.services.vpn.service_drivers.ipsec.IPsecVPNDriver:default
+
 # Agent binaries.  Note, binary paths for other agents are set in per-service
 # scripts in lib/neutron_plugins/services/
 AGENT_DHCP_BINARY="$NEUTRON_BIN_DIR/neutron-dhcp-agent"
@@ -168,6 +171,9 @@
 
 ## Provider Network Information
 PROVIDER_SUBNET_NAME=${PROVIDER_SUBNET_NAME:-"provider_net"}
+IPV6_PROVIDER_SUBNET_NAME=${IPV6_PROVIDER_SUBNET_NAME:-"provider_net_v6"}
+IPV6_PROVIDER_FIXED_RANGE=${IPV6_PROVIDER_FIXED_RANGE:-}
+IPV6_PROVIDER_NETWORK_GATEWAY=${IPV6_PROVIDER_NETWORK_GATEWAY:-}
 
 # Define the public bridge that will transmit traffic from VMs to the
 # physical network - used by both the OVS and Linux Bridge drivers.
@@ -548,9 +554,9 @@
             die_if_not_set $LINENO SUBNET_ID "Failure creating SUBNET_ID for $PROVIDER_SUBNET_NAME $TENANT_ID"
         fi
 
-        if [[ "$IP_VERSION" =~ .*6 ]]; then
-            SUBNET_V6_ID=$(neutron subnet-create --tenant_id $TENANT_ID --ip_version 6 --ipv6-address-mode $IPV6_ADDRESS_MODE --gateway $V6_NETWORK_GATEWAY --name $PROVIDER_SUBNET_NAME_V6 --subnetpool_id None $NET_ID $FIXED_RANGE_V6 | grep 'id' | get_field 2)
-            die_if_not_set $LINENO SUBNET_V6_ID "Failure creating SUBNET_V6_ID for $PROVIDER_SUBNET_NAME_V6 $TENANT_ID"
+        if [[ "$IP_VERSION" =~ .*6 ]] && [[ -n "$IPV6_PROVIDER_FIXED_RANGE" ]] && [[ -n "$IPV6_PROVIDER_NETWORK_GATEWAY" ]]; then
+            SUBNET_V6_ID=$(neutron subnet-create --tenant_id $TENANT_ID --ip_version 6 --ipv6-address-mode $IPV6_ADDRESS_MODE --gateway $IPV6_PROVIDER_NETWORK_GATEWAY --name $IPV6_PROVIDER_SUBNET_NAME --subnetpool None $NET_ID $IPV6_PROVIDER_FIXED_RANGE | grep 'id' | get_field 2)
+            die_if_not_set $LINENO SUBNET_V6_ID "Failure creating SUBNET_V6_ID for $IPV6_PROVIDER_SUBNET_NAME $TENANT_ID"
         fi
 
         if [[ $Q_AGENT == "openvswitch" ]]; then
@@ -777,6 +783,10 @@
     if is_service_enabled q-metering; then
         neutron_metering_stop
     fi
+
+    if [[ "$Q_USE_ROOTWRAP_DAEMON" == "True" ]]; then
+        sudo pkill -9 -f $NEUTRON_ROOTWRAP-daemon || :
+    fi
 }
 
 # stop_neutron() - Stop running processes (non-screen)
@@ -1092,6 +1102,7 @@
     (cd $NEUTRON_VPNAAS_DIR && exec ./tools/generate_config_file_samples.sh)
     if [ -f $NEUTRON_VPNAAS_DIR/etc/neutron_vpnaas.conf.sample ]; then
         cp $NEUTRON_VPNAAS_DIR/etc/neutron_vpnaas.conf.sample $NEUTRON_CONF_DIR/neutron_vpnaas.conf
+        iniset $NEUTRON_CONF_DIR/neutron_vpnaas.conf service_providers service_provider $DEFAULT_VPN_PROVIDER
     fi
     neutron_vpn_install_agent_packages
     neutron_vpn_configure_common
diff --git a/lib/tempest b/lib/tempest
index ecc4865..c510984 100644
--- a/lib/tempest
+++ b/lib/tempest
@@ -281,18 +281,12 @@
     # Identity
     iniset $TEMPEST_CONFIG identity uri "$KEYSTONE_SERVICE_PROTOCOL://$KEYSTONE_SERVICE_HOST:5000/v2.0/"
     iniset $TEMPEST_CONFIG identity uri_v3 "$KEYSTONE_SERVICE_URI_V3"
-    iniset $TEMPEST_CONFIG identity username $TEMPEST_USERNAME
-    iniset $TEMPEST_CONFIG identity password "$password"
-    iniset $TEMPEST_CONFIG identity tenant_name $TEMPEST_TENANT_NAME
-    iniset $TEMPEST_CONFIG identity alt_username $ALT_USERNAME
-    iniset $TEMPEST_CONFIG identity alt_password "$password"
-    iniset $TEMPEST_CONFIG identity alt_tenant_name $ALT_TENANT_NAME
     if [[ "$TEMPEST_HAS_ADMIN" == "True" ]]; then
-        iniset $TEMPEST_CONFIG identity admin_username $ADMIN_USERNAME
-        iniset $TEMPEST_CONFIG identity admin_password "$password"
-        iniset $TEMPEST_CONFIG identity admin_tenant_name $ADMIN_TENANT_NAME
-        iniset $TEMPEST_CONFIG identity admin_tenant_id $ADMIN_TENANT_ID
-        iniset $TEMPEST_CONFIG identity admin_domain_name $ADMIN_DOMAIN_NAME
+        iniset $TEMPEST_CONFIG auth admin_username $ADMIN_USERNAME
+        iniset $TEMPEST_CONFIG auth admin_password "$password"
+        iniset $TEMPEST_CONFIG auth admin_tenant_name $ADMIN_TENANT_NAME
+        iniset $TEMPEST_CONFIG auth admin_tenant_id $ADMIN_TENANT_ID
+        iniset $TEMPEST_CONFIG auth admin_domain_name $ADMIN_DOMAIN_NAME
     fi
     if [ "$ENABLE_IDENTITY_V2" == "False" ]; then
         # Only Identity v3 is available; then skip Identity API v2 tests
@@ -319,11 +313,7 @@
 
     # Compute
     iniset $TEMPEST_CONFIG compute ssh_user ${DEFAULT_INSTANCE_USER:-cirros} # DEPRECATED
-    iniset $TEMPEST_CONFIG compute network_for_ssh $PRIVATE_NETWORK_NAME
-    iniset $TEMPEST_CONFIG compute ip_version_for_ssh 4
-    iniset $TEMPEST_CONFIG compute ssh_timeout $BUILD_TIMEOUT
     iniset $TEMPEST_CONFIG compute image_ref $image_uuid
-    iniset $TEMPEST_CONFIG compute image_ssh_user ${DEFAULT_INSTANCE_USER:-cirros}
     iniset $TEMPEST_CONFIG compute image_ref_alt $image_uuid_alt
     iniset $TEMPEST_CONFIG compute image_alt_ssh_user ${ALT_INSTANCE_USER:-cirros}
     iniset $TEMPEST_CONFIG compute flavor_ref $flavor_ref
@@ -483,6 +473,10 @@
 
     # Validation
     iniset $TEMPEST_CONFIG validation run_validation ${TEMPEST_RUN_VALIDATION:-False}
+    iniset $TEMPEST_CONFIG validation ip_version_for_ssh 4
+    iniset $TEMPEST_CONFIG validation ssh_timeout $BUILD_TIMEOUT
+    iniset $TEMPEST_CONFIG validation image_ssh_user ${DEFAULT_INSTANCE_USER:-cirros}
+    iniset $TEMPEST_CONFIG validation network_for_ssh $PRIVATE_NETWORK_NAME
 
     # Volume
     # TODO(dkranz): Remove the bootable flag when Juno is end of life.
@@ -528,7 +522,6 @@
 
     # Dashboard
     iniset $TEMPEST_CONFIG dashboard dashboard_url "http://$SERVICE_HOST/"
-    iniset $TEMPEST_CONFIG dashboard login_url "http://$SERVICE_HOST/auth/login/"
 
     # CLI
     iniset $TEMPEST_CONFIG cli cli_dir $NOVA_BIN_DIR
@@ -595,13 +588,13 @@
         else
             tempest-account-generator -c $TEMPEST_CONFIG --os-username $ADMIN_USERNAME --os-password $ADMIN_PASSWORD --os-tenant-name $ADMIN_TENANT_NAME -r $TEMPEST_CONCURRENCY etc/accounts.yaml
         fi
-        iniset $TEMPEST_CONFIG auth allow_tenant_isolation False
+        iniset $TEMPEST_CONFIG auth use_dynamic_credentials False
         iniset $TEMPEST_CONFIG auth test_accounts_file "etc/accounts.yaml"
     elif [[ $TEMPEST_HAS_ADMIN == "False" ]]; then
-        iniset $TEMPEST_CONFIG auth allow_tenant_isolation ${TEMPEST_ALLOW_TENANT_ISOLATION:-False}
+        iniset $TEMPEST_CONFIG auth use_dynamic_credentials ${TEMPEST_ALLOW_TENANT_ISOLATION:-False}
 
     else
-        iniset $TEMPEST_CONFIG auth allow_tenant_isolation ${TEMPEST_ALLOW_TENANT_ISOLATION:-True}
+        iniset $TEMPEST_CONFIG auth use_dynamic_credentials ${TEMPEST_ALLOW_TENANT_ISOLATION:-True}
     fi
 
     # Restore IFS
diff --git a/stack.sh b/stack.sh
index 09ab474..bc67ce0 100755
--- a/stack.sh
+++ b/stack.sh
@@ -266,9 +266,7 @@
 # Some distros need to add repos beyond the defaults provided by the vendor
 # to pick up required packages.
 
-if is_fedora && [[ $DISTRO == "rhel7" ]]; then
-    # RHEL requires EPEL for many Open Stack dependencies
-
+function _install_epel_and_rdo {
     # NOTE: We always remove and install latest -- some environments
     # use snapshot images, and if EPEL version updates they break
     # unless we update them to latest version.
@@ -298,18 +296,27 @@
     sudo yum-config-manager --enable epel-bootstrap
     yum_install epel-release || \
         die $LINENO "Error installing EPEL repo, cannot continue"
-    # EPEL rpm has installed it's version
     sudo rm -f /etc/yum.repos.d/epel-bootstrap.repo
 
     # ... and also optional to be enabled
     sudo yum-config-manager --enable rhel-7-server-optional-rpms
 
+    # install the lastest RDO
     sudo yum install -y https://rdoproject.org/repos/rdo-release.rpm
 
     if is_oraclelinux; then
         sudo yum-config-manager --enable ol7_optional_latest ol7_addons ol7_MySQL56
     fi
+}
 
+# If you have all the repos installed above already setup (e.g. a CI
+# situation where they are on your image) you may choose to skip this
+# to speed things up
+SKIP_EPEL_INSTALL=$(trueorfalse False SKIP_EPEL_INSTALL)
+
+if is_fedora && [[ $DISTRO == "rhel7" ]] && \
+        [[ ${SKIP_EPEL_INSTALL} != True ]]; then
+    _install_epel_and_rdo
 fi
 
 
diff --git a/stackrc b/stackrc
index edf23ce..16621f1 100644
--- a/stackrc
+++ b/stackrc
@@ -72,18 +72,6 @@
     ENABLED_SERVICES+=,rabbit,tempest,mysql,dstat
 fi
 
-# SQLAlchemy supports multiple database drivers for each database server
-# type. For example, deployer may use MySQLdb, MySQLConnector, or oursql
-# to access MySQL database.
-#
-# When defined, the variable controls which database driver is used to
-# connect to database server. Otherwise using default driver defined for
-# each database type.
-#
-# You can find the list of currently supported drivers for each database
-# type at: http://docs.sqlalchemy.org/en/rel_0_9/core/engines.html
-# SQLALCHEMY_DATABASE_DRIVER="mysqldb"
-
 # Global toggle for enabling services under mod_wsgi. If this is set to
 # ``True`` all services that use HTTPD + mod_wsgi as the preferred method of
 # deployment, will be deployed under Apache. If this is set to ``False`` all
@@ -225,10 +213,6 @@
 HORIZON_REPO=${HORIZON_REPO:-${GIT_BASE}/openstack/horizon.git}
 HORIZON_BRANCH=${HORIZON_BRANCH:-master}
 
-# baremetal provisioning service
-IRONIC_REPO=${IRONIC_REPO:-${GIT_BASE}/openstack/ironic.git}
-IRONIC_BRANCH=${IRONIC_BRANCH:-master}
-
 # unified auth system (manages accounts/tokens)
 KEYSTONE_REPO=${KEYSTONE_REPO:-${GIT_BASE}/openstack/keystone.git}
 KEYSTONE_BRANCH=${KEYSTONE_BRANCH:-master}
@@ -298,6 +282,8 @@
 # ironic client
 GITREPO["python-ironicclient"]=${IRONICCLIENT_REPO:-${GIT_BASE}/openstack/python-ironicclient.git}
 GITBRANCH["python-ironicclient"]=${IRONICCLIENT_BRANCH:-master}
+# ironic plugin is out of tree, but nova uses it. set GITDIR here.
+GITDIR["python-ironicclient"]=$DEST/python-ironicclient
 
 # the base authentication plugins that clients use to authenticate
 GITREPO["keystoneauth"]=${KEYSTONEAUTH_REPO:-${GIT_BASE}/openstack/keystoneauth.git}
@@ -484,6 +470,8 @@
 # ironic common lib
 GITREPO["ironic-lib"]=${IRONIC_LIB_REPO:-${GIT_BASE}/openstack/ironic-lib.git}
 GITBRANCH["ironic-lib"]=${IRONIC_LIB_BRANCH:-master}
+# this doesn't exist in a lib file, so set it here
+GITDIR["ironic-lib"]=$DEST/ironic-lib
 
 
 ##################
diff --git a/tools/dstat.sh b/tools/dstat.sh
index 6ba4515..3c0b3be 100755
--- a/tools/dstat.sh
+++ b/tools/dstat.sh
@@ -13,7 +13,7 @@
 LOGDIR=$1
 
 # Command line arguments for primary DStat process.
-DSTAT_OPTS="-tcmndrylpg --top-cpu-adv --top-io-adv"
+DSTAT_OPTS="-tcmndrylpg --top-cpu-adv --top-io-adv --swap"
 
 # Command-line arguments for secondary background DStat process.
 DSTAT_CSV_OPTS="-tcmndrylpg --output $LOGDIR/dstat-csv.log"
diff --git a/tools/ironic/scripts/cleanup-node b/tools/ironic/scripts/cleanup-node
deleted file mode 100755
index c4e4e70..0000000
--- a/tools/ironic/scripts/cleanup-node
+++ /dev/null
@@ -1,25 +0,0 @@
-#!/usr/bin/env bash
-
-# **cleanup-nodes**
-
-# Cleans up baremetal poseur nodes and volumes created during ironic setup
-# Assumes calling user has proper libvirt group membership and access.
-
-set -exu
-
-LIBVIRT_STORAGE_POOL=${LIBVIRT_STORAGE_POOL:-"default"}
-LIBVIRT_CONNECT_URI=${LIBVIRT_CONNECT_URI:-"qemu:///system"}
-
-NAME=$1
-NETWORK_BRIDGE=$2
-
-export VIRSH_DEFAULT_CONNECT_URI=$LIBVIRT_CONNECT_URI
-
-VOL_NAME="$NAME.qcow2"
-virsh list | grep -q $NAME && virsh destroy $NAME
-virsh list --inactive | grep -q $NAME && virsh undefine $NAME
-
-if virsh pool-list | grep -q $LIBVIRT_STORAGE_POOL ; then
-  virsh vol-list $LIBVIRT_STORAGE_POOL | grep -q $VOL_NAME &&
-      virsh vol-delete $VOL_NAME --pool $LIBVIRT_STORAGE_POOL
-fi
diff --git a/tools/ironic/scripts/configure-vm b/tools/ironic/scripts/configure-vm
deleted file mode 100755
index 378fcb8..0000000
--- a/tools/ironic/scripts/configure-vm
+++ /dev/null
@@ -1,93 +0,0 @@
-#!/usr/bin/env python
-
-import argparse
-import os.path
-
-import libvirt
-
-templatedir = os.path.join(os.path.dirname(os.path.dirname(__file__)),
-                           '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.")
-    parser.add_argument('--name', default='seed',
-                        help='the name to give the machine in libvirt.')
-    parser.add_argument('--image',
-                        help='Use a custom image file (must be qcow2).')
-    parser.add_argument('--engine', default='qemu',
-                        help='The virtualization engine to use')
-    parser.add_argument('--arch', default='i686',
-                        help='The architecture to use')
-    parser.add_argument('--memory', default='2097152',
-                        help="Maximum memory for the VM in KB.")
-    parser.add_argument('--cpus', default='1',
-                        help="CPU count for the VM.")
-    parser.add_argument('--bootdev', default='hd',
-                        help="What boot device to use (hd/network).")
-    parser.add_argument('--network', default="brbm",
-                        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()
-    with file(templatedir + '/vm.xml', 'rb') as f:
-        source_template = f.read()
-    params = {
-        'name': args.name,
-        'imagefile': args.image,
-        'engine': args.engine,
-        'arch': args.arch,
-        'memory': args.memory,
-        'cpus': args.cpus,
-        'bootdev': args.bootdev,
-        'network': args.network,
-        'nicdriver': args.libvirt_nic_driver,
-        'emulator': args.emulator,
-    }
-
-    if args.emulator:
-        params['emulator'] = args.emulator
-    else:
-        if os.path.exists("/usr/bin/kvm"):  # Debian
-            params['emulator'] = "/usr/bin/kvm"
-        elif os.path.exists("/usr/bin/qemu-kvm"):  # Redhat
-            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")
-
-    a = conn.defineXML(libvirt_template)
-    print ("Created machine %s with UUID %s" % (args.name, a.UUIDString()))
-
-if __name__ == '__main__':
-    main()
diff --git a/tools/ironic/scripts/create-node b/tools/ironic/scripts/create-node
deleted file mode 100755
index b018acd..0000000
--- a/tools/ironic/scripts/create-node
+++ /dev/null
@@ -1,79 +0,0 @@
-#!/usr/bin/env bash
-
-# **create-nodes**
-
-# Creates baremetal poseur nodes for ironic testing purposes
-
-set -ex
-
-# Keep track of the DevStack directory
-TOP_DIR=$(cd $(dirname "$0")/.. && pwd)
-
-NAME=$1
-CPU=$2
-MEM=$(( 1024 * $3 ))
-# Extra G to allow fuzz for partition table : flavor size and registered size
-# need to be different to actual size.
-DISK=$(( $4 + 1))
-
-case $5 in
-    i386) ARCH='i686' ;;
-    amd64) ARCH='x86_64' ;;
-    *) echo "Unsupported arch $4!" ; exit 1 ;;
-esac
-
-BRIDGE=$6
-EMULATOR=$7
-LOGDIR=$8
-
-LIBVIRT_NIC_DRIVER=${LIBVIRT_NIC_DRIVER:-"e1000"}
-LIBVIRT_STORAGE_POOL=${LIBVIRT_STORAGE_POOL:-"default"}
-LIBVIRT_CONNECT_URI=${LIBVIRT_CONNECT_URI:-"qemu:///system"}
-
-export VIRSH_DEFAULT_CONNECT_URI=$LIBVIRT_CONNECT_URI
-
-if ! virsh pool-list --all | grep -q $LIBVIRT_STORAGE_POOL; then
-    virsh pool-define-as --name $LIBVIRT_STORAGE_POOL dir --target /var/lib/libvirt/images >&2
-    virsh pool-autostart $LIBVIRT_STORAGE_POOL >&2
-    virsh pool-start $LIBVIRT_STORAGE_POOL >&2
-fi
-
-pool_state=$(virsh pool-info $LIBVIRT_STORAGE_POOL | grep State | awk '{ print $2 }')
-if [ "$pool_state" != "running" ] ; then
-  [ ! -d /var/lib/libvirt/images ] && sudo mkdir /var/lib/libvirt/images
-  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"
-fi
-
-if [ -n "$LOGDIR" ] ; then
-  VM_LOGGING="--console-log $LOGDIR/${NAME}_console.log"
-else
-  VM_LOGGING=""
-fi
-VOL_NAME="${NAME}.qcow2"
-
-if ! virsh list --all | grep -q $NAME; then
-  virsh vol-list --pool $LIBVIRT_STORAGE_POOL | grep -q $VOL_NAME &&
-      virsh vol-delete $VOL_NAME --pool $LIBVIRT_STORAGE_POOL >&2
-  virsh vol-create-as $LIBVIRT_STORAGE_POOL ${VOL_NAME} ${DISK}G --format qcow2 $PREALLOC >&2
-  volume_path=$(virsh vol-path --pool $LIBVIRT_STORAGE_POOL $VOL_NAME)
-  # 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 $VM_LOGGING >&2
-
-fi
-
-# echo mac
-virsh dumpxml $NAME | grep "mac address" | head -1 | cut -d\' -f2
diff --git a/tools/ironic/scripts/setup-network b/tools/ironic/scripts/setup-network
deleted file mode 100755
index 83308ed..0000000
--- a/tools/ironic/scripts/setup-network
+++ /dev/null
@@ -1,28 +0,0 @@
-#!/usr/bin/env bash
-
-# **setup-network**
-
-# Setups openvswitch libvirt network suitable for
-# running baremetal poseur nodes for ironic testing purposes
-
-set -exu
-
-LIBVIRT_CONNECT_URI=${LIBVIRT_CONNECT_URI:-"qemu:///system"}
-
-# Keep track of the DevStack directory
-TOP_DIR=$(cd $(dirname "$0")/.. && pwd)
-BRIDGE_SUFFIX=${1:-''}
-BRIDGE_NAME=brbm$BRIDGE_SUFFIX
-
-export VIRSH_DEFAULT_CONNECT_URI="$LIBVIRT_CONNECT_URI"
-
-# Only add bridge if missing
-(sudo ovs-vsctl list-br | grep ${BRIDGE_NAME}$) || sudo ovs-vsctl add-br ${BRIDGE_NAME}
-
-# Remove bridge before replacing it.
-(virsh net-list | grep "${BRIDGE_NAME} ") && virsh net-destroy ${BRIDGE_NAME}
-(virsh net-list --inactive  | grep "${BRIDGE_NAME} ") && virsh net-undefine ${BRIDGE_NAME}
-
-virsh net-define <(sed s/brbm/$BRIDGE_NAME/ $TOP_DIR/templates/brbm.xml)
-virsh net-autostart ${BRIDGE_NAME}
-virsh net-start ${BRIDGE_NAME}
diff --git a/tools/ironic/templates/brbm.xml b/tools/ironic/templates/brbm.xml
deleted file mode 100644
index 0769d3f..0000000
--- a/tools/ironic/templates/brbm.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<network>
-  <name>brbm</name>
-  <forward mode='bridge'/>
-  <bridge name='brbm'/>
-  <virtualport type='openvswitch'/>
-</network>
diff --git a/tools/ironic/templates/tftpd-xinetd.template b/tools/ironic/templates/tftpd-xinetd.template
deleted file mode 100644
index 5f3d03f..0000000
--- a/tools/ironic/templates/tftpd-xinetd.template
+++ /dev/null
@@ -1,14 +0,0 @@
-service tftp
-{
-  protocol        = udp
-  port            = 69
-  socket_type     = dgram
-  wait            = yes
-  user            = root
-  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
deleted file mode 100644
index ae7d685..0000000
--- a/tools/ironic/templates/vm.xml
+++ /dev/null
@@ -1,49 +0,0 @@
-<domain type='%(engine)s'>
-  <name>%(name)s</name>
-  <memory unit='KiB'>%(memory)s</memory>
-  <vcpu>%(cpus)s</vcpu>
-  <os>
-    <type arch='%(arch)s' machine='pc-1.0'>hvm</type>
-    <boot dev='%(bootdev)s'/>
-    <bootmenu enable='no'/>
-    %(bios_serial)s
-  </os>
-  <features>
-    <acpi/>
-    <apic/>
-    <pae/>
-  </features>
-  <clock offset='utc'/>
-  <on_poweroff>destroy</on_poweroff>
-  <on_reboot>restart</on_reboot>
-  <on_crash>restart</on_crash>
-  <devices>
-    <emulator>%(emulator)s</emulator>
-    <disk type='file' device='disk'>
-      <driver name='qemu' type='qcow2' cache='writeback'/>
-      <source file='%(imagefile)s'/>
-      <target dev='vda' bus='virtio'/>
-      <address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/>
-    </disk>
-    <controller type='ide' index='0'>
-      <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/>
-    </controller>
-    <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>
-  </devices>
-</domain>
-
diff --git a/tox.ini b/tox.ini
index 9279455..f9d04f2 100644
--- a/tox.ini
+++ b/tox.ini
@@ -12,20 +12,20 @@
    {env:BASHATE_INSTALL_PATH:bashate==0.3.2}
 whitelist_externals = bash
 commands = bash -c "find {toxinidir}             \
-         -not \( -type d -name .?\* -prune \)    \ # prune all 'dot' dirs
-         -not \( -type d -name doc -prune \)     \ # skip documentation
-         -not \( -type d -name shocco -prune \)  \ # skip shocco
-         -type f                                 \ # only files
-         -not -name \*~                          \ # skip editors, readme, etc
+         -not \( -type d -name .?\* -prune \)    \
+         -not \( -type d -name doc -prune \)     \
+         -not \( -type d -name shocco -prune \)  \
+         -type f                                 \
+         -not -name \*~                          \
          -not -name \*.md                        \
          \(                                      \
           -name \*.sh -or                        \
           -name \*.orig -or                      \
-          -name \*rc -or                         \ # openrc files, etc
+          -name \*rc -or                         \
           -name functions\* -or                  \
-          -wholename \*/inc/\* -or               \ # /inc files and
-          -wholename \*/lib/\*                   \ # /lib files are shell, but
-         \)                                      \ #   have no extension
+          -wholename \*/inc/\* -or               \
+          -wholename \*/lib/\*                   \
+         \)                                      \
          -print0 | xargs -0 bashate -v -iE006 -eE005,E042"
 
 [testenv:docs]