Merge "exercises/aggregates.sh: Only source openrc once"
diff --git a/README.md b/README.md
index acc3e5a..ee7f0e7 100644
--- a/README.md
+++ b/README.md
@@ -77,361 +77,21 @@
 of your hypervisor of choice to reduce testing cycle times.  You might even save
 enough time to write one more feature before the next feature freeze...
 
-``stack.sh`` needs to have root access for a lot of tasks, but uses ``sudo``
-for all of those tasks.  However, it needs to be not-root for most of its
-work and for all of the OpenStack services.  ``stack.sh`` specifically
-does not run if started as root.
+``stack.sh`` needs to have root access for a lot of tasks, but uses
+``sudo`` for all of those tasks.  However, it needs to be not-root for
+most of its work and for all of the OpenStack services.  ``stack.sh``
+specifically does not run if started as root.
 
-This is a recent change (Oct 2013) from the previous behaviour of
-automatically creating a ``stack`` user.  Automatically creating
-user accounts is not the right response to running as root, so
-that bit is now an explicit step using ``tools/create-stack-user.sh``.
-Run that (as root!) or just check it out to see what DevStack's
-expectations are for the account it runs under.  Many people simply
-use their usual login (the default 'ubuntu' login on a UEC image
-for example).
+DevStack will not automatically create the user, but provides a helper
+script in ``tools/create-stack-user.sh``.  Run that (as root!) or just
+check it out to see what DevStack's expectations are for the account
+it runs under.  Many people simply use their usual login (the default
+'ubuntu' login on a UEC image for example).
 
 # Customizing
 
-You can override environment variables used in `stack.sh` by creating file
-name `local.conf` with a ``localrc`` section as shown below.  It is likely
-that you will need to do this to tweak your networking configuration should
-you need to access your cloud from a different host.
-
-    [[local|localrc]]
-    VARIABLE=value
-
-See the **Local Configuration** section below for more details.
-
-# Database Backend
-
-Multiple database backends are available. The available databases are defined
-in the lib/databases directory.
-`mysql` is the default database, choose a different one by putting the
-following in the `localrc` section:
-
-    disable_service mysql
-    enable_service postgresql
-
-`mysql` is the default database.
-
-# RPC Backend
-
-Support for a RabbitMQ RPC backend is included. Additional RPC backends may
-be available via external plugins.  Enabling or disabling RabbitMQ is handled
-via the usual service functions and ``ENABLED_SERVICES``.
-
-Example disabling RabbitMQ in ``local.conf``:
-
-    disable_service rabbit
-
-# Apache Frontend
-
-Apache web server can be enabled for wsgi services that support being deployed
-under HTTPD + mod_wsgi. By default, services that recommend running under
-HTTPD + mod_wsgi are deployed under Apache. To use an alternative deployment
-strategy (e.g. eventlet) for services that support an alternative to HTTPD +
-mod_wsgi set ``ENABLE_HTTPD_MOD_WSGI_SERVICES`` to ``False`` in your
-``local.conf``.
-
-Each service that can be run under HTTPD + mod_wsgi also has an override
-toggle available that can be set in your ``local.conf``.
-
-Keystone is run under HTTPD + mod_wsgi by default.
-
-Example (Keystone):
-
-    KEYSTONE_USE_MOD_WSGI="True"
-
-Example (Nova):
-
-    NOVA_USE_MOD_WSGI="True"
-
-Example (Swift):
-
-    SWIFT_USE_MOD_WSGI="True"
-
-# Swift
-
-Swift is disabled by default.  When enabled, it is configured with
-only one replica to avoid being IO/memory intensive on a small
-vm. When running with only one replica the account, container and
-object services will run directly in screen. The others services like
-replicator, updaters or auditor runs in background.
-
-If you would like to enable Swift you can add this to your `localrc` section:
-
-    enable_service s-proxy s-object s-container s-account
-
-If you want a minimal Swift install with only Swift and Keystone you
-can have this instead in your `localrc` section:
-
-    disable_all_services
-    enable_service key mysql s-proxy s-object s-container s-account
-
-If you only want to do some testing of a real normal swift cluster
-with multiple replicas you can do so by customizing the variable
-`SWIFT_REPLICAS` in your `localrc` section (usually to 3).
-
-# Swift S3
-
-If you are enabling `swift3` in `ENABLED_SERVICES` DevStack will
-install the swift3 middleware emulation. Swift will be configured to
-act as a S3 endpoint for Keystone so effectively replacing the
-`nova-objectstore`.
-
-Only Swift proxy server is launched in the screen session all other
-services are started in background and managed by `swift-init` tool.
-
-# Neutron
-
-Basic Setup
-
-In order to enable Neutron in a single node setup, you'll need the
-following settings in your `local.conf`:
-
-    disable_service n-net
-    enable_service q-svc
-    enable_service q-agt
-    enable_service q-dhcp
-    enable_service q-l3
-    enable_service q-meta
-    enable_service q-metering
-
-Then run `stack.sh` as normal.
-
-DevStack supports setting specific Neutron configuration flags to the
-service, ML2 plugin, DHCP and L3 configuration files:
-
-    [[post-config|/$Q_PLUGIN_CONF_FILE]]
-    [ml2]
-    mechanism_drivers=openvswitch,l2population
-
-    [[post-config|$NEUTRON_CONF]]
-    [DEFAULT]
-    quota_port=42
-
-    [[post-config|$Q_L3_CONF_FILE]]
-    [DEFAULT]
-    agent_mode=legacy
-
-    [[post-config|$Q_DHCP_CONF_FILE]]
-    [DEFAULT]
-    dnsmasq_dns_servers = 8.8.8.8,8.8.4.4
-
-The ML2 plugin can run with the OVS, LinuxBridge, or Hyper-V agents on compute
-hosts. This is a simple way to configure the ml2 plugin:
-
-    # VLAN configuration
-    ENABLE_TENANT_VLANS=True
-
-    # GRE tunnel configuration
-    ENABLE_TENANT_TUNNELS=True
-
-    # VXLAN tunnel configuration
-    Q_ML2_TENANT_NETWORK_TYPE=vxlan
-
-The above will default in DevStack to using the OVS on each compute host.
-To change this, set the `Q_AGENT` variable to the agent you want to run
-(e.g. linuxbridge).
-
-    Variable Name                    Notes
-    ----------------------------------------------------------------------------
-    Q_AGENT                          This specifies which agent to run with the
-                                     ML2 Plugin (Typically either `openvswitch`
-                                     or `linuxbridge`).
-                                     Defaults to `openvswitch`.
-    Q_ML2_PLUGIN_MECHANISM_DRIVERS   The ML2 MechanismDrivers to load. The default
-                                     is `openvswitch,linuxbridge`.
-    Q_ML2_PLUGIN_TYPE_DRIVERS        The ML2 TypeDrivers to load. Defaults to
-                                     all available TypeDrivers.
-    Q_ML2_PLUGIN_GRE_TYPE_OPTIONS    GRE TypeDriver options. Defaults to
-                                     `tunnel_id_ranges=1:1000'.
-    Q_ML2_PLUGIN_VXLAN_TYPE_OPTIONS  VXLAN TypeDriver options. Defaults to
-                                     `vni_ranges=1001:2000`
-    Q_ML2_PLUGIN_VLAN_TYPE_OPTIONS   VLAN TypeDriver options. Defaults to none.
-
-# Heat
-
-Heat is disabled by default (see `stackrc` file). To enable it explicitly
-you'll need the following settings in your `localrc` section:
-
-    enable_service heat h-api h-api-cfn h-api-cw h-eng
-
-Heat can also run in standalone mode, and be configured to orchestrate
-on an external OpenStack cloud. To launch only Heat in standalone mode
-you'll need the following settings in your `localrc` section:
-
-    disable_all_services
-    enable_service rabbit mysql heat h-api h-api-cfn h-api-cw h-eng
-    HEAT_STANDALONE=True
-    KEYSTONE_SERVICE_HOST=...
-    KEYSTONE_AUTH_HOST=...
-
-# Tempest
-
-If tempest has been successfully configured, a basic set of smoke
-tests can be run as follows:
-
-    $ cd /opt/stack/tempest
-    $ tox -efull  tempest.scenario.test_network_basic_ops
-
-By default tempest is downloaded and the config file is generated, but the
-tempest package is not installed in the system's global site-packages (the
-package install includes installing dependences). So tempest won't run
-outside of tox. If you would like to install it add the following to your
-``localrc`` section:
-
-    INSTALL_TEMPEST=True
-
-# DevStack on Xenserver
-
-If you would like to use Xenserver as the hypervisor, please refer
-to the instructions in `./tools/xen/README.md`.
-
-# Additional Projects
-
-DevStack has a hook mechanism to call out to a dispatch script at specific
-points in the execution of `stack.sh`, `unstack.sh` and `clean.sh`.  This
-allows upper-layer projects, especially those that the lower layer projects
-have no dependency on, to be added to DevStack without modifying the core
-scripts.  Tempest is built this way as an example of how to structure the
-dispatch script, see `extras.d/80-tempest.sh`.  See `extras.d/README.md`
-for more information.
-
-# Multi-Node Setup
-
-A more interesting setup involves running multiple compute nodes, with Neutron
-networks connecting VMs on different compute nodes.
-You should run at least one "controller node", which should have a `stackrc`
-that includes at least:
-
-    disable_service n-net
-    enable_service q-svc
-    enable_service q-agt
-    enable_service q-dhcp
-    enable_service q-l3
-    enable_service q-meta
-    enable_service neutron
-
-You likely want to change your `localrc` section to run a scheduler that
-will balance VMs across hosts:
-
-    SCHEDULER=nova.scheduler.filter_scheduler.FilterScheduler
-
-You can then run many compute nodes, each of which should have a `stackrc`
-which includes the following, with the IP address of the above controller node:
-
-    ENABLED_SERVICES=n-cpu,rabbit,neutron,q-agt
-    SERVICE_HOST=[IP of controller node]
-    MYSQL_HOST=$SERVICE_HOST
-    RABBIT_HOST=$SERVICE_HOST
-    Q_HOST=$SERVICE_HOST
-    MATCHMAKER_REDIS_HOST=$SERVICE_HOST
-
-# Multi-Region Setup
-
-We want to setup two devstack (RegionOne and RegionTwo) with shared keystone
-(same users and services) and horizon.
-Keystone and Horizon will be located in RegionOne.
-Full spec is available at:
-https://wiki.openstack.org/wiki/Heat/Blueprints/Multi_Region_Support_for_Heat.
-
-In RegionOne:
-
-    REGION_NAME=RegionOne
-
-In RegionTwo:
-
-    disable_service horizon
-    KEYSTONE_SERVICE_HOST=<KEYSTONE_IP_ADDRESS_FROM_REGION_ONE>
-    KEYSTONE_AUTH_HOST=<KEYSTONE_IP_ADDRESS_FROM_REGION_ONE>
-    REGION_NAME=RegionTwo
-
-# Cells
-
-Cells is a new scaling option with a full spec at:
-http://wiki.openstack.org/blueprint-nova-compute-cells.
-
-To setup a cells environment add the following to your `localrc` section:
-
-    enable_service n-cell
-
-Be aware that there are some features currently missing in cells, one notable
-one being security groups.  The exercises have been patched to disable
-functionality not supported by cells.
-
-# IPv6
-
-By default, most Openstack services are bound to 0.0.0.0
-and service endpoints are registered as IPv4 addresses.
-A new variable was created to control this behavior, and to
-allow for operation over IPv6 instead of IPv4.
-
-For this, add the following to `local.conf`:
-
-    SERVICE_IP_VERSION=6
-
-When set to "6" devstack services will open listen sockets on ::
-and service endpoints will be registered using HOST_IPV6 as the
-address.  The default value for this setting is `4`.  Dual-mode
-support, for example `4+6` is not currently supported.
-
-
-# Local Configuration
-
-Historically DevStack has used ``localrc`` to contain all local configuration
-and customizations. More and more of the configuration variables available for
-DevStack are passed-through to the individual project configuration files.
-The old mechanism for this required specific code for each file and did not
-scale well.  This is handled now by a master local configuration file.
-
-# local.conf
-
-The new config file ``local.conf`` is an extended-INI format that introduces
-a new meta-section header that provides some additional information such
-as a phase name and destination config filename:
-
-    [[ <phase> | <config-file-name> ]]
-
-where ``<phase>`` is one of a set of phase names defined by ``stack.sh``
-and ``<config-file-name>`` is the configuration filename.  The filename is
-eval'ed in the ``stack.sh`` context so all environment variables are
-available and may be used.  Using the project config file variables in
-the header is strongly suggested (see the ``NOVA_CONF`` example below).
-If the path of the config file does not exist it is skipped.
-
-The defined phases are:
-
-* **local** - extracts ``localrc`` from ``local.conf`` before ``stackrc`` is sourced
-* **post-config** - runs after the layer 2 services are configured
-                    and before they are started
-* **extra** - runs after services are started and before any files
-              in ``extra.d`` are executed
-* **post-extra** - runs after files in ``extra.d`` are executed
-
-The file is processed strictly in sequence; meta-sections may be specified more
-than once but if any settings are duplicated the last to appear in the file
-will be used.
-
-    [[post-config|$NOVA_CONF]]
-    [DEFAULT]
-    use_syslog = True
-
-    [osapi_v3]
-    enabled = False
-
-A specific meta-section ``local|localrc`` is used to provide a default
-``localrc`` file (actually ``.localrc.auto``).  This allows all custom
-settings for DevStack to be contained in a single file.  If ``localrc``
-exists it will be used instead to preserve backward-compatibility.
-
-    [[local|localrc]]
-    FIXED_RANGE=10.254.1.0/24
-    ADMIN_PASSWORD=speciale
-    LOGFILE=$DEST/logs/stack.sh.log
-
-Note that ``Q_PLUGIN_CONF_FILE`` is unique in that it is assumed to *NOT*
-start with a ``/`` (slash) character.  A slash will need to be added:
-
-    [[post-config|/$Q_PLUGIN_CONF_FILE]]
+DevStack can be extensively configured via the configuration file
+`local.conf`.  It is likely that you will need to provide and modify
+this file if you want anything other than the most basic setup.  Start
+by reading the [configuration guide](doc/source/configuration.rst) for
+details of the configuration file and the many available options.
\ No newline at end of file
diff --git a/doc/source/configuration.rst b/doc/source/configuration.rst
index 05a8d95..fe23d6c 100644
--- a/doc/source/configuration.rst
+++ b/doc/source/configuration.rst
@@ -6,32 +6,15 @@
    :local:
    :depth: 1
 
-DevStack has always tried to be mostly-functional with a minimal amount
-of configuration. The number of options has ballooned as projects add
-features, new projects added and more combinations need to be tested.
-Historically DevStack obtained all local configuration and
-customizations from a ``localrc`` file. The number of configuration
-variables that are simply passed-through to the individual project
-configuration files is also increasing. The old mechanism for this
-(``EXTRAS_OPTS`` and friends) required specific code for each file and
-did not scale well.
-
-In Oct 2013 a new configuration method was introduced (in `review
-46768 <https://review.openstack.org/#/c/46768/>`__) to hopefully
-simplify this process and meet the following goals:
-
--  contain all non-default local configuration in a single file
--  be backward-compatible with ``localrc`` to smooth the transition
-   process
--  allow settings in arbitrary configuration files to be changed
-
 local.conf
 ==========
 
