Merge "Plugin autogen list: handle variable-width plugin names"
diff --git a/.gitignore b/.gitignore
index c72b0c4..a470ff5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -12,6 +12,7 @@
 doc/files
 doc/build
 files/*.gz
+files/*.vmdk
 files/*.rpm
 files/*.rpm.*
 files/*.qcow2
diff --git a/doc/source/faq.rst b/doc/source/faq.rst
index cd48915..7793d8e 100644
--- a/doc/source/faq.rst
+++ b/doc/source/faq.rst
@@ -85,7 +85,7 @@
 
    function sourceopenrc {
        pushd ~/devstack >/dev/null
-       eval $(bash -c ". openrc $1 $2;env|sed -n '/OS_/ { s/^/export /;p}'")
+       eval $(bash -c ". openrc $1 $2 >/dev/null;env|sed -n '/OS_/ { s/^/export /;p}'")
        popd >/dev/null
    }
 
diff --git a/doc/source/guides/neutron.rst b/doc/source/guides/neutron.rst
index 4406aa0..6ac3993 100644
--- a/doc/source/guides/neutron.rst
+++ b/doc/source/guides/neutron.rst
@@ -19,6 +19,18 @@
 the OpenStack API traffic, and management traffic.
 
 
+.. warning::
+
+    When using a single interface networking setup, there will be a
+    temporary network outage as your IP address is moved from the
+    physical NIC of your machine, to the OVS bridge. If you are SSH'd
+    into the machine from another computer, there is a risk of being
+    disconnected from your ssh session (due to arp cache
+    invalidation), which would stop the stack.sh or leave it in an
+    unfinished state. In these cases, start stack.sh inside its own
+    screen session so it can continue to run.
+
+
 Physical Network Setup
 ----------------------
 
@@ -443,13 +455,18 @@
 Non-Standard MTU on the Physical Network
 ----------------------------------------
 
-DevStack defaults to assume that the MTU on the physical network
-is 1500.  A different MTU can be specified by adding the following to
-the `localrc` part of `local.conf` on each machine.
+Neutron by default uses a MTU of 1500 bytes, which is
+the standard MTU for Ethernet.
+
+A different MTU can be specified by adding the following to
+the Neutron section of `local.conf`. For example,
+if you have network equipment that supports jumbo frames, you could
+set the MTU to 9000 bytes by adding the following
 
 ::
 
-    Q_ML2_PLUGIN_PATH_MTU=1500
+    [[post-config|/$Q_PLUGIN_CONF_FILE]]
+    global_physnet_mtu = 9000
 
 
 Disabling Next Generation Firewall Tools
diff --git a/files/debs/ceilometer-collector b/files/debs/ceilometer-collector
deleted file mode 100644
index d1e9eef..0000000
--- a/files/debs/ceilometer-collector
+++ /dev/null
@@ -1,3 +0,0 @@
-libnspr4-dev
-mongodb-server #NOPRIME
-python-pymongo #NOPRIME
diff --git a/files/debs/general b/files/debs/general
index 307cd7b..a1f2a4b 100644
--- a/files/debs/general
+++ b/files/debs/general
@@ -1,5 +1,6 @@
 bc
 bridge-utils
+bsdmainutils
 curl
 g++
 gcc
diff --git a/files/rpms-suse/ceilometer-collector b/files/rpms-suse/ceilometer-collector
deleted file mode 100644
index fc75ffa..0000000
--- a/files/rpms-suse/ceilometer-collector
+++ /dev/null
@@ -1,3 +0,0 @@
-# (devel:languages:python and server:database projects)
-mongodb
-# Not available in openSUSE main repositories, but can be fetched from OBS
diff --git a/files/rpms-suse/general b/files/rpms-suse/general
index e3dfec1..3b19071 100644
--- a/files/rpms-suse/general
+++ b/files/rpms-suse/general
@@ -25,5 +25,6 @@
 tar
 tcpdump
 unzip
+util-linux
 wget
 zlib-devel
diff --git a/files/rpms/ceilometer-collector b/files/rpms/ceilometer-collector
deleted file mode 100644
index a8b8118..0000000
--- a/files/rpms/ceilometer-collector
+++ /dev/null
@@ -1,3 +0,0 @@
-mongodb # NOPRIME
-mongodb-server #NOPRIME
-selinux-policy-targeted
diff --git a/files/rpms/general b/files/rpms/general
index 6d5fd15..2d4a97a 100644
--- a/files/rpms/general
+++ b/files/rpms/general
@@ -30,6 +30,7 @@
 tar
 tcpdump
 unzip
+util-linux
 wget
 which
 zlib-devel
diff --git a/functions b/functions
index 5730b6c..1bfb8a5 100644
--- a/functions
+++ b/functions
@@ -30,6 +30,19 @@
     declare -f -F $1 > /dev/null
 }
 
+# short_source prints out the current location of the caller in a way
+# that strips redundant directories. This is useful for PS4 usage.
+function short_source {
+    saveIFS=$IFS
+    IFS=" "
+    called=($(caller 0))
+    IFS=$saveIFS
+    file=${called[2]}
+    file=${file#$RC_DIR/}
+    printf "%-40s " "$file:${called[1]}:${called[0]}"
+}
+
+
 # Retrieve an image from a URL and upload into Glance.
 # Uses the following variables:
 #
diff --git a/functions-common b/functions-common
index 5ae9745..b0352d3 100644
--- a/functions-common
+++ b/functions-common
@@ -2322,8 +2322,9 @@
 # Resolution is only in whole seconds, so should be used for long
 # running activities.
 
-declare -A TOTAL_TIME
-declare -A START_TIME
+declare -A _TIME_TOTAL
+declare -A _TIME_START
+declare -r _TIME_BEGIN=$(date +%s)
 
 # time_start $name
 #
@@ -2331,11 +2332,11 @@
 # already started.
 function time_start {
     local name=$1
-    local start_time=${START_TIME[$name]}
+    local start_time=${_TIME_START[$name]}
     if [[ -n "$start_time" ]]; then
         die $LINENO "Trying to start the clock on $name, but it's already been started"
     fi
-    START_TIME[$name]=$(date +%s)
+    _TIME_START[$name]=$(date +%s)
 }
 
 # time_stop $name
@@ -2351,32 +2352,53 @@
     local start_time
 
     name=$1
-    start_time=${START_TIME[$name]}
+    start_time=${_TIME_START[$name]}
 
     if [[ -z "$start_time" ]]; then
         die $LINENO "Trying to stop the clock on $name, but it was never started"
     fi
     end_time=$(date +%s)
     elapsed_time=$(($end_time - $start_time))
-    total=${TOTAL_TIME[$name]:-0}
+    total=${_TIME_TOTAL[$name]:-0}
     # reset the clock so we can start it in the future
-    START_TIME[$name]=""
-    TOTAL_TIME[$name]=$(($total + $elapsed_time))
+    _TIME_START[$name]=""
+    _TIME_TOTAL[$name]=$(($total + $elapsed_time))
 }
 
 # time_totals
-#
-# prints out total time
+#  Print out total time summary
 function time_totals {
-    echo
-    echo "========================"
-    echo "DevStack Components Timed"
-    echo "========================"
-    echo
-    for t in ${!TOTAL_TIME[*]}; do
-        local v=${TOTAL_TIME[$t]}
-        echo "$t - $v secs"
+    local elapsed_time
+    local end_time
+    local len=15
+    local xtrace
+
+    end_time=$(date +%s)
+    elapsed_time=$(($end_time - $_TIME_BEGIN))
+
+    # pad 1st column this far
+    for t in ${!_TIME_TOTAL[*]}; do
+        if [[ ${#t} -gt $len ]]; then
+            len=${#t}
+        fi
     done
+
+    xtrace=$(set +o | grep xtrace)
+    set +o xtrace
+
+    echo
+    echo "========================="
+    echo "DevStack Component Timing"
+    echo "========================="
+    printf "%-${len}s %3d\n" "Total runtime" "$elapsed_time"
+    echo
+    for t in ${!_TIME_TOTAL[*]}; do
+        local v=${_TIME_TOTAL[$t]}
+        printf "%-${len}s %3d\n" "$t" "$v"
+    done
+    echo "========================="
+
+    $xtrace
 }
 
 # Restore xtrace
diff --git a/inc/python b/inc/python
index 35bab6f..495150d 100644
--- a/inc/python
+++ b/inc/python
@@ -300,6 +300,13 @@
     local flags=$2
     local extras=$3
 
+    # Normalize the directory name to avoid
+    # "installation from path or url cannot be constrained to a version"
+    # error.
+    # REVISIT(yamamoto): Remove this when fixed in pip.
+    # https://github.com/pypa/pip/pull/3582
+    project_dir=$(cd $project_dir && pwd)
+
     if [ -n "$REQUIREMENTS_DIR" ]; then
         # Constrain this package to this project directory from here on out.
         local name
diff --git a/lib/cinder b/lib/cinder
index 6401f2d..1b6a956 100644
--- a/lib/cinder
+++ b/lib/cinder
@@ -272,6 +272,8 @@
 
     iniset $CINDER_CONF DEFAULT os_region_name "$REGION_NAME"
 
+    iniset $CINDER_CONF privsep_osbrick helper_command "sudo cinder-rootwrap \$rootwrap_config privsep-helper --config-file $CINDER_CONF"
+
     if is_service_enabled c-vol && [[ -n "$CINDER_ENABLED_BACKENDS" ]]; then
         local enabled_backends=""
         local default_name=""
diff --git a/lib/keystone b/lib/keystone
index acdd7e4..71f20ac 100644
--- a/lib/keystone
+++ b/lib/keystone
@@ -340,6 +340,12 @@
     iniset $KEYSTONE_CONF DEFAULT max_token_size 16384
 
     iniset $KEYSTONE_CONF fernet_tokens key_repository "$KEYSTONE_CONF_DIR/fernet-keys/"
+
+    # Configure the project created by the 'keystone-manage bootstrap' as the cloud-admin project.
+    # The users from this project are globally admin as before, but it also
+    # allows policy changes in order to clarify the adminess scope.
+    iniset $KEYSTONE_CONF resource admin_project_domain_name default
+    iniset $KEYSTONE_CONF resource admin_project_name admin
 }
 
 # create_keystone_accounts() - Sets up common required keystone accounts
diff --git a/lib/lvm b/lib/lvm
index ae6023a..b9d7c39 100644
--- a/lib/lvm
+++ b/lib/lvm
@@ -124,7 +124,7 @@
     if [ "$CINDER_ISCSI_HELPER" = "lioadm" ]; then
         sudo cinder-rtstool get-targets | sudo xargs -rn 1 cinder-rtstool delete
     else
-        sudo tgtadm --op show --mode target | grep Target | cut -f3 -d ' ' | sudo xargs -n1 tgt-admin --delete || true
+        sudo tgtadm --op show --mode target | awk '/Target/ {print $3}' | sudo xargs -r -n1 tgt-admin --delete
     fi
     _clean_lvm_volume_group $vg
 }
diff --git a/lib/neutron-legacy b/lib/neutron-legacy
index e06a020..34f9840 100644
--- a/lib/neutron-legacy
+++ b/lib/neutron-legacy
@@ -1453,9 +1453,13 @@
 function setup_neutron_debug {
     if [[ "$Q_USE_DEBUG_COMMAND" == "True" ]]; then
         public_net_id=`_get_net_id $PUBLIC_NETWORK_NAME`
-        neutron-debug --os-tenant-name admin --os-username admin --os-password $ADMIN_PASSWORD probe-create --device-owner compute $public_net_id
+        if [[ -n $public_net_id ]]; then
+            neutron-debug --os-tenant-name admin --os-username admin --os-password $ADMIN_PASSWORD probe-create --device-owner compute $public_net_id
+        fi
         private_net_id=`_get_net_id $PRIVATE_NETWORK_NAME`
-        neutron-debug --os-tenant-name admin --os-username admin --os-password $ADMIN_PASSWORD probe-create --device-owner compute $private_net_id
+        if [[ -n $private_net_id ]]; then
+            neutron-debug --os-tenant-name admin --os-username admin --os-password $ADMIN_PASSWORD probe-create --device-owner compute $private_net_id
+        fi
     fi
 }
 
diff --git a/lib/neutron_plugins/ml2 b/lib/neutron_plugins/ml2
index 0483ef1..30e1b03 100644
--- a/lib/neutron_plugins/ml2
+++ b/lib/neutron_plugins/ml2
@@ -40,12 +40,6 @@
 # L3 Plugin to load for ML2
 ML2_L3_PLUGIN=${ML2_L3_PLUGIN:-neutron.services.l3_router.l3_router_plugin.L3RouterPlugin}
 
-# Underlying path MTU for physical network managing br-tun; use '-' instead of
-# ':-' to allow people to explicitly override this to blank, to disable
-# automatic MTU calculation for tunnelled tenant networks
-Q_ML2_PLUGIN_PATH_MTU=${Q_ML2_PLUGIN_PATH_MTU-1500}
-
-
 function populate_ml2_config {
     CONF=$1
     SECTION=$2
@@ -83,12 +77,6 @@
         echo "WARNING - The ml2 plugin is using local tenant networks, with no connectivity between hosts."
     fi
 
-    # Enable ml2 mtu calculation mechanism for networks by providing path mtu
-    # value for physical devices that are used for br-tun traffic
-    if [[ "$ENABLE_TENANT_TUNNELS" == "True" ]] && [[ "$Q_ML2_PLUGIN_PATH_MTU" != "" ]]; then
-        iniset /$Q_PLUGIN_CONF_FILE ml2 path_mtu "$Q_ML2_PLUGIN_PATH_MTU"
-    fi
-
     # Allow for overrding VLAN configuration (for example, to configure provider
     # VLANs) by first checking if Q_ML2_PLUGIN_VLAN_TYPE_OPTIONS is set.
     if [ "$Q_ML2_PLUGIN_VLAN_TYPE_OPTIONS" == "" ]; then
diff --git a/lib/nova b/lib/nova
index 3a5a47f..c7d7a2c 100644
--- a/lib/nova
+++ b/lib/nova
@@ -34,6 +34,7 @@
 
 # Set up default directories
 GITDIR["python-novaclient"]=$DEST/python-novaclient
+GITDIR["os-vif"]=$DEST/os-vif
 NOVA_DIR=$DEST/nova
 
 # Nova virtual environment
@@ -492,6 +493,8 @@
         iniset $NOVA_CONF DEFAULT bindir "/usr/bin"
     fi
 
+    iniset $NOVA_CONF privsep_osbrick helper_command "sudo nova-rootwrap \$rootwrap_config privsep-helper --config-file $NOVA_CONF"
+
     if is_service_enabled n-api; then
         if is_service_enabled n-api-meta; then
             # If running n-api-meta as a separate service
@@ -707,6 +710,10 @@
 
         recreate_database $NOVA_API_DB
         $NOVA_BIN_DIR/nova-manage api_db sync
+
+        # Run online migrations on the new databases
+        # Needed for flavor conversion
+        $NOVA_BIN_DIR/nova-manage db online_data_migrations
     fi
 
     create_nova_cache_dir
@@ -728,6 +735,13 @@
 
 # install_nova() - Collect source and prepare
 function install_nova {
+
+    # Install os-vif
+    if use_library_from_git "os-vif"; then
+        git_clone_by_name "os-vif"
+        setup_dev_lib "os-vif"
+    fi
+
     if is_service_enabled n-cpu && [[ -r $NOVA_PLUGINS/hypervisor-$VIRT_DRIVER ]]; then
         install_nova_hypervisor
     fi
diff --git a/lib/tempest b/lib/tempest
index 19b63d1..ed26caf 100644
--- a/lib/tempest
+++ b/lib/tempest
@@ -325,6 +325,24 @@
     if [[ "$OFFLINE" != "True" ]]; then
         tox -revenv --notest
     fi
+
+    # Auth
+    iniset $TEMPEST_CONFIG auth tempest_roles "Member"
+    if [[ $TEMPEST_USE_TEST_ACCOUNTS == "True" ]]; then
+        if [[ $TEMPEST_HAS_ADMIN == "True" ]]; then
+            tempest-account-generator -c $TEMPEST_CONFIG --os-username $admin_username --os-password "$password" --os-tenant-name $admin_tenant_name -r $TEMPEST_CONCURRENCY --with-admin etc/accounts.yaml
+        else
+            tempest-account-generator -c $TEMPEST_CONFIG --os-username $admin_username --os-password "$password" --os-tenant-name $admin_tenant_name -r $TEMPEST_CONCURRENCY etc/accounts.yaml
+        fi
+        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 use_dynamic_credentials ${TEMPEST_ALLOW_TENANT_ISOLATION:-False}
+
+    else
+        iniset $TEMPEST_CONFIG auth use_dynamic_credentials ${TEMPEST_ALLOW_TENANT_ISOLATION:-True}
+    fi
+
     # NOTE(mtreinish): Respect constraints on tempest verify-config venv
     tox -evenv -- pip install -c $REQUIREMENTS_DIR/upper-constraints.txt -r requirements.txt
     tox -evenv -- tempest verify-config -uro $tmp_cfg_file
@@ -553,23 +571,6 @@
         iniset $TEMPEST_CONFIG service_available cinder "False"
     fi
 
-    # Auth
-    iniset $TEMPEST_CONFIG auth tempest_roles "Member"
-    if [[ $TEMPEST_USE_TEST_ACCOUNTS == "True" ]]; then
-        if [[ $TEMPEST_HAS_ADMIN == "True" ]]; then
-            tempest-account-generator -c $TEMPEST_CONFIG --os-username $admin_username --os-password "$password" --os-tenant-name $admin_tenant_name -r $TEMPEST_CONCURRENCY --with-admin etc/accounts.yaml
-        else
-            tempest-account-generator -c $TEMPEST_CONFIG --os-username $admin_username --os-password "$password" --os-tenant-name $admin_tenant_name -r $TEMPEST_CONCURRENCY etc/accounts.yaml
-        fi
-        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 use_dynamic_credentials ${TEMPEST_ALLOW_TENANT_ISOLATION:-False}
-
-    else
-        iniset $TEMPEST_CONFIG auth use_dynamic_credentials ${TEMPEST_ALLOW_TENANT_ISOLATION:-True}
-    fi
-
     # Restore IFS
     IFS=$ifs
 }
diff --git a/lib/tls b/lib/tls
index f4740b8..ca57ed4 100644
--- a/lib/tls
+++ b/lib/tls
@@ -257,6 +257,14 @@
     local common_name=$3
     local alt_names=$4
 
+    if [ "$common_name" != "$SERVICE_HOST" ]; then
+        if [[ -z "$alt_names" ]]; then
+            alt_names="DNS:$SERVICE_HOST"
+        else
+            alt_names="$alt_names,DNS:$SERVICE_HOST"
+        fi
+    fi
+
     # Only generate the certificate if it doesn't exist yet on the disk
     if [ ! -r "$ca_dir/$cert_name.crt" ]; then
         # Generate a signing request
diff --git a/stack.sh b/stack.sh
index 5c16f04..793b7dc 100755
--- a/stack.sh
+++ b/stack.sh
@@ -799,7 +799,7 @@
     fi
 fi
 
-if is_service_enabled s-proxy; then
+if is_service_enabled swift; then
     if is_service_enabled ceilometer; then
         install_ceilometermiddleware
     fi
@@ -1004,10 +1004,6 @@
         bootstrap_keystone
     fi
 
-    if is_service_enabled tls-proxy; then
-        export OS_CACERT=$INT_CA_DIR/ca-chain.pem
-    fi
-
     # Rather than just export these, we write them out to a
     # intermediate userrc file that can also be used to debug if
     # something goes wrong between here and running
@@ -1028,6 +1024,10 @@
 
 EOF
 
+    if is_service_enabled tls-proxy; then
+        echo "export OS_CACERT=$INT_CA_DIR/ca-chain.pem" >> $TOP_DIR/userrc_early
+    fi
+
     source $TOP_DIR/userrc_early
 
     create_keystone_accounts
@@ -1118,7 +1118,7 @@
 # Storage Service
 # ---------------
 
-if is_service_enabled s-proxy; then
+if is_service_enabled swift; then
     echo_summary "Configuring Swift"
     init_swift
 fi
@@ -1172,7 +1172,7 @@
 # Only run the services specified in ``ENABLED_SERVICES``
 
 # Launch Swift Services
-if is_service_enabled s-proxy; then
+if is_service_enabled swift; then
     echo_summary "Starting Swift"
     start_swift
 fi
diff --git a/stackrc b/stackrc
index 74d507c..17d6047 100644
--- a/stackrc
+++ b/stackrc
@@ -14,9 +14,6 @@
 LC_ALL=C
 export LC_ALL
 
-# Make tracing more educational
-export PS4='+ ${BASH_SOURCE:-}:${FUNCNAME[0]:-}:L${LINENO:-}:   '
-
 # Find the other rc files
 RC_DIR=$(cd $(dirname "${BASH_SOURCE:-$0}") && pwd)
 
@@ -132,6 +129,16 @@
     source $RC_DIR/.localrc.auto
 fi
 
+# Use color for logging output (only available if syslog is not used)
+LOG_COLOR=$(trueorfalse True LOG_COLOR)
+
+# Make tracing more educational
+if [[ "$LOG_COLOR" == "True" ]]; then
+    export PS4='+\[$(tput setaf 242)\]$(short_source)\[$(tput sgr0)\] '
+else
+    export PS4='+ $(short_source):   '
+fi
+
 # Configure Identity API version: 2.0, 3
 IDENTITY_API_VERSION=${IDENTITY_API_VERSION:-2.0}
 
@@ -477,6 +484,10 @@
 GITREPO["os-brick"]=${OS_BRICK_REPO:-${GIT_BASE}/openstack/os-brick.git}
 GITBRANCH["os-brick"]=${OS_BRICK_BRANCH:-master}
 
+# os-vif library to communicate between Neutron to Nova
+GITREPO["os-vif"]=${OS_VIF_REPO:-${GIT_BASE}/openstack/os-vif.git}
+GITBRANCH["os-vif"]=${OS_VIF_BRANCH:-master}
+
 # ironic common lib
 GITREPO["ironic-lib"]=${IRONIC_LIB_REPO:-${GIT_BASE}/openstack/ironic-lib.git}
 GITBRANCH["ironic-lib"]=${IRONIC_LIB_BRANCH:-master}
@@ -785,9 +796,6 @@
 SYSLOG_HOST=${SYSLOG_HOST:-$HOST_IP}
 SYSLOG_PORT=${SYSLOG_PORT:-516}
 
-# Use color for logging output (only available if syslog is not used)
-LOG_COLOR=$(trueorfalse True LOG_COLOR)
-
 # Set global ``GIT_DEPTH=<number>`` to limit the history depth of the git clone
 # Set to 0 to disable shallow cloning
 GIT_DEPTH=${GIT_DEPTH:-0}
diff --git a/tests/test_functions.sh b/tests/test_functions.sh
index be8dc5e..8aae23d 100755
--- a/tests/test_functions.sh
+++ b/tests/test_functions.sh
@@ -9,6 +9,22 @@
 
 source $TOP/tests/unittest.sh
 
+echo "Testing generate_hex_string()"
+
+VAL=$(generate_hex_string 16)
+if [[ ${#VAL} -eq 32 ]]; then
+    passed "OK"
+else
+    failed "generate_hex_string 16 failed ${#VAL}"
+fi
+
+VAL=$(generate_hex_string 32)
+if [[ ${#VAL} -eq 64 ]]; then
+    passed "OK"
+else
+    failed "generate_hex_string 32 failed ${#VAL}"
+fi
+
 echo "Testing die_if_not_set()"
 
 bash -c "source $TOP/functions; X=`echo Y && true`; die_if_not_set $LINENO X 'not OK'"
diff --git a/tests/test_libs_from_pypi.sh b/tests/test_libs_from_pypi.sh
index ee11fd2..f01db6d 100755
--- a/tests/test_libs_from_pypi.sh
+++ b/tests/test_libs_from_pypi.sh
@@ -42,7 +42,7 @@
 ALL_LIBS+=" debtcollector os-brick automaton futurist oslo.service"
 ALL_LIBS+=" oslo.cache oslo.reports osprofiler"
 ALL_LIBS+=" keystoneauth ironic-lib neutron-lib oslo.privsep"
-ALL_LIBS+=" diskimage-builder"
+ALL_LIBS+=" diskimage-builder os-vif"
 
 # Generate the above list with
 # echo ${!GITREPO[@]}
diff --git a/tools/create_userrc.sh b/tools/create_userrc.sh
index 3325c5e..a7278e4 100755
--- a/tools/create_userrc.sh
+++ b/tools/create_userrc.sh
@@ -7,6 +7,22 @@
 # Warning: This script just for development purposes
 
 set -o errexit
+
+# short_source prints out the current location of the caller in a way
+# that strips redundant directories. This is useful for PS4
+# usage. Needed before we start tracing due to how we set
+# PS4. Normally we'd pick this up from stackrc, but that's not sourced
+# here.
+function short_source {
+    saveIFS=$IFS
+    IFS=" "
+    called=($(caller 0))
+    IFS=$saveIFS
+    file=${called[2]}
+    file=${file#$RC_DIR/}
+    printf "%-40s " "$file:${called[1]}:${called[0]}"
+}
+
 set -o xtrace
 
 ACCOUNT_DIR=./accrc
diff --git a/tools/install_pip.sh b/tools/install_pip.sh
index 2a9d813..dfa4f42 100755
--- a/tools/install_pip.sh
+++ b/tools/install_pip.sh
@@ -2,16 +2,12 @@
 
 # **install_pip.sh**
 
-# install_pip.sh [--pip-version <version>] [--use-get-pip] [--force]
-#
 # Update pip and friends to a known common version
 
 # Assumptions:
-# - update pip to $INSTALL_PIP_VERSION
 # - if USE_PYTHON3=True, PYTHON3_VERSION refers to a version already installed
 
 set -o errexit
-set -o xtrace
 
 # Keep track of the current directory
 TOOLS_DIR=$(cd $(dirname "$0") && pwd)
@@ -23,6 +19,9 @@
 # Import common functions
 source $TOP_DIR/stackrc
 
+# don't start tracing until after we've sourced the world
+set -o xtrace
+
 FILES=$TOP_DIR/files
 
 PIP_GET_PIP_URL=https://bootstrap.pypa.io/get-pip.py
diff --git a/tox.ini b/tox.ini
index 3dfc377..4ec2939 100644
--- a/tox.ini
+++ b/tox.ini
@@ -18,6 +18,7 @@
          -not \( -type d -name .?\* -prune \)    \
          -not \( -type d -name doc -prune \)     \
          -not \( -type d -name shocco -prune \)  \
+         -not \( -type f -name localrc -prune \) \
          -type f                                 \
          -not -name \*~                          \
          -not -name \*.md                        \