Merge "Support heat in standalone mode."
diff --git a/README.md b/README.md
index 95c90bc..6426e9a 100644
--- a/README.md
+++ b/README.md
@@ -203,7 +203,7 @@
 If tempest has been successfully configured, a basic set of smoke tests can be run as follows:
 
     $ cd /opt/stack/tempest
-    $ nosetests tempest/tests/network/test_network_basic_ops.py
+    $ nosetests tempest/scenario/test_network_basic_ops.py
 
 # Multi-Node Setup
 
diff --git a/clean.sh b/clean.sh
index 493c449..f7d15df 100755
--- a/clean.sh
+++ b/clean.sh
@@ -56,6 +56,7 @@
 fi
 
 # Clean projects
+cleanup_oslo
 cleanup_cinder
 cleanup_glance
 cleanup_keystone
diff --git a/exercises/euca.sh b/exercises/euca.sh
index 5b0d1ba..b8b283a 100755
--- a/exercises/euca.sh
+++ b/exercises/euca.sh
@@ -129,7 +129,8 @@
     # Allocate floating address
     FLOATING_IP=`euca-allocate-address | cut -f2`
     die_if_not_set $LINENO FLOATING_IP "Failure allocating floating IP"
-
+    # describe all instances at this moment
+    euca-describe-instances
     # Associate floating address
     euca-associate-address -i $INSTANCE $FLOATING_IP || \
         die $LINENO "Failure associating address $FLOATING_IP to $INSTANCE"
diff --git a/files/apts/general b/files/apts/general
index fdf8e20..fcf0b5b 100644
--- a/files/apts/general
+++ b/files/apts/general
@@ -1,6 +1,6 @@
 bridge-utils
 pylint
-python-pip
+python-setuptools
 screen
 unzip
 wget
diff --git a/files/apts/keystone b/files/apts/keystone
index c98409f..564921b 100644
--- a/files/apts/keystone
+++ b/files/apts/keystone
@@ -1,4 +1,3 @@
-python-setuptools
 python-dev
 python-lxml
 python-pastescript
diff --git a/files/apts/ryu b/files/apts/ryu
index 4a4fc52..e8ed926 100644
--- a/files/apts/ryu
+++ b/files/apts/ryu
@@ -1,4 +1,3 @@
-python-setuptools
 python-gevent
 python-gflags
 python-netifaces
diff --git a/files/apts/swift b/files/apts/swift
index 1c283cf..37d5bc0 100644
--- a/files/apts/swift
+++ b/files/apts/swift
@@ -10,7 +10,6 @@
 python-netifaces
 python-nose
 python-pastedeploy
-python-setuptools
 python-simplejson
 python-webob
 python-xattr
diff --git a/files/rpms-suse/general b/files/rpms-suse/general
index f28267c..355af88 100644
--- a/files/rpms-suse/general
+++ b/files/rpms-suse/general
@@ -6,8 +6,8 @@
 openssh
 openssl
 psmisc
+python-setuptools # instead of python-distribute; dist:sle11sp2
 python-cmd2 # dist:opensuse-12.3
-python-pip
 python-pylint
 python-unittest2
 python-virtualenv
diff --git a/files/rpms-suse/keystone b/files/rpms-suse/keystone
index 7d9a7bf..403d82f 100644
--- a/files/rpms-suse/keystone
+++ b/files/rpms-suse/keystone
@@ -7,8 +7,6 @@
 python-SQLAlchemy
 python-WebOb
 python-devel
-python-distribute
-python-setuptools # instead of python-distribute; dist:sle11sp2
 python-greenlet
 python-lxml
 python-mysql
diff --git a/files/rpms-suse/ryu b/files/rpms-suse/ryu
index 90b43a4..3797b6c 100644
--- a/files/rpms-suse/ryu
+++ b/files/rpms-suse/ryu
@@ -1,5 +1,3 @@
-python-distribute
-python-setuptools # instead of python-distribute; dist:sle11sp2
 python-Sphinx
 python-gevent
 python-netifaces
diff --git a/files/rpms-suse/swift b/files/rpms-suse/swift
index db379bb..f3c95aa 100644
--- a/files/rpms-suse/swift
+++ b/files/rpms-suse/swift
@@ -6,8 +6,6 @@
 python-configobj
 python-coverage
 python-devel