-The new configuration file is ``local.conf`` and resides in the root
-DevStack directory like the old ``localrc`` file. It is a modified INI
-format file that introduces a meta-section header to carry additional
-information regarding the configuration files to be changed.
+DevStack configuration is modified via the file ``local.conf``.  It is
+a modified INI format file that introduces a meta-section header to
+carry additional information regarding the configuration files to be
+changed.
+
+A sample is provided in ``devstack/samples``
 
 The new header is similar to a normal INI section header but with double
 brackets (``[[ ... ]]``) and two internal fields separated by a pipe
@@ -146,6 +129,15 @@
 Setting it here also makes it available for ``openrc`` to set ``OS_AUTH_URL``.
 ``HOST_IPV6`` is not set by default.
 
+Historical Notes
+================
+
+Historically DevStack obtained all local configuration and
+customizations from a ``localrc`` file.  In Oct 2013 the
+``local.conf`` configuration method was introduced (in `review 46768
+<https://review.openstack.org/#/c/46768/>`__) to simplify this
+process.
+
 Configuration Notes
 ===================
 
@@ -226,6 +218,86 @@
         SYSLOG_HOST=$HOST_IP
         SYSLOG_PORT=516
 
+
+Example Logging Configuration
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+For example, non-interactive installs probably wish to save output to
+a file, keep service logs and disable color in the stored files.
+
+   ::
+
+       [[local|localrc]]
+       DEST=/opt/stack/
+       LOGDIR=$DEST/logs
+       LOGFILE=$LOGDIR/stack.sh.log
+       LOG_COLOR=False
+
+Database Backend
+----------------
+
+Multiple database backends are available. The available databases are defined
+in the lib/databases directory.
+`mysql` is the default database, choose a different one by putting the
+following in the `localrc` section:
+
+   ::
+
+      disable_service mysql
+      enable_service postgresql
+
+`mysql` is the default database.
+
+RPC Backend
+-----------
+
+Support for a RabbitMQ RPC backend is included. Additional RPC
+backends may be available via external plugins.  Enabling or disabling
+RabbitMQ is handled via the usual service functions and
+``ENABLED_SERVICES``.
+
+Example disabling RabbitMQ in ``local.conf``:
+
+::
+    disable_service rabbit
+
+
+Apache Frontend
+---------------
+
+The Apache web server can be enabled for wsgi services that support
+being deployed under HTTPD + mod_wsgi. By default, services that
+recommend running under HTTPD + mod_wsgi are deployed under Apache. To
+use an alternative deployment strategy (e.g. eventlet) for services
+that support an alternative to HTTPD + mod_wsgi set
+``ENABLE_HTTPD_MOD_WSGI_SERVICES`` to ``False`` in your
+``local.conf``.
+
+Each service that can be run under HTTPD + mod_wsgi also has an
+override toggle available that can be set in your ``local.conf``.
+
+Keystone is run under Apache with ``mod_wsgi`` by default.
+
+Example (Keystone)
+
+::
+
+    KEYSTONE_USE_MOD_WSGI="True"
+
+Example (Nova):
+
+::
+
+    NOVA_USE_MOD_WSGI="True"
+
+Example (Swift):
+
+::
+
+    SWIFT_USE_MOD_WSGI="True"
+
+
+
 Libraries from Git
 ------------------
 
@@ -293,48 +365,6 @@
 
         PIP_UPGRADE=True
 
-Swift
------
-
-Swift is now used as the back-end for the S3-like object store.  When
-enabled Nova's objectstore (``n-obj`` in ``ENABLED_SERVICES``) is
-automatically disabled. Enable Swift by adding it services to
-``ENABLED_SERVICES``
-
-    ::
-
-       enable_service s-proxy s-object s-container s-account
-
-Setting Swift's hash value is required and you will be prompted for it
-if Swift is enabled so just set it to something already:
-
-    ::
-
-        SWIFT_HASH=66a3d6b56c1f479c8b4e70ab5c2000f5
-
-For development purposes the default number of replicas is set to
-``1`` to reduce the overhead required. To better simulate a production
-deployment set this to ``3`` or more.
-
-    ::
-
-        SWIFT_REPLICAS=3
-
-The data for Swift is stored in the source tree by default (in
-``$DEST/swift/data``) and can be moved by setting
-``SWIFT_DATA_DIR``. The specified directory will be created if it does
-not exist.
-
-    ::
-
-        SWIFT_DATA_DIR=$DEST/data/swift
-
-*Note*: Previously just enabling ``swift`` was sufficient to start the
-Swift services. That does not provide proper service granularity,
-particularly in multi-host configurations, and is considered
-deprecated. Some service combination tests now check for specific
-Swift services and the old blanket acceptance will longer work
-correctly.
 
 Service Catalog Backend
 -----------------------