-python-distribute
-python-setuptools # instead of python-distribute; dist:sle11sp2
 python-eventlet
 python-greenlet
 python-netifaces
diff --git a/files/rpms/general b/files/rpms/general
index 9fa305c..2db31d1 100644
--- a/files/rpms/general
+++ b/files/rpms/general
@@ -11,7 +11,7 @@
 libxslt-devel # dist:rhel6 [2]
 psmisc
 pylint
-python-pip
+python-setuptools
 python-prettytable # dist:rhel6 [1]
 python-unittest2
 python-virtualenv
diff --git a/files/rpms/keystone b/files/rpms/keystone
index 33a4f47..52dbf47 100644
--- a/files/rpms/keystone
+++ b/files/rpms/keystone
@@ -4,10 +4,9 @@
 python-paste-deploy #dist:f16,f17,f18,f19
 python-paste-script #dist:f16,f17,f18,f19
 python-routes
-python-setuptools   #dist:f16,f17,f18,f19
 python-sqlalchemy
 python-sqlite2
 python-webob
 sqlite
 
-# Deps installed via pip for RHEL
\ No newline at end of file
+# Deps installed via pip for RHEL
diff --git a/files/rpms/ryu b/files/rpms/ryu
index 0f62f9f..e8ed926 100644
--- a/files/rpms/ryu
+++ b/files/rpms/ryu
@@ -1,5 +1,4 @@
 python-gevent
 python-gflags
 python-netifaces
-python-setuptools #dist:f16,f17,f18,f19
 python-sphinx
diff --git a/files/rpms/swift b/files/rpms/swift
index 2cc4a0b..b137f30 100644
--- a/files/rpms/swift
+++ b/files/rpms/swift
@@ -10,7 +10,6 @@
 python-netifaces
 python-nose
 python-paste-deploy # dist:f16,f17,f18,f19
-python-setuptools   # dist:f16,f17,f18,f19
 python-simplejson
 python-webob
 pyxattr
diff --git a/functions b/functions
index 4b8a06e..e9c6061 100644
--- a/functions
+++ b/functions
@@ -76,6 +76,19 @@
 }
 
 
+# Prints backtrace info
+# filename:lineno:function
+function backtrace {
+    local level=$1
+    local deep=$((${#BASH_SOURCE[@]} - 1))
+    echo "[Call Trace]"
+    while [ $level -le $deep ]; do
+        echo "${BASH_SOURCE[$deep]}:${BASH_LINENO[$deep-1]}:${FUNCNAME[$deep-1]}"
+        deep=$((deep - 1))
+    done
+}
+
+
 # Prints line number and "message" then exits
 # die $LINENO "message"
 function die() {
@@ -85,6 +98,7 @@
     if [ $exitcode == 0 ]; then
         exitcode=1
     fi
+    backtrace 2
     err $line "$*"
     exit $exitcode
 }
@@ -113,7 +127,7 @@
     local exitcode=$?
     errXTRACE=$(set +o | grep xtrace)
     set +o xtrace
-    local msg="[ERROR] $0:$1 $2"
+    local msg="[ERROR] ${BASH_SOURCE[2]}:$1 $2"
     echo $msg 1>&2;
     if [[ -n ${SCREEN_LOGDIR} ]]; then
         echo $msg >> "${SCREEN_LOGDIR}/error.log"
@@ -930,7 +944,7 @@
         CMD_PIP=$(get_pip_command)
     fi
 
-    if [[ is_fedora && $DISTRO =~ (rhel6) ]]; then
+    if is_fedora && [[ $DISTRO =~ (rhel6) ]]; then
         # RHEL6 pip by default doesn't have this (was introduced
         # around 0.8.1 or so)
         PIP_USE_MIRRORS=${PIP_USE_MIRRORS:-False}
@@ -1116,7 +1130,7 @@
 
     for service in $failures; do
         service=`basename $service`
-        service=${service::-8}
+        service=${service%.failure}
         echo "Error: Service $service is not running"
     done
 
@@ -1128,19 +1142,25 @@
 
 # ``pip install -e`` the package, which processes the dependencies
 # using pip before running `setup.py develop`
-# Uses globals ``STACK_USER``, ``TRACK_DEPENDES``, ``*_proxy`
+# Uses globals ``STACK_USER``, ``TRACK_DEPENDS``, ``REQUIREMENTS_DIR``
 # setup_develop directory
 function setup_develop() {
+    local project_dir=$1
     if [[ $TRACK_DEPENDS = True ]]; then
         SUDO_CMD="env"
     else
         SUDO_CMD="sudo"
     fi
-    $SUDO_CMD \
-        HTTP_PROXY=$http_proxy \
-        HTTPS_PROXY=$https_proxy \
-        NO_PROXY=$no_proxy \
-        pip install -e $1
+
+    echo "cd $REQUIREMENTS_DIR; $SUDO_CMD python update.py $project_dir"
+
+    # Don't update repo if local changes exist
+    if (cd $project_dir && git diff --quiet); then
+        (cd $REQUIREMENTS_DIR; \
+            $SUDO_CMD python update.py $project_dir)
+    fi
+
+    pip_install -e $project_dir
     # ensure that further actions can do things like setup.py sdist
     $SUDO_CMD chown -R $STACK_USER $1/*.egg-info
 }
diff --git a/lib/baremetal b/lib/baremetal
index 145544d..8f6c3f1 100644
--- a/lib/baremetal
+++ b/lib/baremetal
@@ -138,9 +138,12 @@
 BM_IMAGE_BUILD_DIR=${BM_IMAGE_BUILD_DIR:-$DEST/diskimage-builder}
 BM_POSEUR_DIR=${BM_POSEUR_DIR:-$DEST/bm_poseur}
 
-BM_HOST_CURRENT_KERNEL=$(uname -r)
-BM_DEPLOY_RAMDISK=${BM_DEPLOY_RAMDISK:-bm-deploy-$BM_HOST_CURRENT_KERNEL-initrd}
-BM_DEPLOY_KERNEL=${BM_DEPLOY_KERNEL:-bm-deploy-$BM_HOST_CURRENT_KERNEL-vmlinuz}
+# Use DIB to create deploy ramdisk and kernel.
+BM_BUILD_DEPLOY_RAMDISK=`trueorfalse True $BM_BUILD_DEPLOY_RAMDISK`
+# If not use DIB, these files are used as deploy ramdisk/kernel.
+# (The value must be a relative path from $TOP_DIR/files/)
+BM_DEPLOY_RAMDISK=${BM_DEPLOY_RAMDISK:-}
+BM_DEPLOY_KERNEL=${BM_DEPLOY_KERNEL:-}
 
 # If you need to add any extra flavors to the deploy ramdisk image
 # eg, specific network drivers, specify them here
@@ -233,13 +236,13 @@
 function upload_baremetal_deploy() {
     token=$1
 
-    if [ ! -e $TOP_DIR/files/$BM_DEPLOY_KERNEL -a -e /boot/vmlinuz-$BM_HOST_CURRENT_KERNEL ]; then
-        sudo cp /boot/vmlinuz-$BM_HOST_CURRENT_KERNEL $TOP_DIR/files/$BM_DEPLOY_KERNEL
-        sudo chmod a+r $TOP_DIR/files/$BM_DEPLOY_KERNEL
-    fi
-    if [ ! -e $TOP_DIR/files/$BM_DEPLOY_RAMDISK ]; then
-       $BM_IMAGE_BUILD_DIR/bin/ramdisk-image-create $BM_DEPLOY_FLAVOR deploy \
-           -o $TOP_DIR/files/$BM_DEPLOY_RAMDISK -k $BM_HOST_CURRENT_KERNEL
+    if [ "$BM_BUILD_DEPLOY_RAMDISK" = "True" ]; then
+        BM_DEPLOY_KERNEL=bm-deploy.kernel
+        BM_DEPLOY_RAMDISK=bm-deploy.initramfs
+        if [ ! -e "$TOP_DIR/files/$BM_DEPLOY_KERNEL" -o ! -e "$TOP_DIR/files/$BM_DEPLOY_RAMDISK" ]; then
+            $BM_IMAGE_BUILD_DIR/bin/ramdisk-image-create $BM_DEPLOY_FLAVOR deploy \
+                -o $TOP_DIR/files/bm-deploy
+        fi
     fi
 
     # load them into glance
diff --git a/lib/cinder b/lib/cinder
index ef7e3dc..3472dcd 100644
--- a/lib/cinder
+++ b/lib/cinder
@@ -296,6 +296,10 @@
             -e 's/snapshot_autoextend_percent =.*/snapshot_autoextend_percent = 20/' \
             /etc/lvm/lvm.conf
     fi
+    iniset $CINDER_CONF keystone_authtoken auth_uri $KEYSTONE_SERVICE_PROTOCOL://$KEYSTONE_SERVICE_HOST:$KEYSTONE_SERVICE_PORT
+    iniset $CINDER_CONF keystone_authtoken admin_user cinder
+    iniset $CINDER_CONF keystone_authtoken admin_tenant_name $SERVICE_TENANT_NAME
+    iniset $CINDER_CONF keystone_authtoken admin_password $SERVICE_PASSWORD
 
 }
 
diff --git a/lib/neutron b/lib/neutron
index 835f900..306140a 100644
--- a/lib/neutron
+++ b/lib/neutron
@@ -367,7 +367,9 @@
 
 # init_neutron() - Initialize databases, etc.
 function init_neutron() {
-    :
+    recreate_database $Q_DB_NAME utf8
+    # Run Neutron db migrations
+    $NEUTRON_BIN_DIR/neutron-db-manage --config-file $NEUTRON_CONF --config-file /$Q_PLUGIN_CONF_FILE upgrade head
 }
 
 # install_neutron() - Collect source and prepare
@@ -523,7 +525,6 @@
     # be cleaned.
     iniset $NEUTRON_TEST_CONFIG_FILE agent root_helper "$Q_RR_COMMAND"
 
-    _neutron_setup_keystone $NEUTRON_TEST_CONFIG_FILE DEFAULT set_auth_url
     _neutron_setup_interface_driver $NEUTRON_TEST_CONFIG_FILE
 
     neutron_plugin_configure_debug_command
@@ -540,7 +541,6 @@
     iniset $Q_DHCP_CONF_FILE DEFAULT use_namespaces $Q_USE_NAMESPACE
     iniset $Q_DHCP_CONF_FILE DEFAULT root_helper "$Q_RR_COMMAND"
 
-    _neutron_setup_keystone $Q_DHCP_CONF_FILE DEFAULT set_auth_url
     _neutron_setup_interface_driver $Q_DHCP_CONF_FILE
 
     neutron_plugin_configure_dhcp_agent
@@ -561,7 +561,6 @@
     iniset $Q_L3_CONF_FILE DEFAULT use_namespaces $Q_USE_NAMESPACE
     iniset $Q_L3_CONF_FILE DEFAULT root_helper "$Q_RR_COMMAND"
 
-    _neutron_setup_keystone $Q_L3_CONF_FILE DEFAULT set_auth_url
     _neutron_setup_interface_driver $Q_L3_CONF_FILE
 
     neutron_plugin_configure_l3_agent
@@ -578,7 +577,6 @@
     iniset $Q_META_CONF_FILE DEFAULT nova_metadata_ip $Q_META_DATA_IP
     iniset $Q_META_CONF_FILE DEFAULT root_helper "$Q_RR_COMMAND"
 
-    _neutron_setup_keystone $Q_META_CONF_FILE DEFAULT set_auth_url
 }
 
 function _configure_neutron_lbaas() {
@@ -614,12 +612,6 @@
     cp $NEUTRON_DIR/etc/api-paste.ini $Q_API_PASTE_FILE
     cp $NEUTRON_DIR/etc/policy.json $Q_POLICY_FILE
 
-    if is_service_enabled $DATABASE_BACKENDS; then
-        recreate_database $Q_DB_NAME utf8
-    else
-        die $LINENO "A database must be enabled in order to use the $Q_PLUGIN Neutron plugin."
-    fi
-
     # Update either configuration file with plugin
     iniset $NEUTRON_CONF DEFAULT core_plugin $Q_PLUGIN_CLASS
 
diff --git a/lib/neutron_plugins/ml2 b/lib/neutron_plugins/ml2
index ff49d8e..00bd716 100644
--- a/lib/neutron_plugins/ml2
+++ b/lib/neutron_plugins/ml2
@@ -20,7 +20,7 @@
 source $TOP_DIR/lib/neutron_plugins/${Q_AGENT}_agent
 
 # List of MechanismDrivers to load
-Q_ML2_PLUGIN_MECHANISM_DRIVERS=${Q_PLUGIN_MECHANISM_DRIVERS:-}
+Q_ML2_PLUGIN_MECHANISM_DRIVERS=${Q_ML2_PLUGIN_MECHANISM_DRIVERS:-}
 # List of Type Drivers to load
 Q_ML2_PLUGIN_TYPE_DRIVERS=${Q_ML2_PLUGIN_TYPE_DRIVERS:-local,flat,vlan,gre,vxlan}
 # Default GRE TypeDriver options
@@ -92,6 +92,8 @@
     # Since we enable the tunnel TypeDrivers, also enable a local_ip
     iniset /$Q_PLUGIN_CONF_FILE ovs local_ip $HOST_IP
 
+    populate_ml2_config mechanism_drivers=$Q_ML2_PLUGIN_MECHANISM_DRIVERS /$Q_PLUGIN_CONF_FILE ml2
+
     populate_ml2_config type_drivers=$Q_ML2_PLUGIN_TYPE_DRIVERS /$Q_PLUGIN_CONF_FILE ml2
 
     populate_ml2_config $Q_SRV_EXTRA_OPTS /$Q_PLUGIN_CONF_FILE ml2
diff --git a/lib/oslo b/lib/oslo
index 1eb13db..de5ec4e 100644
--- a/lib/oslo
+++ b/lib/oslo
@@ -27,6 +27,10 @@
 
 # install_oslo() - Collect source and prepare
 function install_oslo() {
+    # TODO(sdague): remove this once we get to Icehouse, this just makes
+    # for a smoother transition of existing users.
+    cleanup_oslo
+
     git_clone $OSLOCFG_REPO $OSLOCFG_DIR $OSLOCFG_BRANCH
     setup_develop $OSLOCFG_DIR
 
@@ -34,6 +38,17 @@
     setup_develop $OSLOMSG_DIR
 }
 
+# cleanup_oslo() - purge possibly old versions of oslo
+function cleanup_oslo() {
+    # this means we've got an old olso installed, lets get rid of it
+    if find /usr | grep oslo.config | grep -v oslo.config.egg-link > /dev/null; then
+        echo "Found old oslo.config... removing to ensure consistency"
+        local PIP_CMD=$(get_pip_command)
+        pip_install olso.config
+        sudo $PIP_CMD uninstall -y olso.config
+    fi
+}
+
 # Restore xtrace
 $XTRACE
 
diff --git a/lib/swift b/lib/swift
index c93b8b3..8e64152 100644
--- a/lib/swift
+++ b/lib/swift
@@ -58,8 +58,8 @@
 SWIFT_LOOPBACK_DISK_SIZE=${SWIFT_LOOPBACK_DISK_SIZE:-1000000}
 
 # Set ``SWIFT_EXTRAS_MIDDLEWARE`` to extras middlewares.
-# Default is ``staticweb, tempurl, bulk, formpost``
-SWIFT_EXTRAS_MIDDLEWARE=${SWIFT_EXTRAS_MIDDLEWARE:-tempurl formpost staticweb bulk}
+# Default is ``staticweb, tempurl, formpost``
+SWIFT_EXTRAS_MIDDLEWARE=${SWIFT_EXTRAS_MIDDLEWARE:-tempurl formpost staticweb}
 
 # The ring uses a configurable number of bits from a path’s MD5 hash as
 # a partition index that designates a device. The number of bits kept
diff --git a/stack.sh b/stack.sh
index 5ba60d2..22a23c8 100755
--- a/stack.sh
+++ b/stack.sh
@@ -578,18 +578,8 @@
 echo_summary "Installing package prerequisites"
 source $TOP_DIR/tools/install_prereqs.sh
 
-install_rpc_backend
-
-if is_service_enabled $DATABASE_BACKENDS; then
-    install_database
-fi
-
-if is_service_enabled neutron; then
-    install_neutron_agent_packages
-fi
-
-# Unbreak the giant mess that is the current state of setuptools
-unfubar_setuptools
+# Configure an appropriate python environment
+$TOP_DIR/tools/install_pip.sh
 
 # System-specific preconfigure
 # ============================
@@ -601,23 +591,29 @@
         sudo setenforce 0
     fi
 
-    # An old version of ``python-crypto`` (2.0.1) may be installed on a
-    # fresh system via Anaconda and the dependency chain
-    # ``cas`` -> ``python-paramiko`` -> ``python-crypto``.
-    # ``pip uninstall pycrypto`` will remove the packaged ``.egg-info`` file
-    # but leave most of the actual library files behind in ``/usr/lib64/python2.6/Crypto``.
-    # Later ``pip install pycrypto`` will install over the packaged files resulting
-    # in a useless mess of old, rpm-packaged files and pip-installed files.
-    # Remove the package so that ``pip install python-crypto`` installs cleanly.
-    # Note: other RPM packages may require ``python-crypto`` as well.  For example,
-    # RHEL6 does not install ``python-paramiko packages``.
-    uninstall_package python-crypto
+    # The following workarounds break xenserver
+    if [ "$VIRT_DRIVER" != 'xenserver' ]; then
+        # An old version of ``python-crypto`` (2.0.1) may be installed on a
+        # fresh system via Anaconda and the dependency chain
+        # ``cas`` -> ``python-paramiko`` -> ``python-crypto``.
+        # ``pip uninstall pycrypto`` will remove the packaged ``.egg-info``
+        #  file but leave most of the actual library files behind in
+        # ``/usr/lib64/python2.6/Crypto``. Later ``pip install pycrypto``
+        # will install over the packaged files resulting
+        # in a useless mess of old, rpm-packaged files and pip-installed files.
+        # Remove the package so that ``pip install python-crypto`` installs
+        # cleanly.
+        # Note: other RPM packages may require ``python-crypto`` as well.
+        # For example, RHEL6 does not install ``python-paramiko packages``.
+        uninstall_package python-crypto
 
-    # A similar situation occurs with ``python-lxml``, which is required by
-    # ``ipa-client``, an auditing package we don't care about.  The
-    # build-dependencies needed for ``pip install lxml`` (``gcc``,
-    # ``libxml2-dev`` and ``libxslt-dev``) are present in ``files/rpms/general``.
-    uninstall_package python-lxml
+        # A similar situation occurs with ``python-lxml``, which is required by
+        # ``ipa-client``, an auditing package we don't care about.  The
+        # build-dependencies needed for ``pip install lxml`` (``gcc``,
+        # ``libxml2-dev`` and ``libxslt-dev``) are present in
+        # ``files/rpms/general``.
+        uninstall_package python-lxml
+    fi
 
     # If the ``dbus`` package was installed by DevStack dependencies the
     # uuid may not be generated because the service was never started (PR#598200),
@@ -642,12 +638,22 @@
     sudo ln -sf /usr/bin/nosetests1.1 /usr/local/bin/nosetests
 fi
 
+install_rpc_backend
+
+if is_service_enabled $DATABASE_BACKENDS; then
+    install_database
+fi
+
+if is_service_enabled neutron; then
+    install_neutron_agent_packages
+fi
+
 TRACK_DEPENDS=${TRACK_DEPENDS:-False}
 
 # Install python packages into a virtualenv so that we can track them
 if [[ $TRACK_DEPENDS = True ]]; then
     echo_summary "Installing Python packages into a virtualenv $DEST/.venv"
-    install_package python-virtualenv
+    pip_install -U virtualenv
 
     rm -rf $DEST/.venv
     virtualenv --system-site-packages $DEST/.venv
@@ -939,7 +945,10 @@
     echo_summary "Configuring Neutron"
 
     configure_neutron
-    init_neutron
+    # Run init_neutron only on the node hosting the neutron API server
+    if is_service_enabled $DATABASE_BACKENDS && is_service_enabled q-svc; then
+        init_neutron
+    fi
 fi
 
 # Some Neutron plugins require network controllers which are not
diff --git a/stackrc b/stackrc
index 1e08d16..c81906a 100644
--- a/stackrc
+++ b/stackrc
@@ -180,8 +180,11 @@
 
 # Nova hypervisor configuration.  We default to libvirt with **kvm** but will
 # drop back to **qemu** if we are unable to load the kvm module.  ``stack.sh`` can
-# also install an **LXC**, **OpenVZ** or **XenAPI** based system.
-VIRT_DRIVER=${VIRT_DRIVER:-libvirt}
+# also install an **LXC**, **OpenVZ** or **XenAPI** based system.  If xenserver-core
+# is installed, the default will be XenAPI
+DEFAULT_VIRT_DRIVER=libvirt
+is_package_installed xenserver-core && DEFAULT_VIRT_DRIVER=xenserver
+VIRT_DRIVER=${VIRT_DRIVER:-$DEFAULT_VIRT_DRIVER}
 case "$VIRT_DRIVER" in
     libvirt)
         LIBVIRT_TYPE=${LIBVIRT_TYPE:-kvm}
diff --git a/tools/install_pip.sh b/tools/install_pip.sh
new file mode 100755
index 0000000..0ea8f53
--- /dev/null
+++ b/tools/install_pip.sh
@@ -0,0 +1,118 @@
+#!/usr/bin/env bash
+
+# **install_pip.sh**
+
+# install_pip.sh [--pip-version <version>] [--use-get-pip] [--setuptools] [--force]
+#
+# Update pip and friends to a known common version
+
+# Assumptions:
+# - currently we try to leave the system setuptools alone, install
+#   the system package if it is not already present
+# - update pip to $INSTALL_PIP_VERSION
+
+# Keep track of the current directory
+TOOLS_DIR=$(cd $(dirname "$0") && pwd)
+TOP_DIR=`cd $TOOLS_DIR/..; pwd`
+
+# Change dir to top of devstack
+cd $TOP_DIR
+
+# Import common functions
+source $TOP_DIR/functions
+
+FILES=$TOP_DIR/files
+
+# Handle arguments
+
+INSTALL_PIP_VERSION=${INSTALL_PIP_VERSION:-"1.4"}
+while [[ -n "$1" ]]; do
+    case $1 in
+        --force)
+            FORCE=1
+            ;;
+        --pip-version)
+            INSTALL_PIP_VERSION="$2"
+            shift
+            ;;
+        --setuptools)
+            SETUPTOOLS=1
+            ;;
+        --use-get-pip)
+            USE_GET_PIP=1;
+            ;;
+    esac
+    shift
+done
+
+SETUPTOOLS_EZ_SETUP_URL=https://bitbucket.org/pypa/setuptools/raw/bootstrap/ez_setup.py
+PIP_GET_PIP_URL=https://raw.github.com/pypa/pip/master/contrib/get-pip.py
+PIP_TAR_URL=https://pypi.python.org/packages/source/p/pip/pip-$INSTALL_PIP_VERSION.tar.gz
+
+GetDistro
+echo "Distro: $DISTRO"
+
+function get_versions() {
+    PIP=$(which pip 2>/dev/null || which pip-python 2>/dev/null)
+    if [[ -n $PIP ]]; then
+        DISTRIBUTE_VERSION=$($PIP freeze | grep 'distribute==')
+        SETUPTOOLS_VERSION=$($PIP freeze | grep 'setuptools==')
+        PIP_VERSION=$($PIP --version | awk '{ print $2}')
+        echo "pip: $PIP_VERSION  setuptools: $SETUPTOOLS_VERSION  distribute: $DISTRIBUTE_VERSION"
+    fi
+}
+
+function setuptools_ez_setup() {
+    if [[ ! -r $FILES/ez_setup.py ]]; then
+        (cd $FILES; \
+         curl -OR $SETUPTOOLS_EZ_SETUP_URL; \
+        )
+    fi
+    sudo python $FILES/ez_setup.py
+}
+
+function install_get_pip() {
+    if [[ ! -r $FILES/get-pip.py ]]; then
+        (cd $FILES; \
+            curl $PIP_GET_PIP_URL; \
+        )
+    fi
+    sudo python $FILES/get-pip.py
+}
+
+function install_pip_tarball() {
+    curl -O $PIP_TAR_URL
+    tar xvfz pip-$INSTALL_PIP_VERSION.tar.gz
+    cd pip-$INSTALL_PIP_VERSION
+    sudo python setup.py install
+}
+
+# Show starting versions
+get_versions
+
+# Do setuptools
+if [[ -n "$SETUPTOOLS" ]]; then
+    # We want it from source
+    uninstall_package python-setuptools
+    setuptools_ez_setup
+else
+    # See about installing the distro setuptools
+    if ! python -c "import setuptools"; then
+        install_package python-setuptools
+    fi
+fi
+
+# Do pip
+if [[ -z $PIP || "$PIP_VERSION" != "$INSTALL_PIP_VERSION" || -n $FORCE ]]; then
+
+    # Eradicate any and all system packages
+    uninstall_package python-pip
+
+    if [[ -n "$USE_GET_PIP" ]]; then
+        install_get_pip
+    else
+        install_pip_tarball
+    fi
+
+    get_versions
+fi