@@ -352,47 +382,6 @@
 DevStack's default configuration in ``sql`` mode is set in
 ``files/keystone_data.sh``
 
-Cinder
-------
-
-The logical volume group used to hold the Cinder-managed volumes is
-set by ``VOLUME_GROUP``, the logical volume name prefix is set with
-``VOLUME_NAME_PREFIX`` and the size of the volume backing file is set
-with ``VOLUME_BACKING_FILE_SIZE``.
-
-    ::
-
-        VOLUME_GROUP="stack-volumes"
-        VOLUME_NAME_PREFIX="volume-"
-        VOLUME_BACKING_FILE_SIZE=10250M
-
-Multi-host DevStack
--------------------
-
-Running DevStack with multiple hosts requires a custom ``local.conf``
-section for each host. The master is the same as a single host
-installation with ``MULTI_HOST=True``. The slaves have fewer services
-enabled and a couple of host variables pointing to the master.
-
-Master
-~~~~~~
-
-Set ``MULTI_HOST`` to true
-    ::
-
-        MULTI_HOST=True
-
-Slave
-~~~~~
-
-Set the following options to point to the master
-
-    ::
-
-        MYSQL_HOST=w.x.y.z
-        RABBIT_HOST=w.x.y.z
-        GLANCE_HOSTPORT=w.x.y.z:9292
-        ENABLED_SERVICES=n-vol,n-cpu,n-net,n-api
 
 IP Version
 ----------
@@ -445,29 +434,163 @@
 
         HOST_IPV6=${some_local_ipv6_address}
 
-Examples
-========
+Multi-node setup
+~~~~~~~~~~~~~~~~
 
--  Eliminate a Cinder pass-through (``CINDER_PERIODIC_INTERVAL``):
+See the :doc:`multi-node lab guide<guides/multinode-lab>`
 
-   ::
+Projects
+--------
 
-       [[post-config|$CINDER_CONF]]
-       [DEFAULT]
-       periodic_interval = 60
+Neutron
+~~~~~~~
 
--  Sample ``local.conf`` with screen logging enabled:
+See the :doc:`neutron configuration guide<guides/neutron>` for
+details on configuration of Neutron
 
-   ::
 
-       [[local|localrc]]
-       FIXED_RANGE=10.254.1.0/24
-       NETWORK_GATEWAY=10.254.1.1
-       LOGDAYS=1
-       LOGDIR=$DEST/logs
-       LOGFILE=$LOGDIR/stack.sh.log
-       ADMIN_PASSWORD=quiet
-       DATABASE_PASSWORD=$ADMIN_PASSWORD
-       RABBIT_PASSWORD=$ADMIN_PASSWORD
-       SERVICE_PASSWORD=$ADMIN_PASSWORD
-       SERVICE_TOKEN=a682f596-76f3-11e3-b3b2-e716f9080d50
+Swift
+~~~~~
+
+Swift is disabled by default.  When enabled, it is configured with
+only one replica to avoid being IO/memory intensive on a small
+VM. When running with only one replica the account, container and
+object services will run directly in screen. The others services like
+replicator, updaters or auditor runs in background.
+
+If you would like to enable Swift you can add this to your `localrc`
+section:
+
+::
+
+    enable_service s-proxy s-object s-container s-account
+
+If you want a minimal Swift install with only Swift and Keystone you
+can have this instead in your `localrc` section:
+
+::
+
+    disable_all_services
+    enable_service key mysql s-proxy s-object s-container s-account
+
+If you only want to do some testing of a real normal swift cluster
+with multiple replicas you can do so by customizing the variable
+`SWIFT_REPLICAS` in your `localrc` section (usually to 3).
+
+Swift S3
+++++++++
+
+If you are enabling `swift3` in `ENABLED_SERVICES` DevStack will
+install the swift3 middleware emulation. Swift will be configured to
+act as a S3 endpoint for Keystone so effectively replacing the
+`nova-objectstore`.
+
+Only Swift proxy server is launched in the screen session all other
+services are started in background and managed by `swift-init` tool.
+
+Heat
+~~~~
+
+Heat is disabled by default (see `stackrc` file). To enable it
+explicitly you'll need the following settings in your `localrc`
+section
+
+::
+
+    enable_service heat h-api h-api-cfn h-api-cw h-eng
+
+Heat can also run in standalone mode, and be configured to orchestrate
+on an external OpenStack cloud. To launch only Heat in standalone mode
+you'll need the following settings in your `localrc` section
+
+::
+
+    disable_all_services
+    enable_service rabbit mysql heat h-api h-api-cfn h-api-cw h-eng
+    HEAT_STANDALONE=True
+    KEYSTONE_SERVICE_HOST=...
+    KEYSTONE_AUTH_HOST=...
+
+Tempest
+~~~~~~~
+
+If tempest has been successfully configured, a basic set of smoke
+tests can be run as follows:
+
+::
+
+    $ cd /opt/stack/tempest
+    $ tox -efull  tempest.scenario.test_network_basic_ops
+
+By default tempest is downloaded and the config file is generated, but the
+tempest package is not installed in the system's global site-packages (the
+package install includes installing dependences). So tempest won't run
+outside of tox. If you would like to install it add the following to your
+``localrc`` section:
+
+::
+
+    INSTALL_TEMPEST=True
+
+
+Xenserver
+~~~~~~~~~
+
+If you would like to use Xenserver as the hypervisor, please refer to
+the instructions in `./tools/xen/README.md`.
+
+Cells
+~~~~~
+
+`Cells <http://wiki.openstack.org/blueprint-nova-compute-cells>`__ is
+an alternative scaling option.  To setup a cells environment add the
+following to your `localrc` section:
+
+::
+
+    enable_service n-cell
+
+Be aware that there are some features currently missing in cells, one
+notable one being security groups.  The exercises have been patched to
+disable functionality not supported by cells.
+
+Cinder
+~~~~~~
+
+The logical volume group used to hold the Cinder-managed volumes is
+set by ``VOLUME_GROUP``, the logical volume name prefix is set with
+``VOLUME_NAME_PREFIX`` and the size of the volume backing file is set
+with ``VOLUME_BACKING_FILE_SIZE``.
+
+    ::
+
+        VOLUME_GROUP="stack-volumes"
+        VOLUME_NAME_PREFIX="volume-"
+        VOLUME_BACKING_FILE_SIZE=10250M
+
+
+Keystone
+~~~~~~~~
+
+Multi-Region Setup
+++++++++++++++++++
+
+We want to setup two devstack (RegionOne and RegionTwo) with shared
+keystone (same users and services) and horizon.  Keystone and Horizon
+will be located in RegionOne.  Full spec is available at:
+`<https://wiki.openstack.org/wiki/Heat/Blueprints/Multi_Region_Support_for_Heat>`__.
+
+In RegionOne:
+
+::
+
+    REGION_NAME=RegionOne
+
+In RegionTwo:
+
+::
+   
+    disable_service horizon
+    KEYSTONE_SERVICE_HOST=<KEYSTONE_IP_ADDRESS_FROM_REGION_ONE>
+    KEYSTONE_AUTH_HOST=<KEYSTONE_IP_ADDRESS_FROM_REGION_ONE>
+    REGION_NAME=RegionTwo
diff --git a/doc/source/guides/multinode-lab.rst b/doc/source/guides/multinode-lab.rst
index 557b522..1530a84 100644
--- a/doc/source/guides/multinode-lab.rst
+++ b/doc/source/guides/multinode-lab.rst
@@ -175,12 +175,12 @@
     SERVICE_TOKEN=xyzpdqlazydog
     DATABASE_TYPE=mysql
     SERVICE_HOST=192.168.42.11
-    MYSQL_HOST=192.168.42.11
-    RABBIT_HOST=192.168.42.11
-    GLANCE_HOSTPORT=192.168.42.11:9292
+    MYSQL_HOST=$SERVICE_HOST
+    RABBIT_HOST=$SERVICE_HOST
+    GLANCE_HOSTPORT=$SERVICE_HOST:9292
     ENABLED_SERVICES=n-cpu,n-net,n-api-meta,c-vol
     NOVA_VNC_ENABLED=True
-    NOVNCPROXY_URL="http://192.168.42.11:6080/vnc_auto.html"
+    NOVNCPROXY_URL="http://$SERVICE_HOST:6080/vnc_auto.html"
     VNCSERVER_LISTEN=$HOST_IP
     VNCSERVER_PROXYCLIENT_ADDRESS=$VNCSERVER_LISTEN
 
diff --git a/files/apache-horizon.template b/files/apache-horizon.template
index 6883898..bfd7567 100644
--- a/files/apache-horizon.template
+++ b/files/apache-horizon.template
@@ -1,5 +1,5 @@
 <VirtualHost *:80>
-    WSGIScriptAlias / %HORIZON_DIR%/openstack_dashboard/wsgi/django.wsgi
+    WSGIScriptAlias %WEBROOT% %HORIZON_DIR%/openstack_dashboard/wsgi/django.wsgi
     WSGIDaemonProcess horizon user=%USER% group=%GROUP% processes=3 threads=10 home=%HORIZON_DIR% display-name=%{GROUP}
     WSGIApplicationGroup %{GLOBAL}
 
@@ -8,7 +8,10 @@
     WSGIProcessGroup horizon
 
     DocumentRoot %HORIZON_DIR%/.blackhole/
-    Alias /media %HORIZON_DIR%/openstack_dashboard/static
+    Alias %WEBROOT%/media %HORIZON_DIR%/openstack_dashboard/static
+    Alias %WEBROOT%/static %HORIZON_DIR%/static
+
+    RedirectMatch "^/$" "%WEBROOT%/"
 
     <Directory />
         Options FollowSymLinks
diff --git a/files/debs/n-cpu b/files/debs/n-cpu
index 5d5052a..ffc947a 100644
--- a/files/debs/n-cpu
+++ b/files/debs/n-cpu
@@ -5,3 +5,4 @@
 sysfsutils
 sg3-utils
 python-guestfs # NOPRIME
+cryptsetup
diff --git a/files/rpms-suse/n-cpu b/files/rpms-suse/n-cpu
index 7040b84..b3a468d 100644
--- a/files/rpms-suse/n-cpu
+++ b/files/rpms-suse/n-cpu
@@ -4,3 +4,4 @@
 open-iscsi
 sysfsutils
 sg3_utils
+cryptsetup
diff --git a/files/rpms/n-cpu b/files/rpms/n-cpu
index c1a8e8f..81278b3 100644
--- a/files/rpms/n-cpu
+++ b/files/rpms/n-cpu
@@ -4,4 +4,4 @@
 genisoimage
 sysfsutils
 sg3_utils
-
+cryptsetup
diff --git a/functions b/functions
index 5bbe18f..4001e9d 100644
--- a/functions
+++ b/functions
@@ -10,6 +10,10 @@
 # - ``GLANCE_HOSTPORT``
 #
 
+# ensure we don't re-source this in the same environment
+[[ -z "$_DEVSTACK_FUNCTIONS" ]] || return 0
+declare -r _DEVSTACK_FUNCTIONS=1
+
 # Include the common functions
 FUNC_DIR=$(cd $(dirname "${BASH_SOURCE:-$0}") && pwd)
 source ${FUNC_DIR}/functions-common
diff --git a/functions-common b/functions-common
index 60cf04c..f6a5253 100644
--- a/functions-common
+++ b/functions-common
@@ -28,7 +28,6 @@
 # - ``REQUIREMENTS_DIR``
 # - ``STACK_USER``
 # - ``TRACK_DEPENDS``
-# - ``UNDO_REQUIREMENTS``
 # - ``http_proxy``, ``https_proxy``, ``no_proxy``
 #
 
@@ -36,6 +35,10 @@
 XTRACE=$(set +o | grep xtrace)
 set +o xtrace
 
+# ensure we don't re-source this in the same environment
+[[ -z "$_DEVSTACK_FUNCTIONS_COMMON" ]] || return 0
+declare -r _DEVSTACK_FUNCTIONS_COMMON=1
+
 # Global Config Variables
 declare -A GITREPO
 declare -A GITBRANCH
@@ -852,13 +855,18 @@
 # Usage: _get_or_create_endpoint_with_interface <service> <interface> <url> <region>
 function _get_or_create_endpoint_with_interface {
     local endpoint_id
+    # TODO(dgonzalez): The check of the region name, as done in the grep
+    # statement below, exists only because keystone does currently
+    # not allow filtering the region name when listing endpoints. If keystone
+    # gets support for this, the check for the region name can be removed.
+    # Related bug in keystone: https://bugs.launchpad.net/keystone/+bug/1482772
     endpoint_id=$(openstack endpoint list \
         --os-url $KEYSTONE_SERVICE_URI_V3 \
         --os-identity-api-version=3 \
         --service $1 \
         --interface $2 \
         --region $4 \
-        -c ID -f value)
+        -c ID -c Region -f value | grep $4 | cut -f 1 -d " ")
     if [[ -z "$endpoint_id" ]]; then
         # Creates new endpoint
         endpoint_id=$(openstack endpoint create \
diff --git a/inc/ini-config b/inc/ini-config
index 8e7c018..d23f474 100644
--- a/inc/ini-config
+++ b/inc/ini-config
@@ -15,30 +15,40 @@
 # ================
 
 # Append a new option in an ini file without replacing the old value
-# iniadd config-file section option value1 value2 value3 ...
+# iniadd [-sudo] config-file section option value1 value2 value3 ...
 function iniadd {
     local xtrace=$(set +o | grep xtrace)
     set +o xtrace
+    local sudo=""
+    if [ $1 == "-sudo" ]; then
+        sudo="-sudo "
+        shift
+    fi
     local file=$1
     local section=$2
     local option=$3
     shift 3
 
     local values="$(iniget_multiline $file $section $option) $@"
-    iniset_multiline $file $section $option $values
+    iniset_multiline $sudo $file $section $option $values
     $xtrace
 }
 
 # Comment an option in an INI file
-# inicomment config-file section option
+# inicomment [-sudo] config-file section option
 function inicomment {
     local xtrace=$(set +o | grep xtrace)
     set +o xtrace
+    local sudo=""
+    if [ $1 == "-sudo" ]; then
+        sudo="sudo "
+        shift
+    fi
     local file=$1
     local section=$2
     local option=$3
 
-    sed -i -e "/^\[$section\]/,/^\[.*\]/ s|^\($option[ \t]*=.*$\)|#\1|" "$file"
+    $sudo sed -i -e "/^\[$section\]/,/^\[.*\]/ s|^\($option[ \t]*=.*$\)|#\1|" "$file"
     $xtrace
 }
 
@@ -95,10 +105,15 @@
 # in the argument list. Doing that will cause incorrect configuration
 # if spaces are used in the config values.
 #
-# iniadd_literal config-file section option value
+# iniadd_literal [-sudo] config-file section option value
 function iniadd_literal {
     local xtrace=$(set +o | grep xtrace)
     set +o xtrace
+    local sudo=""
+    if [ $1 == "-sudo" ]; then
+        sudo="sudo "
+        shift
+    fi
     local file=$1
     local section=$2
     local option=$3
@@ -110,7 +125,7 @@
     fi
 
     # Add it
-    sed -i -e "/^\[$section\]/ a\\
+    $sudo sed -i -e "/^\[$section\]/ a\\
 $option = $value
 " "$file"
 
@@ -118,10 +133,15 @@
 }
 
 # Remove an option from an INI file
-# inidelete config-file section option
+# inidelete [-sudo] config-file section option
 function inidelete {
     local xtrace=$(set +o | grep xtrace)
     set +o xtrace
+    local sudo=""
+    if [ $1 == "-sudo" ]; then
+        sudo="sudo "
+        shift
+    fi
     local file=$1
     local section=$2
     local option=$3
@@ -132,16 +152,21 @@
     fi
 
     # Remove old values
-    sed -i -e "/^\[$section\]/,/^\[.*\]/ { /^$option[ \t]*=/ d; }" "$file"
+    $sudo sed -i -e "/^\[$section\]/,/^\[.*\]/ { /^$option[ \t]*=/ d; }" "$file"
 
     $xtrace
 }
 
 # Set an option in an INI file
-# iniset config-file section option value
+# iniset [-sudo] config-file section option value
 function iniset {
     local xtrace=$(set +o | grep xtrace)
     set +o xtrace
+    local sudo=""
+    if [ $1 == "-sudo" ]; then
+        sudo="sudo "
+        shift
+    fi
     local file=$1
     local section=$2
     local option=$3
@@ -154,26 +179,31 @@
 
     if ! grep -q "^\[$section\]" "$file" 2>/dev/null; then
         # Add section at the end
-        echo -e "\n[$section]" >>"$file"
+        echo -e "\n[$section]" | $sudo tee --append "$file" > /dev/null
     fi
     if ! ini_has_option "$file" "$section" "$option"; then
         # Add it
-        sed -i -e "/^\[$section\]/ a\\
+        $sudo sed -i -e "/^\[$section\]/ a\\
 $option = $value
 " "$file"
     else
         local sep=$(echo -ne "\x01")
         # Replace it
-        sed -i -e '/^\['${section}'\]/,/^\[.*\]/ s'${sep}'^\('${option}'[ \t]*=[ \t]*\).*$'${sep}'\1'"${value}"${sep} "$file"
+        $sudo sed -i -e '/^\['${section}'\]/,/^\[.*\]/ s'${sep}'^\('${option}'[ \t]*=[ \t]*\).*$'${sep}'\1'"${value}"${sep} "$file"
     fi
     $xtrace
 }
 
 # Set a multiple line option in an INI file
-# iniset_multiline config-file section option value1 value2 valu3 ...
+# iniset_multiline [-sudo] config-file section option value1 value2 valu3 ...
 function iniset_multiline {
     local xtrace=$(set +o | grep xtrace)
     set +o xtrace
+    local sudo=""
+    if [ $1 == "-sudo" ]; then
+        sudo="sudo "
+        shift
+    fi
     local file=$1
     local section=$2
     local option=$3
@@ -188,14 +218,14 @@
     done
     if ! grep -q "^\[$section\]" "$file"; then
         # Add section at the end
-        echo -e "\n[$section]" >>"$file"
+        echo -e "\n[$section]" | $sudo tee --append "$file" > /dev/null
     else
         # Remove old values
-        sed -i -e "/^\[$section\]/,/^\[.*\]/ { /^$option[ \t]*=/ d; }" "$file"
+        $sudo sed -i -e "/^\[$section\]/,/^\[.*\]/ { /^$option[ \t]*=/ d; }" "$file"
     fi
     # Add new ones
     for v in $values; do
-        sed -i -e "/^\[$section\]/ a\\
+        $sudo sed -i -e "/^\[$section\]/ a\\
 $option = $v
 " "$file"
     done
@@ -207,10 +237,15 @@
 function iniuncomment {
     local xtrace=$(set +o | grep xtrace)
     set +o xtrace
+    local sudo=""
+    if [ $1 == "-sudo" ]; then
+        sudo="sudo "
+        shift
+    fi
     local file=$1
     local section=$2
     local option=$3
-    sed -i -e "/^\[$section\]/,/^\[.*\]/ s|[^ \t]*#[ \t]*\($option[ \t]*=.*$\)|\1|" "$file"
+    $sudo sed -i -e "/^\[$section\]/,/^\[.*\]/ s|[^ \t]*#[ \t]*\($option[ \t]*=.*$\)|\1|" "$file"
     $xtrace
 }
 
diff --git a/inc/python b/inc/python
index 54e19a7..5c9dc5c 100644
--- a/inc/python
+++ b/inc/python
@@ -67,7 +67,6 @@
 # Wrapper for ``pip install`` to set cache and proxy environment variables
 # Uses globals ``OFFLINE``, ``PIP_VIRTUAL_ENV``,
 # ``PIP_UPGRADE``, ``TRACK_DEPENDS``, ``*_proxy``,
-# ``USE_CONSTRAINTS``
 # pip_install package [package ...]
 function pip_install {
     local xtrace=$(set +o | grep xtrace)
@@ -105,11 +104,8 @@
     fi
 
     cmd_pip="$cmd_pip install"
-
-    # Handle a constraints file, if needed.
-    if [[ "$USE_CONSTRAINTS" == "True" ]]; then
-        cmd_pip="$cmd_pip -c $REQUIREMENTS_DIR/upper-constraints.txt"
-    fi
+    # Always apply constraints
+    cmd_pip="$cmd_pip -c $REQUIREMENTS_DIR/upper-constraints.txt"
 
     local pip_version=$(python -c "import pip; \
                         print(pip.__version__.strip('.')[0])")
@@ -187,13 +183,13 @@
 # use this, especially *oslo* ones
 function setup_install {
     local project_dir=$1
-    setup_package_with_req_sync $project_dir
+    setup_package_with_constraints_edit $project_dir
 }
 
 # this should be used for projects which run services, like all services
 function setup_develop {
     local project_dir=$1
-    setup_package_with_req_sync $project_dir -e
+    setup_package_with_constraints_edit $project_dir -e
 }
 
 # determine if a project as specified by directory is in
@@ -209,32 +205,16 @@
 # ``pip install -e`` the package, which processes the dependencies
 # using pip before running `setup.py develop`
 #
-# Updates the dependencies in project_dir from the
-# openstack/requirements global list before installing anything.
+# Updates the constraints from REQUIREMENTS_DIR to reflect the
+# future installed state of this package. This ensures when we
+# install this package we get the from source version.
 #
-# Uses globals ``TRACK_DEPENDS``, ``REQUIREMENTS_DIR``, ``UNDO_REQUIREMENTS``
+# Uses globals ``REQUIREMENTS_DIR``
 # setup_develop directory
-function setup_package_with_req_sync {
+function setup_package_with_constraints_edit {
     local project_dir=$1
     local flags=$2
 
-    # Don't update repo if local changes exist
-    # Don't use buggy "git diff --quiet"
-    # ``errexit`` requires us to trap the exit code when the repo is changed
-    local update_requirements=$(cd $project_dir && git diff --exit-code >/dev/null || echo "changed")
-
-    if [[ $update_requirements != "changed" && "$USE_CONSTRAINTS" == "False" ]]; then
-        if is_in_projects_txt $project_dir; then
-            (cd $REQUIREMENTS_DIR; \
-                ./.venv/bin/python update.py $project_dir)
-        else
-            # soft update projects not found in requirements project.txt
-            echo "$project_dir not a constrained repository, soft enforcing requirements"
-            (cd $REQUIREMENTS_DIR; \
-                ./.venv/bin/python update.py -s $project_dir)
-        fi
-    fi
-
     if [ -n "$REQUIREMENTS_DIR" ]; then
         # Constrain this package to this project directory from here on out.
         local name=$(awk '/^name.*=/ {print $3}' $project_dir/setup.cfg)
@@ -245,19 +225,6 @@
 
     setup_package $project_dir $flags
 
-    # We've just gone and possibly modified the user's source tree in an
-    # automated way, which is considered bad form if it's a development
-    # tree because we've screwed up their next git checkin. So undo it.
-    #
-    # However... there are some circumstances, like running in the gate
-    # where we really really want the overridden version to stick. So provide
-    # a variable that tells us whether or not we should UNDO the requirements
-    # changes (this will be set to False in the OpenStack ci gate)
-    if [ $UNDO_REQUIREMENTS = "True" ]; then
-        if [[ $update_requirements != "changed" ]]; then
-            (cd $project_dir && git reset --hard)
-        fi
-    fi
 }
 
 # ``pip install -e`` the package, which processes the dependencies
diff --git a/lib/apache b/lib/apache
index c7d69f2..a8e9bc5 100644
--- a/lib/apache
+++ b/lib/apache
@@ -11,7 +11,6 @@
 # lib/apache exports the following functions:
 #
 # - install_apache_wsgi
-# - config_apache_wsgi
 # - apache_site_config_for
 # - enable_apache_site
 # - disable_apache_site
diff --git a/lib/ceilometer b/lib/ceilometer
index ce93ebd..3df75b7 100644
--- a/lib/ceilometer
+++ b/lib/ceilometer
@@ -211,7 +211,6 @@
     cp $CEILOMETER_DIR/etc/ceilometer/event_pipeline.yaml $CEILOMETER_CONF_DIR
     cp $CEILOMETER_DIR/etc/ceilometer/api_paste.ini $CEILOMETER_CONF_DIR
     cp $CEILOMETER_DIR/etc/ceilometer/event_definitions.yaml $CEILOMETER_CONF_DIR
-    cp $CEILOMETER_DIR/etc/ceilometer/meters.yaml $CEILOMETER_CONF_DIR
     cp $CEILOMETER_DIR/etc/ceilometer/gnocchi_archive_policy_map.yaml $CEILOMETER_CONF_DIR
     cp $CEILOMETER_DIR/etc/ceilometer/gnocchi_resources.yaml $CEILOMETER_CONF_DIR
 
diff --git a/lib/databases/mysql b/lib/databases/mysql
index fb55b60..7ae9a93 100644
--- a/lib/databases/mysql
+++ b/lib/databases/mysql
@@ -85,12 +85,12 @@
         sudo mysqladmin -u root password $DATABASE_PASSWORD || true
     fi
 
-    # Update the DB to give user ‘$DATABASE_USER’@’%’ full control of the all databases:
+    # Update the DB to give user '$DATABASE_USER'@'%' full control of the all databases:
     sudo mysql -uroot -p$DATABASE_PASSWORD -h127.0.0.1 -e "GRANT ALL PRIVILEGES ON *.* TO '$DATABASE_USER'@'%' identified by '$DATABASE_PASSWORD';"
 
     # Now update ``my.cnf`` for some local needs and restart the mysql service
 
-    # Change ‘bind-address’ from localhost (127.0.0.1) to any (::) and
+    # Change bind-address from localhost (127.0.0.1) to any (::) and
     # set default db type to InnoDB
     sudo bash -c "source $TOP_DIR/functions && \
         iniset $my_conf mysqld bind-address "$SERVICE_LISTEN_ADDRESS" && \
diff --git a/lib/glance b/lib/glance
index f200dca..b1b0f32 100644
--- a/lib/glance
+++ b/lib/glance
@@ -154,7 +154,10 @@
 
         iniset $GLANCE_SWIFT_STORE_CONF ref1 user $SERVICE_TENANT_NAME:glance-swift
         iniset $GLANCE_SWIFT_STORE_CONF ref1 key $SERVICE_PASSWORD
-        iniset $GLANCE_SWIFT_STORE_CONF ref1 auth_address $KEYSTONE_SERVICE_URI/v2.0/
+        iniset $GLANCE_SWIFT_STORE_CONF ref1 auth_address $KEYSTONE_SERVICE_URI/v3
+        iniset $GLANCE_SWIFT_STORE_CONF ref1 user_domain_id default
+        iniset $GLANCE_SWIFT_STORE_CONF ref1 project_domain_id default
+        iniset $GLANCE_SWIFT_STORE_CONF ref1 auth_version 3
 
         # commenting is not strictly necessary but it's confusing to have bad values in conf
         inicomment $GLANCE_API_CONF glance_store swift_store_user
diff --git a/lib/horizon b/lib/horizon
index b0f306b..9fe0aa8 100644
--- a/lib/horizon
+++ b/lib/horizon
@@ -93,6 +93,9 @@
     local local_settings=$HORIZON_DIR/openstack_dashboard/local/local_settings.py
     cp $HORIZON_SETTINGS $local_settings
 
+    _horizon_config_set $local_settings "" WEBROOT \"$HORIZON_APACHE_ROOT/\"
+    _horizon_config_set $local_settings "" CUSTOM_THEME_PATH \"themes/webroot\"
+
     _horizon_config_set $local_settings "" COMPRESS_OFFLINE True
     _horizon_config_set $local_settings "" OPENSTACK_KEYSTONE_DEFAULT_ROLE \"Member\"
 
@@ -122,6 +125,7 @@
         s,%HORIZON_DIR%,$HORIZON_DIR,g;
         s,%APACHE_NAME%,$APACHE_NAME,g;
         s,%DEST%,$DEST,g;
+        s,%WEBROOT%,$HORIZON_APACHE_ROOT,g;
     \" $FILES/apache-horizon.template >$horizon_conf"
 
     if is_ubuntu; then
diff --git a/lib/infra b/lib/infra
index 3d68e45..89397de 100644
--- a/lib/infra
+++ b/lib/infra
@@ -22,7 +22,6 @@
 # Defaults
 # --------
 GITDIR["pbr"]=$DEST/pbr
-REQUIREMENTS_DIR=$DEST/requirements
 
 # Entry Points
 # ------------
@@ -30,8 +29,6 @@
 # install_infra() - Collect source and prepare
 function install_infra {
     local PIP_VIRTUAL_ENV="$REQUIREMENTS_DIR/.venv"
-    # bring down global requirements
-    git_clone $REQUIREMENTS_REPO $REQUIREMENTS_DIR $REQUIREMENTS_BRANCH
     [ ! -d $PIP_VIRTUAL_ENV ] && virtualenv $PIP_VIRTUAL_ENV
     # We don't care about testing git pbr in the requirements venv.
     PIP_VIRTUAL_ENV=$PIP_VIRTUAL_ENV pip_install -U pbr
diff --git a/lib/ironic b/lib/ironic
index 1323446..b3ad586 100644
--- a/lib/ironic
+++ b/lib/ironic
@@ -618,6 +618,7 @@
         local 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\
diff --git a/lib/neutron-legacy b/lib/neutron-legacy
index 4069439..d0eb0c0 100644
--- a/lib/neutron-legacy
+++ b/lib/neutron-legacy
@@ -471,11 +471,21 @@
 
 function create_nova_conf_neutron {
     iniset $NOVA_CONF DEFAULT network_api_class "nova.network.neutronv2.api.API"
-    iniset $NOVA_CONF neutron admin_username "$Q_ADMIN_USERNAME"
-    iniset $NOVA_CONF neutron admin_password "$SERVICE_PASSWORD"
-    iniset $NOVA_CONF neutron admin_auth_url "$KEYSTONE_SERVICE_PROTOCOL://$KEYSTONE_SERVICE_HOST:$KEYSTONE_AUTH_PORT/v2.0"
+
+
+    if [ "$ENABLE_IDENTITY_V2" == "False" ]; then
+        iniset $NOVA_CONF neutron auth_plugin "v3password"
+        iniset $NOVA_CONF neutron auth_url "$KEYSTONE_SERVICE_PROTOCOL://$KEYSTONE_SERVICE_HOST:$KEYSTONE_AUTH_PORT/v3"
+        iniset $NOVA_CONF neutron username "$Q_ADMIN_USERNAME"
+        iniset $NOVA_CONF neutron password "$SERVICE_PASSWORD"
+        iniset $NOVA_CONF neutron user_domain_name "default"
+    else
+        iniset $NOVA_CONF neutron admin_username "$Q_ADMIN_USERNAME"
+        iniset $NOVA_CONF neutron admin_password "$SERVICE_PASSWORD"
+        iniset $NOVA_CONF neutron admin_auth_url "$KEYSTONE_SERVICE_PROTOCOL://$KEYSTONE_SERVICE_HOST:$KEYSTONE_AUTH_PORT/v2.0"
+        iniset $NOVA_CONF neutron admin_tenant_name "$SERVICE_TENANT_NAME"
+    fi
     iniset $NOVA_CONF neutron auth_strategy "$Q_AUTH_STRATEGY"
-    iniset $NOVA_CONF neutron admin_tenant_name "$SERVICE_TENANT_NAME"
     iniset $NOVA_CONF neutron region_name "$REGION_NAME"
     iniset $NOVA_CONF neutron url "${Q_PROTOCOL}://$Q_HOST:$Q_PORT"
 
@@ -730,7 +740,9 @@
 function start_neutron_other_agents {
     run_process q-dhcp "python $AGENT_DHCP_BINARY --config-file $NEUTRON_CONF --config-file=$Q_DHCP_CONF_FILE"
 
-    if is_service_enabled q-vpn; then
+    if is_service_enabled neutron-vpnaas; then
+        :  # Started by plugin
+    elif is_service_enabled q-vpn; then
         run_process q-vpn "$AGENT_VPN_BINARY $(determine_config_files neutron-vpn-agent)"
     else
         run_process q-l3 "python $AGENT_L3_BINARY $(determine_config_files neutron-l3-agent)"
@@ -793,7 +805,8 @@
 }
 
 # _move_neutron_addresses_route() - Move the primary IP to the OVS bridge
-# on startup, or back to the public interface on cleanup
+# on startup, or back to the public interface on cleanup. If no IP is
+# configured on the interface, just add it as a port to the OVS bridge.
 function _move_neutron_addresses_route {
     local from_intf=$1
     local to_intf=$2
@@ -806,7 +819,8 @@
         # on configure we will also add $from_intf as a port on $to_intf,
         # assuming it is an OVS bridge.
 
-        local IP_BRD=$(ip -f $af a s dev $from_intf | awk '/inet/ { print $2, $3, $4; exit }')
+        local IP_ADD=""
+        local IP_DEL=""
         local DEFAULT_ROUTE_GW=$(ip r | awk "/default.+$from_intf/ { print \$3; exit }")
         local ADD_OVS_PORT=""
 
@@ -826,7 +840,12 @@
             ADD_OVS_PORT="sudo ovs-vsctl --may-exist add-port $to_intf $from_intf"
         fi
 
-        sudo ip addr del $IP_BRD dev $from_intf; sudo ip addr add $IP_BRD dev $to_intf; $ADD_OVS_PORT; $ADD_DEFAULT_ROUTE
+        if [[ "$IP_BRD" != "" ]]; then
+            IP_ADD="sudo ip addr del $IP_BRD dev $from_intf"
+            IP_DEL="sudo ip addr add $IP_BRD dev $to_intf"
+        fi
+
+        $IP_ADD; $IP_DEL; $ADD_OVS_PORT; $ADD_DEFAULT_ROUTE
     fi
 }
 
@@ -834,9 +853,7 @@
 # runs that a clean run would need to clean up
 function cleanup_neutron {
 
-    if [[ $(ip -f inet a s dev "$OVS_PHYSICAL_BRIDGE" | grep -c 'global') != 0 ]]; then
-        _move_neutron_addresses_route "$OVS_PHYSICAL_BRIDGE" "$PUBLIC_INTERFACE" False "inet"
-    fi
+    _move_neutron_addresses_route "$OVS_PHYSICAL_BRIDGE" "$PUBLIC_INTERFACE" False "inet"
 
     if [[ $(ip -f inet6 a s dev "$OVS_PHYSICAL_BRIDGE" | grep -c 'global') != 0 ]]; then
         _move_neutron_addresses_route "$OVS_PHYSICAL_BRIDGE" "$PUBLIC_INTERFACE" False "inet6"
@@ -878,6 +895,12 @@
 
     cp $NEUTRON_DIR/etc/neutron.conf $NEUTRON_CONF
 
+    Q_POLICY_FILE=$NEUTRON_CONF_DIR/policy.json
+    cp $NEUTRON_DIR/etc/policy.json $Q_POLICY_FILE
+
+    # allow neutron user to administer neutron to match neutron account
+    sed -i 's/"context_is_admin":  "role:admin"/"context_is_admin":  "role:admin or user_name:neutron"/g' $Q_POLICY_FILE
+
     # Set plugin-specific variables ``Q_DB_NAME``, ``Q_PLUGIN_CLASS``.
     # For main plugin config file, set ``Q_PLUGIN_CONF_PATH``, ``Q_PLUGIN_CONF_FILENAME``.
     # For addition plugin config files, set ``Q_PLUGIN_EXTRA_CONF_PATH``,
@@ -960,9 +983,9 @@
     iniset $NEUTRON_TEST_CONFIG_FILE DEFAULT verbose False
     iniset $NEUTRON_TEST_CONFIG_FILE DEFAULT debug False
     iniset $NEUTRON_TEST_CONFIG_FILE DEFAULT use_namespaces $Q_USE_NAMESPACE
-    iniset $NEUTRON_TEST_CONFIG_FILE agent root_helper "$Q_RR_COMMAND"
+    iniset $NEUTRON_TEST_CONFIG_FILE AGENT root_helper "$Q_RR_COMMAND"
     if [[ "$Q_USE_ROOTWRAP_DAEMON" == "True" ]]; then
-        iniset $NEUTRON_TEST_CONFIG_FILE agent root_helper_daemon "$Q_RR_DAEMON_COMMAND"
+        iniset $NEUTRON_TEST_CONFIG_FILE AGENT root_helper_daemon "$Q_RR_DAEMON_COMMAND"
     fi
 
     _neutron_setup_interface_driver $NEUTRON_TEST_CONFIG_FILE
@@ -977,9 +1000,9 @@
     iniset $Q_DHCP_CONF_FILE DEFAULT verbose True
     iniset $Q_DHCP_CONF_FILE DEFAULT debug $ENABLE_DEBUG_LOG_LEVEL
     iniset $Q_DHCP_CONF_FILE DEFAULT use_namespaces $Q_USE_NAMESPACE
-    iniset $Q_DHCP_CONF_FILE DEFAULT root_helper "$Q_RR_COMMAND"
+    iniset $Q_DHCP_CONF_FILE AGENT root_helper "$Q_RR_COMMAND"
     if [[ "$Q_USE_ROOTWRAP_DAEMON" == "True" ]]; then
-        iniset $NEUTRON_TEST_CONFIG_FILE agent root_helper_daemon "$Q_RR_DAEMON_COMMAND"
+        iniset $Q_DHCP_CONF_FILE AGENT root_helper_daemon "$Q_RR_DAEMON_COMMAND"
     fi
 
     if ! is_service_enabled q-l3; then
@@ -1012,18 +1035,16 @@
     iniset $Q_L3_CONF_FILE DEFAULT verbose True
     iniset $Q_L3_CONF_FILE DEFAULT debug $ENABLE_DEBUG_LOG_LEVEL
     iniset $Q_L3_CONF_FILE DEFAULT use_namespaces $Q_USE_NAMESPACE
-    iniset $Q_L3_CONF_FILE DEFAULT root_helper "$Q_RR_COMMAND"
+    iniset $Q_L3_CONF_FILE AGENT root_helper "$Q_RR_COMMAND"
     if [[ "$Q_USE_ROOTWRAP_DAEMON" == "True" ]]; then
-        iniset $Q_L3_CONF_FILE agent root_helper_daemon "$Q_RR_DAEMON_COMMAND"
+        iniset $Q_L3_CONF_FILE AGENT root_helper_daemon "$Q_RR_DAEMON_COMMAND"
     fi
 
     _neutron_setup_interface_driver $Q_L3_CONF_FILE
 
     neutron_plugin_configure_l3_agent
 
-    if [[ $(ip -f inet a s dev "$PUBLIC_INTERFACE" | grep -c 'global') != 0 ]]; then
-        _move_neutron_addresses_route "$PUBLIC_INTERFACE" "$OVS_PHYSICAL_BRIDGE" True "inet"
-    fi
+    _move_neutron_addresses_route "$PUBLIC_INTERFACE" "$OVS_PHYSICAL_BRIDGE" True "inet"
 
     if [[ $(ip -f inet6 a s dev "$PUBLIC_INTERFACE" | grep -c 'global') != 0 ]]; then
         _move_neutron_addresses_route "$PUBLIC_INTERFACE" "$OVS_PHYSICAL_BRIDGE" False "inet6"
@@ -1036,9 +1057,9 @@
     iniset $Q_META_CONF_FILE DEFAULT verbose True
     iniset $Q_META_CONF_FILE DEFAULT debug $ENABLE_DEBUG_LOG_LEVEL
     iniset $Q_META_CONF_FILE DEFAULT nova_metadata_ip $Q_META_DATA_IP
-    iniset $Q_META_CONF_FILE DEFAULT root_helper "$Q_RR_COMMAND"
+    iniset $Q_META_CONF_FILE AGENT root_helper "$Q_RR_COMMAND"
     if [[ "$Q_USE_ROOTWRAP_DAEMON" == "True" ]]; then
-        iniset $Q_META_CONF_FILE agent root_helper_daemon "$Q_RR_DAEMON_COMMAND"
+        iniset $Q_META_CONF_FILE AGENT root_helper_daemon "$Q_RR_DAEMON_COMMAND"
     fi
 
     # Configures keystone for metadata_agent
@@ -1106,13 +1127,7 @@
 # It is called when q-svc is enabled.
 function _configure_neutron_service {
     Q_API_PASTE_FILE=$NEUTRON_CONF_DIR/api-paste.ini
-    Q_POLICY_FILE=$NEUTRON_CONF_DIR/policy.json
-
     cp $NEUTRON_DIR/etc/api-paste.ini $Q_API_PASTE_FILE
-    cp $NEUTRON_DIR/etc/policy.json $Q_POLICY_FILE
-
-    # allow neutron user to administer neutron to match neutron account
-    sed -i 's/"context_is_admin":  "role:admin"/"context_is_admin":  "role:admin or user_name:neutron"/g' $Q_POLICY_FILE
 
     # Update either configuration file with plugin
     iniset $NEUTRON_CONF DEFAULT core_plugin $Q_PLUGIN_CLASS
diff --git a/lib/swift b/lib/swift
index 96d730e..fc736a6 100644
--- a/lib/swift
+++ b/lib/swift
@@ -97,7 +97,7 @@
 # the beginning of the pipeline, before authentication middlewares.
 SWIFT_EXTRAS_MIDDLEWARE_NO_AUTH=${SWIFT_EXTRAS_MIDDLEWARE_NO_AUTH:-crossdomain}
 
-# The ring uses a configurable number of bits from a path’s MD5 hash as
+# 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
 # from the hash is known as the partition power, and 2 to the partition
 # power indicates the partition count. Partitioning the full MD5 hash
@@ -610,7 +610,7 @@
 
     KEYSTONE_CATALOG_BACKEND=${KEYSTONE_CATALOG_BACKEND:-sql}
 
-    local another_role=$(openstack role list | awk "/ anotherrole / { print \$2 }")
+    local another_role=$(get_or_create_role "anotherrole")
 
     # NOTE(jroll): Swift doesn't need the admin role here, however Ironic uses
     # temp urls, which break when uploaded by a non-admin role
diff --git a/lib/tempest b/lib/tempest
index 3a9ba81..be24da6 100644
--- a/lib/tempest
+++ b/lib/tempest
@@ -82,6 +82,21 @@
 IPV6_ENABLED=$(trueorfalse True IPV6_ENABLED)
 IPV6_SUBNET_ATTRIBUTES_ENABLED=$(trueorfalse True IPV6_SUBNET_ATTRIBUTES_ENABLED)
 
+# Do we want to make a configuration where Tempest has admin on
+# the cloud. We don't always want to so that we can ensure Tempest
+# would work on a public cloud.
+TEMPEST_HAS_ADMIN=$(trueorfalse True TEMPEST_HAS_ADMIN)
+
+# Credential provider configuration option variables
+TEMPEST_ALLOW_TENANT_ISOLATION=${TEMPEST_ALLOW_TENANT_ISOLATION:-$TEMPEST_HAS_ADMIN}
+TEMPEST_USE_TEST_ACCOUNTS=$(trueorfalse False TEMPEST_USE_TEST_ACCOUNTS)
+
+# The number of workers tempest is expected to be run with. This is used for
+# generating a accounts.yaml for running with test-accounts. This is also the
+# same variable that devstack-gate uses to specify the number of workers that
+# it will run tempest with
+TEMPEST_CONCURRENCY=${TEMPEST_CONCURRENCY:-$(nproc)}
+
 
 # Functions
 # ---------
@@ -174,11 +189,6 @@
 
     password=${ADMIN_PASSWORD:-secrete}
 
-    # Do we want to make a configuration where Tempest has admin on
-    # the cloud. We don't always want to so that we can ensure Tempest
-    # would work on a public cloud.
-    TEMPEST_HAS_ADMIN=$(trueorfalse True TEMPEST_HAS_ADMIN)
-
     # See ``lib/keystone`` where these users and tenants are set up
     ADMIN_USERNAME=${ADMIN_USERNAME:-admin}
     ADMIN_TENANT_NAME=${ADMIN_TENANT_NAME:-admin}
@@ -313,7 +323,7 @@
     fi
     if [ "$ENABLE_IDENTITY_V2" == "False" ]; then
         # Only Identity v3 is available; then skip Identity API v2 tests
-        iniset $TEMPEST_CONFIG identity-feature-enabled v2_api False
+        iniset $TEMPEST_CONFIG identity-feature-enabled api_v2 False
         # In addition, use v3 auth tokens for running all Tempest tests
         iniset $TEMPEST_CONFIG identity auth_version v3
     else
@@ -335,11 +345,6 @@
     # Image Features
     iniset $TEMPEST_CONFIG image-feature-enabled deactivate_image True
 
-    # Auth
-    TEMPEST_ALLOW_TENANT_ISOLATION=${TEMPEST_ALLOW_TENANT_ISOLATION:-$TEMPEST_HAS_ADMIN}
-    iniset $TEMPEST_CONFIG auth allow_tenant_isolation ${TEMPEST_ALLOW_TENANT_ISOLATION:-True}
-    iniset $TEMPEST_CONFIG auth tempest_roles "Member"
-
     # Compute
     iniset $TEMPEST_CONFIG compute ssh_user ${DEFAULT_INSTANCE_USER:-cirros} # DEPRECATED
     iniset $TEMPEST_CONFIG compute network_for_ssh $PRIVATE_NETWORK_NAME
@@ -386,7 +391,7 @@
     # and is now the default behavior.
     iniset $TEMPEST_CONFIG compute-feature-enabled allow_duplicate_networks ${NOVA_ALLOW_DUPLICATE_NETWORKS:-True}
 
-    # Network
+    # Network
     iniset $TEMPEST_CONFIG network api_version 2.0
     iniset $TEMPEST_CONFIG network tenant_networks_reachable "$tenant_networks_reachable"
     iniset $TEMPEST_CONFIG network public_network_id "$public_network_id"
@@ -468,7 +473,7 @@
     if [[ ! -z "$DISABLE_VOLUME_API_EXTENSIONS" ]]; then
         # Enabled extensions are either the ones explicitly specified or those available on the API endpoint
         volume_api_extensions=${VOLUME_API_EXTENSIONS:-$(iniget $tmp_cfg_file volume-feature-enabled api_extensions | tr -d " ")}
-        # Remove disabled extensions
+        # Remove disabled extensions
         volume_api_extensions=$(remove_disabled_extensions $volume_api_extensions $DISABLE_VOLUME_API_EXTENSIONS)
     fi
     iniset $TEMPEST_CONFIG volume-feature-enabled api_extensions $volume_api_extensions
@@ -545,6 +550,19 @@
         sudo chown $STACK_USER $BOTO_CONF
     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 $ADMIN_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 $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 test_accounts_file "etc/accounts.yaml"
+    else
+        iniset $TEMPEST_CONFIG auth allow_tenant_isolation ${TEMPEST_ALLOW_TENANT_ISOLATION:-True}
+    fi
     # Restore IFS
     IFS=$ifs
 }
diff --git a/pkg/elasticsearch.sh b/pkg/elasticsearch.sh
index 79f67a0..14d13cf 100755
--- a/pkg/elasticsearch.sh
+++ b/pkg/elasticsearch.sh
@@ -6,9 +6,7 @@
 # step can probably be factored out to something nicer
 TOP_DIR=$(cd $(dirname "$0")/.. && pwd)
 FILES=$TOP_DIR/files
-source $TOP_DIR/functions
-DEST=${DEST:-/opt/stack}
-source $TOP_DIR/lib/infra
+source $TOP_DIR/stackrc
 
 # Package source and version, all pkg files are expected to have
 # something like this, as well as a way to override them.
diff --git a/stack.sh b/stack.sh
index cc8bc8c..accfd0a 100755
--- a/stack.sh
+++ b/stack.sh
@@ -21,6 +21,10 @@
 
 # Learn more and get the most recent version at http://devstack.org
 
+# Print the commands being run so that we can see the command that triggers
+# an error.  It is also useful for following along as the install occurs.
+set -o xtrace
+
 # Make sure custom grep options don't get in the way
 unset GREP_OPTIONS
 
@@ -494,10 +498,6 @@
 # Begin trapping error exit codes
 set -o errexit
 
-# Print the commands being run so that we can see the command that triggers
-# an error.  It is also useful for following along as the install occurs.
-set -o xtrace
-
 # Print the kernel version
 uname -a
 
@@ -683,14 +683,16 @@
 
 # OpenStack uses a fair number of other projects.
 
+# Bring down global requirements before any use of pip_install. This is
+# necessary to ensure that the constraints file is in place before we
+# attempt to apply any constraints to pip installs.
+git_clone $REQUIREMENTS_REPO $REQUIREMENTS_DIR $REQUIREMENTS_BRANCH
+
 # Install package requirements
 # Source it so the entire environment is available
 echo_summary "Installing package prerequisites"
 source $TOP_DIR/tools/install_prereqs.sh
 
-# Normalise USE_CONSTRAINTS
-USE_CONSTRAINTS=$(trueorfalse False USE_CONSTRAINTS)
-
 # Configure an appropriate Python environment
 if [[ "$OFFLINE" != "True" ]]; then
     PYPI_ALTERNATIVE_URL=${PYPI_ALTERNATIVE_URL:-""} $TOP_DIR/tools/install_pip.sh
@@ -1421,7 +1423,7 @@
 # If you installed Horizon on this server you should be able
 # to access the site using your browser.
 if is_service_enabled horizon; then
-    echo "Horizon is now available at http://$SERVICE_HOST/"
+    echo "Horizon is now available at http://$SERVICE_HOST$HORIZON_APACHE_ROOT"
 fi
 
 # If Keystone is present you can point ``nova`` cli to this server
diff --git a/stackrc b/stackrc
index 8beef96..156cb1f 100644
--- a/stackrc
+++ b/stackrc
@@ -87,6 +87,9 @@
 # Set the default Nova APIs to enable
 NOVA_ENABLED_APIS=ec2,osapi_compute,metadata
 
+# Set the root URL for Horizon
+HORIZON_APACHE_ROOT="/dashboard"
+
 # Whether to use 'dev mode' for screen windows. Dev mode works by
 # stuffing text into the screen windows so that a developer can use
 # ctrl-c, up-arrow, enter to restart the service. Starting services
@@ -149,13 +152,6 @@
 # Zero disables timeouts
 GIT_TIMEOUT=${GIT_TIMEOUT:-0}
 
-# Constraints mode
-# - False (default) : update git projects dependencies from global-requirements.
-#
-# - True : use upper-constraints.txt to constrain versions of packages intalled
-#          and do not edit projects at all.
-USE_CONSTRAINTS=$(trueorfalse False USE_CONSTRAINTS)
-
 # Repositories
 # ------------
 
@@ -163,6 +159,9 @@
 # Another option is https://git.openstack.org
 GIT_BASE=${GIT_BASE:-git://git.openstack.org}
 
+# The location of REQUIREMENTS once cloned
+REQUIREMENTS_DIR=$DEST/requirements
+
 # Which libraries should we install from git instead of using released
 # versions on pypi?
 #
@@ -627,9 +626,6 @@
 # Set default screen name
 SCREEN_NAME=${SCREEN_NAME:-stack}
 
-# Undo requirements changes by global requirements
-UNDO_REQUIREMENTS=${UNDO_REQUIREMENTS:-True}
-
 # Allow the use of an alternate protocol (such as https) for service endpoints
 SERVICE_PROTOCOL=${SERVICE_PROTOCOL:-http}
 
diff --git a/tests/test_ini_config.sh b/tests/test_ini_config.sh
index 3aef6f3..61f2c41 100755
--- a/tests/test_ini_config.sh
+++ b/tests/test_ini_config.sh
@@ -71,15 +71,23 @@
 
 EOF
 
-# Test with missing arguments
+# set TEST_SUDO to test writing to root-owned files
+SUDO_ARG=""
+SUDO=""
+if [ -n "$TEST_SUDO" ]; then
+    SUDO="sudo "
+    SUDO_ARG="-sudo "
+    sudo chown -R root:root ${INI_TMP_ETC_DIR}
+fi
 
+# Test with missing arguments
 BEFORE=$(cat ${TEST_INI})
 
-iniset ${TEST_INI} aaa
+iniset ${SUDO_ARG} ${TEST_INI} aaa
 NO_ATTRIBUTE=$(cat ${TEST_INI})
 assert_equal "$BEFORE" "$NO_ATTRIBUTE" "test missing attribute argument"
 
-iniset ${TEST_INI}
+iniset ${SUDO_ARG} ${TEST_INI}
 NO_SECTION=$(cat ${TEST_INI})
 assert_equal "$BEFORE" "$NO_SECTION" "missing section argument"
 
@@ -87,7 +95,7 @@
 VAL=$(iniget ${TEST_INI} aaa handlers)
 assert_equal "$VAL" "aa, bb" "iniget spaces in option"
 
-iniset ${TEST_INI} aaa handlers "11, 22"
+iniset ${SUDO_ARG} ${TEST_INI} aaa handlers "11, 22"
 VAL=$(iniget ${TEST_INI} aaa handlers)
 assert_equal "$VAL" "11, 22" "iniset spaces in option"
 
@@ -95,7 +103,7 @@
 VAL=$(iniget ${TEST_INI} " ccc " spaces)
 assert_equal "$VAL" "yes" "iniget with section header space"
 
-iniset ${TEST_INI} "b b" opt_ion 42
+iniset ${SUDO_ARG} ${TEST_INI} "b b" opt_ion 42
 VAL=$(iniget ${TEST_INI} "b b" opt_ion)
 assert_equal "$VAL" "42" "iniset with section header space"
 
@@ -103,7 +111,7 @@
 VAL=$(iniget ${TEST_INI} bbb handlers)
 assert_equal "$VAL" "ee,ff" "iniget at EOF"
 
-iniset ${TEST_INI} bbb handlers "33,44"
+iniset ${SUDO_ARG} ${TEST_INI} bbb handlers "33,44"
 VAL=$(iniget ${TEST_INI} bbb handlers)
 assert_equal "$VAL" "33,44" "inset at EOF"
 
@@ -122,12 +130,12 @@
 fi
 
 # test changing empty option
-iniset ${TEST_INI} ddd empty "42"
+iniset ${SUDO_ARG} ${TEST_INI} ddd empty "42"
 VAL=$(iniget ${TEST_INI} ddd empty)
 assert_equal "$VAL" "42" "change empty option"
 
 # test pipe in option
-iniset ${TEST_INI} aaa handlers "a|b"
+iniset ${SUDO_ARG} ${TEST_INI} aaa handlers "a|b"
 VAL=$(iniget ${TEST_INI} aaa handlers)
 assert_equal "$VAL" "a|b" "pipe in option"
 
@@ -146,23 +154,23 @@
 fi
 
 # Test comments
-inicomment ${TEST_INI} aaa handlers
+inicomment ${SUDO_ARG} ${TEST_INI} aaa handlers
 VAL=$(iniget ${TEST_INI} aaa handlers)
 assert_empty VAL "test inicomment"
 
 # Test multiple line iniset/iniget
-iniset_multiline ${TEST_INI} eee multi bar1 bar2
+iniset_multiline ${SUDO_ARG} ${TEST_INI} eee multi bar1 bar2
 
 VAL=$(iniget_multiline ${TEST_INI} eee multi)
 assert_equal "$VAL" "bar1 bar2" "iniget_multiline"
 
 # Test iniadd with exiting values
-iniadd ${TEST_INI} eee multi bar3
+iniadd ${SUDO_ARG} ${TEST_INI} eee multi bar3
 VAL=$(iniget_multiline ${TEST_INI} eee multi)
 assert_equal "$VAL" "bar1 bar2 bar3" "iniadd with existing values"
 
 # Test iniadd with non-exiting values
-iniadd ${TEST_INI} eee non-multi foobar1 foobar2
+iniadd ${SUDO_ARG} ${TEST_INI} eee non-multi foobar1 foobar2
 VAL=$(iniget_multiline ${TEST_INI} eee non-multi)
 assert_equal "$VAL" "foobar1 foobar2" "iniadd non-existing values"
 
@@ -176,7 +184,7 @@
     del_no_section"
 
 for x in $del_cases; do
-    inidelete ${TEST_INI} $x a
+    inidelete ${SUDO_ARG} ${TEST_INI} $x a
     VAL=$(iniget_multiline ${TEST_INI} $x a)
     assert_empty VAL "inidelete $x"
     if [ "$x" = "del_separate_options" -o \
@@ -191,6 +199,6 @@
     fi
 done
 
-rm -rf ${INI_TMP_DIR}
+$SUDO rm -rf ${INI_TMP_DIR}
 
 report_results
diff --git a/tools/install_pip.sh b/tools/install_pip.sh
index 0f7c962..7b42c8c 100755
--- a/tools/install_pip.sh
+++ b/tools/install_pip.sh
@@ -20,7 +20,7 @@
 cd $TOP_DIR
 
 # Import common functions
-source $TOP_DIR/functions
+source $TOP_DIR/stackrc
 
 FILES=$TOP_DIR/files