Merge "Set deploywait_timeout via localrc option"
diff --git a/Makefile b/Makefile
index a94d60a..970d800 100644
--- a/Makefile
+++ b/Makefile
@@ -15,7 +15,7 @@
 DEST=/opt/stack
 
 all:
-	echo "This just saved you from a terrible mistake!"
+	@echo "This just saved you from a terrible mistake!"
 
 # Do Some Work
 stack:
diff --git a/clean.sh b/clean.sh
index b18f28e..0641bff 100755
--- a/clean.sh
+++ b/clean.sh
@@ -49,6 +49,7 @@
 source $TOP_DIR/lib/cinder
 source $TOP_DIR/lib/swift
 source $TOP_DIR/lib/heat
+source $TOP_DIR/lib/neutron
 source $TOP_DIR/lib/neutron-legacy
 
 set -o xtrace
@@ -137,9 +138,10 @@
 FILES_TO_CLEAN=".localrc.auto .localrc.password "
 FILES_TO_CLEAN+="docs/files docs/html shocco/ "
 FILES_TO_CLEAN+="stack-screenrc test*.conf* test.ini* "
-FILES_TO_CLEAN+=".stackenv .prereqs "
-FILES_TO_CLEAN+="~/.config/openstack"
+FILES_TO_CLEAN+=".stackenv .prereqs"
 
 for file in $FILES_TO_CLEAN; do
     rm -rf $TOP_DIR/$file
 done
+
+rm -rf ~/.config/openstack
diff --git a/data/devstack-plugins-registry.header b/data/devstack-plugins-registry.header
index f105fe9..6119ab5 100644
--- a/data/devstack-plugins-registry.header
+++ b/data/devstack-plugins-registry.header
@@ -1,20 +1,23 @@
 ..
-  Note to patch submitters: this file is covered by a periodic proposal
-  job.  You should edit the files data/devstack-plugins-registry.footer
-  data/devstack-plugins-registry.header instead of this one.
+
+  Note to patch submitters:
+
+  # ============================= #
+  # THIS FILE IS AUTOGENERATED !  #
+  # ============================= #
+
+  ** Plugins are found automatically and added to this list **
+
+  This file is created by a periodic proposal job.  You should not
+  edit this file.
+
+  You should edit the files data/devstack-plugins-registry.footer
+  data/devstack-plugins-registry.header to modify this text.
 
 ==========================
  DevStack Plugin Registry
 ==========================
 
-Since we've created the external plugin mechanism, it's gotten used by
-a lot of projects. The following is a list of plugins that currently
-exist. Any project that wishes to list their plugin here is welcomed
-to.
-
-Detected Plugins
-================
-
-The following are plugins that a script has found in the openstack/
-namespace, which includes but is not limited to official OpenStack
-projects.
+The following list is an automatically-generated collection of
+available DevStack plugins.  This includes, but is not limited to,
+official OpenStack projects.
diff --git a/doc/source/changes.rst b/doc/source/changes.rst
deleted file mode 100644
index 19fce0f..0000000
--- a/doc/source/changes.rst
+++ /dev/null
@@ -1,12 +0,0 @@
-=======
-Changes
-=======
-
-Recent Changes What's been happening?
-=====================================
-
-These are the commits to DevStack for the last six months. For the
-complete list see `the DevStack project in
-Gerrit <https://review.openstack.org/#/q/status:merged+project:openstack-dev/devstack,n,z>`__.
-
-%GIT_LOG%
diff --git a/doc/source/configuration.rst b/doc/source/configuration.rst
index 0493f8f..1161b34 100644
--- a/doc/source/configuration.rst
+++ b/doc/source/configuration.rst
@@ -36,10 +36,6 @@
 
 -  **local** - extracts ``localrc`` from ``local.conf`` before
    ``stackrc`` is sourced
--  **pre-install** - runs after the system packages are installed but
-   before any of the source repositories are installed
--  **install** - runs immediately after the repo installations are
-   complete
 -  **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
@@ -62,8 +58,7 @@
 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. More
-details on the :doc:`contents of local.conf <local.conf>` are available.
+exists it will be used instead to preserve backward-compatibility.
 
 ::
 
@@ -84,6 +79,76 @@
 fragment and MUST conform to the shell requirements, specifically no
 whitespace around ``=`` (equals).
 
+openrc
+======
+
+``openrc`` configures login credentials suitable for use with the
+OpenStack command-line tools. ``openrc`` sources ``stackrc`` at the
+beginning (which in turn sources the ``localrc`` section of
+``local.conf``) in order to pick up ``HOST_IP`` and/or ``SERVICE_HOST``
+to use in the endpoints. The values shown below are the default values.
+
+OS\_PROJECT\_NAME (OS\_TENANT\_NAME)
+    Keystone has
+    standardized the term *project* as the entity that owns resources. In
+    some places references still exist to the previous term
+    *tenant* for this use. Also, *project\_name* is preferred to
+    *project\_id*.  OS\_TENANT\_NAME remains supported for compatibility
+    with older tools.
+
+    ::
+
+        OS_PROJECT_NAME=demo
+
+OS\_USERNAME
+    In addition to the owning entity (project), OpenStack calls the entity
+    performing the action *user*.
+
+    ::
+
+        OS_USERNAME=demo
+
+OS\_PASSWORD
+    Keystone's default authentication requires a password be provided.
+    The usual cautions about putting passwords in environment variables
+    apply, for most DevStack uses this may be an acceptable tradeoff.
+
+    ::
+
+        OS_PASSWORD=secret
+
+HOST\_IP, SERVICE\_HOST
+    Set API endpoint host using ``HOST_IP``. ``SERVICE_HOST`` may also
+    be used to specify the endpoint, which is convenient for some
+    ``local.conf`` configurations. Typically, ``HOST_IP`` is set in the
+    ``localrc`` section.
+
+    ::
+
+        HOST_IP=127.0.0.1
+        SERVICE_HOST=$HOST_IP
+
+OS\_AUTH\_URL
+    Authenticating against an OpenStack cloud using Keystone returns a
+    *Token* and *Service Catalog*. The catalog contains the endpoints
+    for all services the user/tenant has access to - including Nova,
+    Glance, Keystone and Swift.
+
+    ::
+
+        OS_AUTH_URL=http://$SERVICE_HOST:5000/v2.0
+
+KEYSTONECLIENT\_DEBUG, NOVACLIENT\_DEBUG
+    Set command-line client log level to ``DEBUG``. These are commented
+    out by default.
+
+    ::
+
+        # export KEYSTONECLIENT_DEBUG=1
+        # export NOVACLIENT_DEBUG=1
+
+
+
 .. _minimal-configuration:
 
 Minimal Configuration
@@ -145,6 +210,37 @@
 .. contents::
    :local:
 
+Service Repos
+-------------
+
+The Git repositories used to check out the source for each service are
+controlled by a pair of variables set for each service.  ``*_REPO``
+points to the repository and ``*_BRANCH`` selects which branch to
+check out. These may be overridden in ``local.conf`` to pull source
+from a different repo for testing, such as a Gerrit branch
+proposal. ``GIT_BASE`` points to the primary repository server.
+
+    ::
+
+        NOVA_REPO=$GIT_BASE/openstack/nova.git
+        NOVA_BRANCH=master
+
+To pull a branch directly from Gerrit, get the repo and branch from
+the Gerrit review page:
+
+    ::
+
+        git fetch https://review.openstack.org/p/openstack/nova refs/changes/50/5050/1 && git checkout FETCH_HEAD
+
+    The repo is the stanza following ``fetch`` and the branch is the
+    stanza following that:
+
+    ::
+
+        NOVA_REPO=https://review.openstack.org/p/openstack/nova
+        NOVA_BRANCH=refs/changes/50/5050/1
+
+
 Installation Directory
 ----------------------
 
@@ -327,6 +423,9 @@
 
       LIBS_FROM_GIT=python-keystoneclient,oslo.config
 
+Setting the variable to ``ALL`` will activate the download for all
+libraries.
+
 Virtual Environments
 --------------------
 
@@ -423,8 +522,8 @@
 ----------
 
 ``IP_VERSION`` can be used to configure DevStack to create either an
-IPv4, IPv6, or dual-stack tenant data-network by with either
-``IP_VERSION=4``, ``IP_VERSION=6``, or ``IP_VERSION=4+6``
+IPv4, IPv6, or dual-stack self service project data-network by with
+either ``IP_VERSION=4``, ``IP_VERSION=6``, or ``IP_VERSION=4+6``
 respectively.  This functionality requires that the Neutron networking
 service is enabled by setting the following options:
 
@@ -513,6 +612,18 @@
 with multiple replicas you can do so by customizing the variable
 ``SWIFT_REPLICAS`` in your ``localrc`` section (usually to 3).
 
+You can manually override the ring building to use specific storage
+nodes, for example when you want to test a multinode environment. In
+this case you have to set a space-separated list of IPs in
+``SWIFT_STORAGE_IPS`` in your ``localrc`` section that should be used
+as Swift storage nodes.
+Please note that this does not create a multinode setup, it is only
+used when adding nodes to the Swift rings.
+
+::
+
+    SWIFT_STORAGE_IPS="192.168.1.10 192.168.1.11 192.168.1.12"
+
 Swift S3
 ++++++++
 
@@ -630,6 +741,16 @@
     KEYSTONE_SERVICE_HOST=<KEYSTONE_IP_ADDRESS_FROM_REGION_ONE>
     KEYSTONE_AUTH_HOST=<KEYSTONE_IP_ADDRESS_FROM_REGION_ONE>
     REGION_NAME=RegionTwo
+    KEYSTONE_REGION_NAME=RegionOne
+
+In the devstack for RegionOne, we set REGION_NAME as RegionOne, so region of
+the services started in this devstack are registered as RegionOne. In devstack
+for RegionTwo, similarly, we set REGION_NAME as RegionTwo since we want
+services started in this devstack to be registered in RegionTwo. But Keystone
+service is started and registered in RegionOne, not RegionTwo, so we use
+KEYSTONE_REGION_NAME to specify the region of Keystone service.
+KEYSTONE_REGION_NAME has a default value the same as REGION_NAME thus we omit
+it in the configuration of RegionOne.
 
 Disabling Identity API v2
 +++++++++++++++++++++++++
@@ -640,3 +761,40 @@
 ::
 
     ENABLE_IDENTITY_V2=False
+
+Exercises
+~~~~~~~~~
+
+``exerciserc`` is used to configure settings for the exercise scripts.
+The values shown below are the default values. These can all be
+overridden by setting them in the ``localrc`` section.
+
+* Max time to wait while vm goes from build to active state
+
+    ::
+
+        ACTIVE_TIMEOUT==30
+
+* Max time to wait for proper IP association and dis-association.
+
+    ::
+
+        ASSOCIATE_TIMEOUT=15
+
+* Max time till the vm is bootable
+
+    ::
+
+        BOOT_TIMEOUT=30
+
+* Max time from run instance command until it is running
+
+    ::
+
+        RUNNING_TIMEOUT=$(($BOOT_TIMEOUT + $ACTIVE_TIMEOUT))
+
+* Max time to wait for a vm to terminate
+
+    ::
+
+        TERMINATE_TIMEOUT=30
diff --git a/doc/source/exerciserc.rst b/doc/source/exerciserc.rst
deleted file mode 100644
index dacae2e..0000000
--- a/doc/source/exerciserc.rst
+++ /dev/null
@@ -1,42 +0,0 @@
-==============================
-exerciserc - Exercise Settings
-==============================
-
-``exerciserc`` is used to configure settings for the exercise scripts.
-The values shown below are the default values. These can all be
-overridden by setting them in the ``localrc`` section.
-
-ACTIVE\_TIMEOUT
-    Max time to wait while vm goes from build to active state
-
-    ::
-
-        ACTIVE_TIMEOUT==30
-
-ASSOCIATE\_TIMEOUT
-    Max time to wait for proper IP association and dis-association.
-
-    ::
-
-        ASSOCIATE_TIMEOUT=15
-
-BOOT\_TIMEOUT
-    Max time till the vm is bootable
-
-    ::
-
-        BOOT_TIMEOUT=30
-
-RUNNING\_TIMEOUT
-    Max time from run instance command until it is running
-
-    ::
-
-        RUNNING_TIMEOUT=$(($BOOT_TIMEOUT + $ACTIVE_TIMEOUT))
-
-TERMINATE\_TIMEOUT
-    Max time to wait for a vm to terminate
-
-    ::
-
-        TERMINATE_TIMEOUT=30
diff --git a/doc/source/guides.rst b/doc/source/guides.rst
new file mode 100644
index 0000000..c2c7b91
--- /dev/null
+++ b/doc/source/guides.rst
@@ -0,0 +1,68 @@
+Guides
+======
+
+.. warning::
+
+   The guides are point in time contributions, and may not always be
+   up to date with the latest work in devstack.
+
+Walk through various setups used by stackers
+
+.. toctree::
+   :glob:
+   :maxdepth: 1
+
+   guides/single-vm
+   guides/single-machine
+   guides/lxc
+   guides/multinode-lab
+   guides/neutron
+   guides/devstack-with-nested-kvm
+   guides/nova
+   guides/devstack-with-lbaas-v2
+
+All-In-One Single VM
+--------------------
+
+Run :doc:`OpenStack in a VM <guides/single-vm>`. The VMs launched in your cloud will be slow as
+they are running in QEMU (emulation), but it is useful if you don't have
+spare hardware laying around. :doc:`[Read] <guides/single-vm>`
+
+All-In-One Single Machine
+-------------------------
+
+Run :doc:`OpenStack on dedicated hardware <guides/single-machine>`  This can include a
+server-class machine or a laptop at home.
+:doc:`[Read] <guides/single-machine>`
+
+All-In-One LXC Container
+-------------------------
+
+Run :doc:`OpenStack in a LXC container <guides/lxc>`. Beneficial for intermediate
+and advanced users. The VMs launched in this cloud will be fully accelerated but
+not all OpenStack features are supported. :doc:`[Read] <guides/lxc>`
+
+Multi-Node Lab
+--------------
+
+Setup a :doc:`multi-node cluster <guides/multinode-lab>` with dedicated VLANs for VMs & Management.
+:doc:`[Read] <guides/multinode-lab>`
+
+DevStack with Neutron Networking
+--------------------------------
+
+Building a DevStack cluster with :doc:`Neutron Networking <guides/neutron>`.
+This guide is meant for building lab environments with a dedicated
+control node and multiple compute nodes.
+
+DevStack with KVM-based Nested Virtualization
+---------------------------------------------
+
+Procedure to setup :doc:`DevStack with KVM-based Nested Virtualization
+<guides/devstack-with-nested-kvm>`. With this setup, Nova instances
+will be more performant than with plain QEMU emulation.
+
+Nova and devstack
+--------------------------------
+
+Guide to working with nova features :doc:`Nova and devstack <guides/nova>`.
diff --git a/doc/source/guides/lxc.rst b/doc/source/guides/lxc.rst
index a719d60..9549ed2 100644
--- a/doc/source/guides/lxc.rst
+++ b/doc/source/guides/lxc.rst
@@ -88,7 +88,7 @@
 
 You can also ssh into your container. On your host, run
 ``sudo lxc-info -n devstack`` to get the IP address (e.g. 
-``ssh ubuntu@$(sudo lxc-info -n p2 | awk '/IP/ { print $2 }')``).
+``ssh ubuntu@$(sudo lxc-info -n devstack | awk '/IP/ { print $2 }')``).
 
 Run Devstack
 -------------
diff --git a/doc/source/guides/neutron.rst b/doc/source/guides/neutron.rst
index 6ac3993..c5b1634 100644
--- a/doc/source/guides/neutron.rst
+++ b/doc/source/guides/neutron.rst
@@ -15,8 +15,8 @@
 network interface that is available. In this scenario, the physical
 interface is added to the Open vSwitch bridge, and the IP address of
 the laptop is migrated onto the bridge interface. That way, the
-physical interface can be used to transmit tenant network traffic,
-the OpenStack API traffic, and management traffic.
+physical interface can be used to transmit self service project
+network traffic, the OpenStack API traffic, and management traffic.
 
 
 .. warning::
@@ -88,7 +88,6 @@
         FIXED_RANGE="10.0.0.0/24"
         Q_FLOATING_ALLOCATION_POOL=start=172.18.161.250,end=172.18.161.254
         PUBLIC_NETWORK_GATEWAY="172.18.161.1"
-        Q_L3_ENABLED=True
         PUBLIC_INTERFACE=eth0
 
         # Open vSwitch provider networking configuration
@@ -222,12 +221,12 @@
 which is used as the "integration bridge" where ports are created, and
 plugged into the virtual switching fabric. `br-ex` is an OVS bridge
 that is used to connect physical ports (like `eth0`), so that floating
-IP traffic for tenants can be received from the physical network
-infrastructure (and the internet), and routed to tenant network ports.
-`br-tun` is a tunnel bridge that is used to connect OpenStack nodes
-(like `devstack-2`) together. This bridge is used so that tenant
-network traffic, using the VXLAN tunneling protocol, flows between
-each compute node where tenant instances run.
+IP traffic for project networks can be received from the physical
+network infrastructure (and the internet), and routed to self service
+project network ports.  `br-tun` is a tunnel bridge that is used to
+connect OpenStack nodes (like `devstack-2`) together. This bridge is
+used so that project network traffic, using the VXLAN tunneling
+protocol, flows between each compute node where project instances run.
 
 
 
@@ -362,6 +361,8 @@
 DevStack Configuration
 ----------------------
 
+.. _ovs-provider-network-controller:
+
 The following is a snippet of the DevStack configuration on the
 controller node.
 
@@ -381,13 +382,12 @@
 
         ## Neutron options
         Q_USE_SECGROUP=True
-        ENABLE_TENANT_VLANS=True
-        TENANT_VLAN_RANGE=3001:4000
+        ENABLE_PROJECT_VLANS=True
+        PROJECT_VLAN_RANGE=3001:4000
         PHYSICAL_NETWORK=default
         OVS_PHYSICAL_BRIDGE=br-ex
 
         Q_USE_PROVIDER_NETWORKING=True
-        Q_L3_ENABLED=False
 
         # Do not use Nova-Network
         disable_service n-net
@@ -434,13 +434,12 @@
         OVS_PHYSICAL_BRIDGE=br-ex
         PUBLIC_INTERFACE=eth1
         Q_USE_PROVIDER_NETWORKING=True
-        Q_L3_ENABLED=False
 
 Compute node 2's configuration will be exactly the same, except
 ``HOST_IP`` will be ``10.0.0.4``
 
 When DevStack is configured to use provider networking (via
-``Q_USE_PROVIDER_NETWORKING`` is True and ``Q_L3_ENABLED`` is False) -
+``Q_USE_PROVIDER_NETWORKING`` is True) -
 DevStack will automatically add the network interface defined in
 ``PUBLIC_INTERFACE`` to the ``OVS_PHYSICAL_BRIDGE``
 
@@ -543,7 +542,6 @@
     FIXED_RANGE="10.0.0.0/24"
     Q_FLOATING_ALLOCATION_POOL=start=172.18.161.250,end=172.18.161.254
     PUBLIC_NETWORK_GATEWAY="172.18.161.1"
-    Q_L3_ENABLED=True
     PUBLIC_INTERFACE=eth0
 
     Q_USE_PROVIDERNET_FOR_PUBLIC=True
@@ -554,3 +552,100 @@
     PUBLIC_PHYSICAL_NETWORK=default
     LB_INTERFACE_MAPPINGS=default:eth0
 
+Using MacVTap instead of Open vSwitch
+------------------------------------------
+
+Security groups are not supported by the MacVTap agent. Due to that, devstack
+configures the NoopFirewall driver on the compute node.
+
+MacVTap agent does not support l3, dhcp and metadata agent. Due to that you can
+chose between the following deployment scenarios:
+
+Single node with provider networks using config drive and external l3, dhcp
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+This scenario applies, if l3 and dhcp services are provided externally, or if
+you do not require them.
+
+
+::
+
+    [[local|localrc]]
+    HOST_IP=10.0.0.2
+    SERVICE_HOST=10.0.0.2
+    MYSQL_HOST=10.0.0.2
+    RABBIT_HOST=10.0.0.2
+    ADMIN_PASSWORD=secret
+    MYSQL_PASSWORD=secret
+    RABBIT_PASSWORD=secret
+    SERVICE_PASSWORD=secret
+
+    Q_ML2_PLUGIN_MECHANISM_DRIVERS=macvtap
+    Q_USE_PROVIDER_NETWORKING=True
+
+    #Enable Neutron services
+    disable_service n-net
+    enable_plugin neutron git://git.openstack.org/openstack/neutron
+    ENABLED_SERVICES+=,q-agt,q-svc
+
+    ## MacVTap agent options
+    Q_AGENT=macvtap
+    PHYSICAL_NETWORK=default
+
+    FIXED_RANGE="203.0.113.0/24"
+    NETWORK_GATEWAY=203.0.113.1
+    PROVIDER_SUBNET_NAME="provider_net"
+    PROVIDER_NETWORK_TYPE="vlan"
+    SEGMENTATION_ID=2010
+
+    [[post-config|/$Q_PLUGIN_CONF_FILE]]
+    [macvtap]
+    physical_interface_mappings = $PHYSICAL_NETWORK:eth1
+
+    [[post-config|$NOVA_CONF]]
+    force_config_drive = True
+
+
+Multi node with MacVTap compute node
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+This scenario applies, if you require OpenStack provided l3, dhcp or metadata
+services. Those are hosted on a separate controller and network node, running
+some other l2 agent technology (in this example Open vSwitch). This node needs
+to be configured for VLAN tenant networks.
+
+For OVS, a similar configuration like described in the
+:ref:`OVS Provider Network <ovs-provider-network-controller>` section can be
+used. Just add the the following line to this local.conf, which also loads
+the MacVTap mechanism driver:
+
+::
+
+    [[local|localrc]]
+    ...
+    Q_ML2_PLUGIN_MECHANISM_DRIVERS=openvswitch,linuxbridge,macvtap
+    ...
+
+For the MacVTap compute node, use this local.conf:
+
+::
+
+    HOST_IP=10.0.0.3
+    SERVICE_HOST=10.0.0.2
+    MYSQL_HOST=10.0.0.2
+    RABBIT_HOST=10.0.0.2
+    ADMIN_PASSWORD=secret
+    MYSQL_PASSWORD=secret
+    RABBIT_PASSWORD=secret
+    SERVICE_PASSWORD=secret
+
+    # Services that a compute node runs
+    disable_all_services
+    enable_plugin neutron git://git.openstack.org/openstack/neutron
+    ENABLED_SERVICES+=n-cpu,q-agt
+
+    ## MacVTap agent options
+    Q_AGENT=macvtap
+    PHYSICAL_NETWORK=default
+
+    [[post-config|/$Q_PLUGIN_CONF_FILE]]
+    [macvtap]
+    physical_interface_mappings = $PHYSICAL_NETWORK:eth1
diff --git a/doc/source/index.rst b/doc/source/index.rst
index c79b2ce..c1302eb 100644
--- a/doc/source/index.rst
+++ b/doc/source/index.rst
@@ -1,255 +1,131 @@
-DevStack - an OpenStack Community Production
-============================================
+.. Documentation Architecture for the devstack docs.
+
+   It is really easy for online docs to meander over time as people
+   attempt to add the small bit of additional information they think
+   people need, into an existing information architecture. In order to
+   prevent that we need to be a bit strict as to what's on this front
+   page.
+
+   This should *only* be the quick start narrative. Which should end
+   with 2 sections: what you can do with devstack once it's set up,
+   and how to go beyond this setup. Both should be a set of quick
+   links to other documents to let people explore from there.
+
+==========
+ DevStack
+==========
 
 .. image:: assets/images/logo-blue.png
 
-.. toctree::
-   :glob:
-   :maxdepth: 1
+DevStack is a series of extensible scripts used to quickly bring up a
+complete OpenStack environment based on the latest versions of
+everything from git master.  It is used interactively as a development
+environment and as the basis for much of the OpenStack project's
+functional testing.
 
-   overview
-   configuration
-   plugins
-   plugin-registry
-   faq
-   changes
-   hacking
+The source is available at
+`<https://git.openstack.org/cgit/openstack-dev/devstack>`__.
+
+.. warning::
+
+   DevStack will make substantial changes to your system during
+   installation. Only run DevStack on servers or virtual machines that
+   are dedicated to this purpose.
 
 Quick Start
------------
+===========
 
-#. Select a Linux Distribution
-
-   Only Ubuntu 14.04 (Trusty), Fedora 22 (or Fedora 23) and CentOS/RHEL
-   7 are documented here. OpenStack also runs and is packaged on other
-   flavors of Linux such as OpenSUSE and Debian.
-
-#. Install Selected OS
-
-   In order to correctly install all the dependencies, we assume a
-   specific minimal version of the supported distributions to make it as
-   easy as possible. We recommend using a minimal install of Ubuntu or
-   Fedora server in a VM if this is your first time.
-
-#. Download DevStack
-
-   ::
-
-       git clone https://git.openstack.org/openstack-dev/devstack
-
-   The ``devstack`` repo contains a script that installs OpenStack and
-   templates for configuration files
-
-#. Configure
-
-   We recommend at least a :ref:`minimal-configuration` be set up.
-
-#. Add Stack User
-
-   Devstack should be run as a non-root user with sudo enabled
-   (standard logins to cloud images such as "ubuntu" or "cloud-user"
-   are usually fine).
-
-   You can quickly create a separate `stack` user to run DevStack with
-
-   ::
-
-       devstack/tools/create-stack-user.sh; su stack
-
-#. Start the install
-
-   ::
-
-       cd devstack; ./stack.sh
-
-   It takes a few minutes, we recommend `reading the
-   script <stack.sh.html>`__ while it is building.
-
-Guides
-======
-
-Walk through various setups used by stackers
-
-.. toctree::
-   :glob:
-   :maxdepth: 1
-
-   guides/single-vm
-   guides/single-machine
-   guides/lxc
-   guides/multinode-lab
-   guides/neutron
-   guides/devstack-with-nested-kvm
-   guides/nova
-   guides/devstack-with-lbaas-v2
-
-All-In-One Single VM
---------------------
-
-Run :doc:`OpenStack in a VM <guides/single-vm>`. The VMs launched in your cloud will be slow as
-they are running in QEMU (emulation), but it is useful if you don't have
-spare hardware laying around. :doc:`[Read] <guides/single-vm>`
-
-All-In-One Single Machine
--------------------------
-
-Run :doc:`OpenStack on dedicated hardware <guides/single-machine>`  This can include a
-server-class machine or a laptop at home.
-:doc:`[Read] <guides/single-machine>`
-
-All-In-One LXC Container
--------------------------
-
-Run :doc:`OpenStack in a LXC container <guides/lxc>`. Beneficial for intermediate
-and advanced users. The VMs launched in this cloud will be fully accelerated but
-not all OpenStack features are supported. :doc:`[Read] <guides/lxc>`
-
-Multi-Node Lab
---------------
-
-Setup a :doc:`multi-node cluster <guides/multinode-lab>` with dedicated VLANs for VMs & Management.
-:doc:`[Read] <guides/multinode-lab>`
-
-DevStack with Neutron Networking
---------------------------------
-
-Building a DevStack cluster with :doc:`Neutron Networking <guides/neutron>`.
-This guide is meant for building lab environments with a dedicated
-control node and multiple compute nodes.
-
-DevStack with KVM-based Nested Virtualization
----------------------------------------------
-
-Procedure to setup :doc:`DevStack with KVM-based Nested Virtualization
-<guides/devstack-with-nested-kvm>`. With this setup, Nova instances
-will be more performant than with plain QEMU emulation.
-
-Nova and devstack
---------------------------------
-
-Guide to working with nova features :doc:`Nova and devstack <guides/nova>`.
-
-DevStack Documentation
-======================
-
-Overview
---------
-
-:doc:`An overview of DevStack goals and priorities <overview>`
-
-Configuration
+Install Linux
 -------------
 
-:doc:`Configuring and customizing the stack <configuration>`
+Start with a clean and minimal install of a Linux system. Devstack
+attempts to support Ubuntu 14.04/16.04, Fedora 23/24, CentOS/RHEL 7,
+as well as Debian and OpenSUSE.
 
-Plugins
--------
+If you do not have a preference, Ubuntu 16.04 is the most tested, and
+will probably go the smoothest.
 
-:doc:`Extending DevStack with new features <plugins>`
+Download DevStack
+-----------------
 
-Recent Changes
+::
+
+   git clone https://git.openstack.org/openstack-dev/devstack
+
+The ``devstack`` repo contains a script that installs OpenStack and
+templates for configuration files
+
+Create a local.conf
+-------------------
+
+Create a ``local.conf`` file with 4 passwords preset
+
+::
+
+   [[local|localrc]]
+   ADMIN_PASSWORD=secret
+   DATABASE_PASSWORD=$ADMIN_PASSWORD
+   RABBIT_PASSWORD=$ADMIN_PASSWORD
+   SERVICE_PASSWORD=$ADMIN_PASSWORD
+
+This is the minimum required config to get started with DevStack.
+
+Add Stack User
 --------------
 
-:doc:`An incomplete summary of recent changes <changes>`
+Devstack should be run as a non-root user with sudo enabled
+(standard logins to cloud images such as "ubuntu" or "cloud-user"
+are usually fine).
 
-FAQ
----
+You can quickly create a separate `stack` user to run DevStack with
 
-:doc:`The DevStack FAQ <faq>`
+::
 
-Contributing
-------------
+   devstack/tools/create-stack-user.sh; su stack
 
-:doc:`Pitching in to make DevStack a better place <hacking>`
+Start the install
+-----------------
 
-Code
-====
+::
 
-*A look at the bits that make it all go*
+   cd devstack; ./stack.sh
 
-Scripts
+This will take a 15 - 20 minutes, largely depending on the speed of
+your internet connection. Many git trees and packages will be
+installed during this process.
+
+Profit!
 -------
 
-* `stack.sh <stack.sh.html>`__ - The main script
-* `functions <functions.html>`__ - DevStack-specific functions
-* `functions-common <functions-common.html>`__ - Functions shared with other projects
-* `lib/apache <lib/apache.html>`__
-* `lib/ceph <lib/ceph.html>`__
-* `lib/cinder <lib/cinder.html>`__
-* `lib/database <lib/database.html>`__
-* `lib/dstat <lib/dstat.html>`__
-* `lib/glance <lib/glance.html>`__
-* `lib/heat <lib/heat.html>`__
-* `lib/horizon <lib/horizon.html>`__
-* `lib/infra <lib/infra.html>`__
-* `lib/keystone <lib/keystone.html>`__
-* `lib/ldap <lib/ldap.html>`__
-* `lib/neutron-legacy <lib/neutron-legacy.html>`__
-* `lib/nova <lib/nova.html>`__
-* `lib/oslo <lib/oslo.html>`__
-* `lib/rpc\_backend <lib/rpc_backend.html>`__
-* `lib/swift <lib/swift.html>`__
-* `lib/tempest <lib/tempest.html>`__
-* `lib/tls <lib/tls.html>`__
-* `lib/trove <lib/trove.html>`__
-* `unstack.sh <unstack.sh.html>`__
-* `clean.sh <clean.sh.html>`__
-* `run\_tests.sh <run_tests.sh.html>`__
+You now have a working DevStack! Congrats!
 
-* `extras.d/60-ceph.sh <extras.d/60-ceph.sh.html>`__
-* `extras.d/70-tuskar.sh <extras.d/70-tuskar.sh.html>`__
-* `extras.d/80-tempest.sh <extras.d/80-tempest.sh.html>`__
+Your devstack will have installed ``keystone``, ``glance``, ``nova``,
+``cinder``, ``neutron``, and ``horizon``. Floating IPs will be
+available, guests have access to the external world.
 
-* `inc/ini-config <inc/ini-config.html>`__
-* `inc/meta-config <inc/meta-config.html>`__
-* `inc/python <inc/python.html>`__
+You can access horizon to experience the web interface to
+OpenStack, and manage vms, networks, volumes, and images from
+there.
 
-* `pkg/elasticsearch.sh <pkg/elasticsearch.sh.html>`_
+You can ``source openrc`` in your shell, and then use the
+``openstack`` command line tool to manage your devstack.
 
-Configuration
+You can ``cd /opt/stack/tempest`` and run tempest tests that have
+been configured to work with your devstack.
+
+Going further
 -------------
 
-.. toctree::
-   :glob:
-   :maxdepth: 1
+Learn more about our :doc:`configuration system <configuration>` to
+customize devstack for your needs.
 
-   local.conf
-   stackrc
-   openrc
-   exerciserc
+Read :doc:`guides <guides>` for specific setups people have (note:
+guides are point in time contributions, and may not always be kept
+up to date to the latest devstack).
 
-Tools
------
+Enable :doc:`devstack plugins <plugins>` to support additional
+services, features, and configuration not present in base devstack.
 
-* `tools/build\_docs.sh <tools/build_docs.sh.html>`__
-* `tools/build\_venv.sh <tools/build_venv.sh.html>`__
-* `tools/create-stack-user.sh <tools/create-stack-user.sh.html>`__
-* `tools/create\_userrc.sh <tools/create_userrc.sh.html>`__
-* `tools/fixup\_stuff.sh <tools/fixup_stuff.sh.html>`__
-* `tools/info.sh <tools/info.sh.html>`__
-* `tools/install\_pip.sh <tools/install_pip.sh.html>`__
-* `tools/install\_prereqs.sh <tools/install_prereqs.sh.html>`__
-* `tools/make\_cert.sh <tools/make_cert.sh.html>`__
-* `tools/upload\_image.sh <tools/upload_image.sh.html>`__
-
-Samples
--------
-
-* `local.sh <samples/local.sh.html>`__
-
-Exercises
----------
-
-* `exercise.sh <exercise.sh.html>`__
-* `exercises/aggregates.sh <exercises/aggregates.sh.html>`__
-* `exercises/boot\_from\_volume.sh <exercises/boot_from_volume.sh.html>`__
-* `exercises/bundle.sh <exercises/bundle.sh.html>`__
-* `exercises/client-args.sh <exercises/client-args.sh.html>`__
-* `exercises/client-env.sh <exercises/client-env.sh.html>`__
-* `exercises/euca.sh <exercises/euca.sh.html>`__
-* `exercises/floating\_ips.sh <exercises/floating_ips.sh.html>`__
-* `exercises/horizon.sh <exercises/horizon.sh.html>`__
-* `exercises/neutron-adv-test.sh <exercises/neutron-adv-test.sh.html>`__
-* `exercises/sec\_groups.sh <exercises/sec_groups.sh.html>`__
-* `exercises/swift.sh <exercises/swift.sh.html>`__
-* `exercises/volumes.sh <exercises/volumes.sh.html>`__
+Get :doc:`the big picture <overview>` of what we are trying to do
+with devstack, and help us by :doc:`contributing to the project
+<hacking>`.
diff --git a/doc/source/local.conf.rst b/doc/source/local.conf.rst
deleted file mode 100644
index a1ca60a..0000000
--- a/doc/source/local.conf.rst
+++ /dev/null
@@ -1,9 +0,0 @@
-==========================
-local.conf - User Settings
-==========================
-
-``local.conf`` is a user-maintained settings file that is sourced in
-``stackrc``. It contains a section that replaces the historical
-``localrc`` file. See the description of
-:doc:`local.conf <configuration>` for more details about the mechanics
-of the file.
diff --git a/doc/source/openrc.rst b/doc/source/openrc.rst
deleted file mode 100644
index 4e7f075..0000000
--- a/doc/source/openrc.rst
+++ /dev/null
@@ -1,68 +0,0 @@
-=====================================
-openrc - User Authentication Settings
-=====================================
-
-``openrc`` configures login credentials suitable for use with the
-OpenStack command-line tools. ``openrc`` sources ``stackrc`` at the
-beginning (which in turn sources the ``localrc`` section of
-``local.conf``) in order to pick up ``HOST_IP`` and/or ``SERVICE_HOST``
-to use in the endpoints. The values shown below are the default values.
-
-OS\_PROJECT\_NAME (OS\_TENANT\_NAME)
-    Keystone has
-    standardized the term *project* as the entity that owns resources. In
-    some places references still exist to the previous term
-    *tenant* for this use. Also, *project\_name* is preferred to
-    *project\_id*.  OS\_TENANT\_NAME remains supported for compatibility
-    with older tools.
-
-    ::
-
-        OS_PROJECT_NAME=demo
-
-OS\_USERNAME
-    In addition to the owning entity (project), OpenStack calls the entity
-    performing the action *user*.
-
-    ::
-
-        OS_USERNAME=demo
-
-OS\_PASSWORD
-    Keystone's default authentication requires a password be provided.
-    The usual cautions about putting passwords in environment variables
-    apply, for most DevStack uses this may be an acceptable tradeoff.
-
-    ::
-
-        OS_PASSWORD=secret
-
-HOST\_IP, SERVICE\_HOST
-    Set API endpoint host using ``HOST_IP``. ``SERVICE_HOST`` may also
-    be used to specify the endpoint, which is convenient for some
-    ``local.conf`` configurations. Typically, ``HOST_IP`` is set in the
-    ``localrc`` section.
-
-    ::
-
-        HOST_IP=127.0.0.1
-        SERVICE_HOST=$HOST_IP
-
-OS\_AUTH\_URL
-    Authenticating against an OpenStack cloud using Keystone returns a
-    *Token* and *Service Catalog*. The catalog contains the endpoints
-    for all services the user/tenant has access to - including Nova,
-    Glance, Keystone and Swift.
-
-    ::
-
-        OS_AUTH_URL=http://$SERVICE_HOST:5000/v2.0
-
-KEYSTONECLIENT\_DEBUG, NOVACLIENT\_DEBUG
-    Set command-line client log level to ``DEBUG``. These are commented
-    out by default.
-
-    ::
-
-        # export KEYSTONECLIENT_DEBUG=1
-        # export NOVACLIENT_DEBUG=1
diff --git a/doc/source/plugin-registry.rst b/doc/source/plugin-registry.rst
index 999350f..bdb8d8b 100644
--- a/doc/source/plugin-registry.rst
+++ b/doc/source/plugin-registry.rst
@@ -1,23 +1,26 @@
 ..
-  Note to patch submitters: this file is covered by a periodic proposal
-  job.  You should edit the files data/devstack-plugins-registry.footer
-  data/devstack-plugins-registry.header instead of this one.
+
+  Note to patch submitters:
+
+  # ============================= #
+  # THIS FILE IS AUTOGENERATED !  #
+  # ============================= #
+
+  ** Plugins are found automatically and added to this list **
+
+  This file is created by a periodic proposal job.  You should not
+  edit this file.
+
+  You should edit the files data/devstack-plugins-registry.footer
+  data/devstack-plugins-registry.header to modify this text.
 
 ==========================
  DevStack Plugin Registry
 ==========================
 
-Since we've created the external plugin mechanism, it's gotten used by
-a lot of projects. The following is a list of plugins that currently
-exist. Any project that wishes to list their plugin here is welcomed
-to.
-
-Detected Plugins
-================
-
-The following are plugins that a script has found in the openstack/
-namespace, which includes but is not limited to official OpenStack
-projects.
+The following list is an automatically-generated collection of
+available DevStack plugins.  This includes, but is not limited to,
+official OpenStack projects.
 
 
 ====================================== ===
@@ -27,6 +30,7 @@
 app-catalog-ui                         `git://git.openstack.org/openstack/app-catalog-ui <https://git.openstack.org/cgit/openstack/app-catalog-ui>`__
 astara                                 `git://git.openstack.org/openstack/astara <https://git.openstack.org/cgit/openstack/astara>`__
 barbican                               `git://git.openstack.org/openstack/barbican <https://git.openstack.org/cgit/openstack/barbican>`__
+bilean                                 `git://git.openstack.org/openstack/bilean <https://git.openstack.org/cgit/openstack/bilean>`__
 blazar                                 `git://git.openstack.org/openstack/blazar <https://git.openstack.org/cgit/openstack/blazar>`__
 broadview-collector                    `git://git.openstack.org/openstack/broadview-collector <https://git.openstack.org/cgit/openstack/broadview-collector>`__
 ceilometer                             `git://git.openstack.org/openstack/ceilometer <https://git.openstack.org/cgit/openstack/ceilometer>`__
@@ -44,6 +48,7 @@
 devstack-plugin-glusterfs              `git://git.openstack.org/openstack/devstack-plugin-glusterfs <https://git.openstack.org/cgit/openstack/devstack-plugin-glusterfs>`__
 devstack-plugin-hdfs                   `git://git.openstack.org/openstack/devstack-plugin-hdfs <https://git.openstack.org/cgit/openstack/devstack-plugin-hdfs>`__
 devstack-plugin-kafka                  `git://git.openstack.org/openstack/devstack-plugin-kafka <https://git.openstack.org/cgit/openstack/devstack-plugin-kafka>`__
+devstack-plugin-mariadb                `git://git.openstack.org/openstack/devstack-plugin-mariadb <https://git.openstack.org/cgit/openstack/devstack-plugin-mariadb>`__
 devstack-plugin-nfs                    `git://git.openstack.org/openstack/devstack-plugin-nfs <https://git.openstack.org/cgit/openstack/devstack-plugin-nfs>`__
 devstack-plugin-pika                   `git://git.openstack.org/openstack/devstack-plugin-pika <https://git.openstack.org/cgit/openstack/devstack-plugin-pika>`__
 devstack-plugin-sheepdog               `git://git.openstack.org/openstack/devstack-plugin-sheepdog <https://git.openstack.org/cgit/openstack/devstack-plugin-sheepdog>`__
@@ -56,15 +61,24 @@
 freezer-web-ui                         `git://git.openstack.org/openstack/freezer-web-ui <https://git.openstack.org/cgit/openstack/freezer-web-ui>`__
 gce-api                                `git://git.openstack.org/openstack/gce-api <https://git.openstack.org/cgit/openstack/gce-api>`__
 gnocchi                                `git://git.openstack.org/openstack/gnocchi <https://git.openstack.org/cgit/openstack/gnocchi>`__
+group-based-policy                     `git://git.openstack.org/openstack/group-based-policy <https://git.openstack.org/cgit/openstack/group-based-policy>`__
+heat                                   `git://git.openstack.org/openstack/heat <https://git.openstack.org/cgit/openstack/heat>`__
+higgins                                `git://git.openstack.org/openstack/higgins <https://git.openstack.org/cgit/openstack/higgins>`__
+horizon-mellanox                       `git://git.openstack.org/openstack/horizon-mellanox <https://git.openstack.org/cgit/openstack/horizon-mellanox>`__
 ironic                                 `git://git.openstack.org/openstack/ironic <https://git.openstack.org/cgit/openstack/ironic>`__
 ironic-inspector                       `git://git.openstack.org/openstack/ironic-inspector <https://git.openstack.org/cgit/openstack/ironic-inspector>`__
+ironic-staging-drivers                 `git://git.openstack.org/openstack/ironic-staging-drivers <https://git.openstack.org/cgit/openstack/ironic-staging-drivers>`__
 kingbird                               `git://git.openstack.org/openstack/kingbird <https://git.openstack.org/cgit/openstack/kingbird>`__
-kuryr                                  `git://git.openstack.org/openstack/kuryr <https://git.openstack.org/cgit/openstack/kuryr>`__
+kuryr-libnetwork                       `git://git.openstack.org/openstack/kuryr-libnetwork <https://git.openstack.org/cgit/openstack/kuryr-libnetwork>`__
 magnum                                 `git://git.openstack.org/openstack/magnum <https://git.openstack.org/cgit/openstack/magnum>`__
 magnum-ui                              `git://git.openstack.org/openstack/magnum-ui <https://git.openstack.org/cgit/openstack/magnum-ui>`__
 manila                                 `git://git.openstack.org/openstack/manila <https://git.openstack.org/cgit/openstack/manila>`__
 mistral                                `git://git.openstack.org/openstack/mistral <https://git.openstack.org/cgit/openstack/mistral>`__
+monasca-analytics                      `git://git.openstack.org/openstack/monasca-analytics <https://git.openstack.org/cgit/openstack/monasca-analytics>`__
 monasca-api                            `git://git.openstack.org/openstack/monasca-api <https://git.openstack.org/cgit/openstack/monasca-api>`__
+monasca-ceilometer                     `git://git.openstack.org/openstack/monasca-ceilometer <https://git.openstack.org/cgit/openstack/monasca-ceilometer>`__
+monasca-log-api                        `git://git.openstack.org/openstack/monasca-log-api <https://git.openstack.org/cgit/openstack/monasca-log-api>`__
+monasca-transform                      `git://git.openstack.org/openstack/monasca-transform <https://git.openstack.org/cgit/openstack/monasca-transform>`__
 murano                                 `git://git.openstack.org/openstack/murano <https://git.openstack.org/cgit/openstack/murano>`__
 networking-6wind                       `git://git.openstack.org/openstack/networking-6wind <https://git.openstack.org/cgit/openstack/networking-6wind>`__
 networking-bagpipe                     `git://git.openstack.org/openstack/networking-bagpipe <https://git.openstack.org/cgit/openstack/networking-bagpipe>`__
@@ -74,6 +88,7 @@
 networking-cisco                       `git://git.openstack.org/openstack/networking-cisco <https://git.openstack.org/cgit/openstack/networking-cisco>`__
 networking-fortinet                    `git://git.openstack.org/openstack/networking-fortinet <https://git.openstack.org/cgit/openstack/networking-fortinet>`__
 networking-generic-switch              `git://git.openstack.org/openstack/networking-generic-switch <https://git.openstack.org/cgit/openstack/networking-generic-switch>`__
+networking-huawei                      `git://git.openstack.org/openstack/networking-huawei <https://git.openstack.org/cgit/openstack/networking-huawei>`__
 networking-infoblox                    `git://git.openstack.org/openstack/networking-infoblox <https://git.openstack.org/cgit/openstack/networking-infoblox>`__
 networking-l2gw                        `git://git.openstack.org/openstack/networking-l2gw <https://git.openstack.org/cgit/openstack/networking-l2gw>`__
 networking-midonet                     `git://git.openstack.org/openstack/networking-midonet <https://git.openstack.org/cgit/openstack/networking-midonet>`__
@@ -81,6 +96,7 @@
 networking-nec                         `git://git.openstack.org/openstack/networking-nec <https://git.openstack.org/cgit/openstack/networking-nec>`__
 networking-odl                         `git://git.openstack.org/openstack/networking-odl <https://git.openstack.org/cgit/openstack/networking-odl>`__
 networking-ofagent                     `git://git.openstack.org/openstack/networking-ofagent <https://git.openstack.org/cgit/openstack/networking-ofagent>`__
+networking-onos                        `git://git.openstack.org/openstack/networking-onos <https://git.openstack.org/cgit/openstack/networking-onos>`__
 networking-ovn                         `git://git.openstack.org/openstack/networking-ovn <https://git.openstack.org/cgit/openstack/networking-ovn>`__
 networking-ovs-dpdk                    `git://git.openstack.org/openstack/networking-ovs-dpdk <https://git.openstack.org/cgit/openstack/networking-ovs-dpdk>`__
 networking-plumgrid                    `git://git.openstack.org/openstack/networking-plumgrid <https://git.openstack.org/cgit/openstack/networking-plumgrid>`__
@@ -88,13 +104,17 @@
 networking-sfc                         `git://git.openstack.org/openstack/networking-sfc <https://git.openstack.org/cgit/openstack/networking-sfc>`__
 networking-vsphere                     `git://git.openstack.org/openstack/networking-vsphere <https://git.openstack.org/cgit/openstack/networking-vsphere>`__
 neutron                                `git://git.openstack.org/openstack/neutron <https://git.openstack.org/cgit/openstack/neutron>`__
+neutron-dynamic-routing                `git://git.openstack.org/openstack/neutron-dynamic-routing <https://git.openstack.org/cgit/openstack/neutron-dynamic-routing>`__
+neutron-fwaas                          `git://git.openstack.org/openstack/neutron-fwaas <https://git.openstack.org/cgit/openstack/neutron-fwaas>`__
 neutron-lbaas                          `git://git.openstack.org/openstack/neutron-lbaas <https://git.openstack.org/cgit/openstack/neutron-lbaas>`__
 neutron-lbaas-dashboard                `git://git.openstack.org/openstack/neutron-lbaas-dashboard <https://git.openstack.org/cgit/openstack/neutron-lbaas-dashboard>`__
 neutron-vpnaas                         `git://git.openstack.org/openstack/neutron-vpnaas <https://git.openstack.org/cgit/openstack/neutron-vpnaas>`__
 nova-docker                            `git://git.openstack.org/openstack/nova-docker <https://git.openstack.org/cgit/openstack/nova-docker>`__
+nova-lxd                               `git://git.openstack.org/openstack/nova-lxd <https://git.openstack.org/cgit/openstack/nova-lxd>`__
 nova-powervm                           `git://git.openstack.org/openstack/nova-powervm <https://git.openstack.org/cgit/openstack/nova-powervm>`__
 octavia                                `git://git.openstack.org/openstack/octavia <https://git.openstack.org/cgit/openstack/octavia>`__
 osprofiler                             `git://git.openstack.org/openstack/osprofiler <https://git.openstack.org/cgit/openstack/osprofiler>`__
+panko                                  `git://git.openstack.org/openstack/panko <https://git.openstack.org/cgit/openstack/panko>`__
 python-freezerclient                   `git://git.openstack.org/openstack/python-freezerclient <https://git.openstack.org/cgit/openstack/python-freezerclient>`__
 rally                                  `git://git.openstack.org/openstack/rally <https://git.openstack.org/cgit/openstack/rally>`__
 sahara                                 `git://git.openstack.org/openstack/sahara <https://git.openstack.org/cgit/openstack/sahara>`__
diff --git a/doc/source/plugins.rst b/doc/source/plugins.rst
index 83e5609..70469d6 100644
--- a/doc/source/plugins.rst
+++ b/doc/source/plugins.rst
@@ -99,6 +99,8 @@
       should exist at this point.
    -  **extra** - Called near the end after layer 1 and 2 services have
       been started.
+   - **test-config** Called at the end of devstack used to configure tempest
+      or any other test environments
 
 -  **unstack** - Called by ``unstack.sh`` before other services are shut
    down.
diff --git a/doc/source/site-map.rst b/doc/source/site-map.rst
new file mode 100644
index 0000000..480d6aa
--- /dev/null
+++ b/doc/source/site-map.rst
@@ -0,0 +1,21 @@
+:orphan:
+
+.. the TOC on the front page actually makes the document a lot more
+   confusing. This lets us bury a toc which we can link in when
+   appropriate.
+
+==========
+ Site Map
+==========
+
+.. toctree::
+   :glob:
+   :maxdepth: 3
+
+   overview
+   configuration
+   plugins
+   plugin-registry
+   faq
+   hacking
+   guides
diff --git a/doc/source/stackrc.rst b/doc/source/stackrc.rst
deleted file mode 100644
index 81d4b80..0000000
--- a/doc/source/stackrc.rst
+++ /dev/null
@@ -1,66 +0,0 @@
-===========================
-stackrc - DevStack Settings
-===========================
-
-``stackrc`` is the primary configuration file for DevStack. It contains
-all of the settings that control the services started and the
-repositories used to download the source for those services. ``stackrc``
-sources the ``localrc`` section of ``local.conf`` to perform the default
-overrides.
-
-DATABASE\_TYPE
-    Select the database backend to use. The default is ``mysql``,
-    ``postgresql`` is also available.
-ENABLED\_SERVICES
-    Specify which services to launch. These generally correspond to
-    screen tabs. The default includes: Glance (API and Registry),
-    Keystone, Nova (API, Certificate, Object Store, Compute, Network,
-    Scheduler, Certificate Authentication), Cinder
-    (Scheduler, API, Volume), Horizon, MySQL, RabbitMQ, Tempest.
-
-    ::
-
-        ENABLED_SERVICES=g-api,g-reg,key,n-api,n-crt,n-cpu,n-net,n-cond,c-sch,c-api,c-vol,n-sch,n-cauth,horizon,rabbit,tempest,$DATABASE_TYPE
-
-    Other services that are not enabled by default can be enabled in
-    ``localrc``. For example, to add Swift, use the following service
-    names:
-
-    ::
-
-        enable_service s-proxy s-object s-container s-account
-
-    A service can similarly be disabled:
-
-    ::
-
-        disable_service horizon
-
-Service Repos
-    The Git repositories used to check out the source for each service
-    are controlled by a pair of variables set for each service.
-    ``*_REPO`` points to the repository and ``*_BRANCH`` selects which
-    branch to check out. These may be overridden in ``local.conf`` to
-    pull source from a different repo for testing, such as a Gerrit
-    branch proposal. ``GIT_BASE`` points to the primary repository
-    server.
-
-    ::
-
-        NOVA_REPO=$GIT_BASE/openstack/nova.git
-        NOVA_BRANCH=master
-
-    To pull a branch directly from Gerrit, get the repo and branch from
-    the Gerrit review page:
-
-    ::
-
-        git fetch https://review.openstack.org/p/openstack/nova refs/changes/50/5050/1 && git checkout FETCH_HEAD
-
-    The repo is the stanza following ``fetch`` and the branch is the
-    stanza following that:
-
-    ::
-
-        NOVA_REPO=https://review.openstack.org/p/openstack/nova
-        NOVA_BRANCH=refs/changes/50/5050/1
diff --git a/exercises/boot_from_volume.sh b/exercises/boot_from_volume.sh
index 5409859..84ac08f 100755
--- a/exercises/boot_from_volume.sh
+++ b/exercises/boot_from_volume.sh
@@ -32,6 +32,7 @@
 
 # Import project functions
 source $TOP_DIR/lib/cinder
+source $TOP_DIR/lib/neutron
 source $TOP_DIR/lib/neutron-legacy
 
 # Import configuration
diff --git a/exercises/floating_ips.sh b/exercises/floating_ips.sh
index 4b72a00..485208b 100755
--- a/exercises/floating_ips.sh
+++ b/exercises/floating_ips.sh
@@ -31,6 +31,7 @@
 source $TOP_DIR/openrc
 
 # Import project functions
+source $TOP_DIR/lib/neutron
 source $TOP_DIR/lib/neutron-legacy
 
 # Import exercise configuration
diff --git a/exercises/neutron-adv-test.sh b/exercises/neutron-adv-test.sh
index a3128a8..8115006 100755
--- a/exercises/neutron-adv-test.sh
+++ b/exercises/neutron-adv-test.sh
@@ -37,6 +37,7 @@
 source $TOP_DIR/openrc
 
 # Import neutron functions
+source $TOP_DIR/lib/neutron
 source $TOP_DIR/lib/neutron-legacy
 
 # If neutron is not enabled we exit with exitcode 55, which means exercise is skipped.
diff --git a/exercises/volumes.sh b/exercises/volumes.sh
index f95c81f..0de1226 100755
--- a/exercises/volumes.sh
+++ b/exercises/volumes.sh
@@ -32,6 +32,7 @@
 
 # Import project functions
 source $TOP_DIR/lib/cinder
+source $TOP_DIR/lib/neutron
 source $TOP_DIR/lib/neutron-legacy
 
 # Import exercise configuration
diff --git a/extras.d/80-tempest.sh b/extras.d/80-tempest.sh
index fcf79bd..6a3d121 100644
--- a/extras.d/80-tempest.sh
+++ b/extras.d/80-tempest.sh
@@ -13,6 +13,8 @@
     elif [[ "$1" == "stack" && "$2" == "extra" ]]; then
         echo_summary "Initializing Tempest"
         configure_tempest
+        echo_summary "Installing Tempest Plugins"
+        install_tempest_plugins
     elif [[ "$1" == "stack" && "$2" == "post-extra" ]]; then
         # local.conf Tempest option overrides
         :
diff --git a/files/apache-keystone.template b/files/apache-keystone.template
index 428544f..8a4b0f0 100644
--- a/files/apache-keystone.template
+++ b/files/apache-keystone.template
@@ -44,8 +44,8 @@
     WSGIPassAuthorization On
 </Location>
 
-Alias /identity_admin %KEYSTONE_BIN%/keystone-wsgi-admin
-<Location /identity_admin>
+Alias /identity_v2_admin %KEYSTONE_BIN%/keystone-wsgi-admin
+<Location /identity_v2_admin>
     SetHandler wsgi-script
     Options +ExecCGI
 
diff --git a/files/rpms/general b/files/rpms/general
index 2d4a97a..d0ceb56 100644
--- a/files/rpms/general
+++ b/files/rpms/general
@@ -7,9 +7,9 @@
 gettext  # used for compiling message catalogs
 git-core
 graphviz # needed only for docs
-iptables-services  # NOPRIME f22,f23
+iptables-services  # NOPRIME f23,f24
 java-1.7.0-openjdk-headless  # NOPRIME rhel7
-java-1.8.0-openjdk-headless  # NOPRIME f22,f23
+java-1.8.0-openjdk-headless  # NOPRIME f23,f24
 libffi-devel
 libjpeg-turbo-devel # Pillow 3.0.0
 libxml2-devel # lxml
diff --git a/files/rpms/nova b/files/rpms/nova
index 0312e85..a883ec4 100644
--- a/files/rpms/nova
+++ b/files/rpms/nova
@@ -7,7 +7,7 @@
 genisoimage # required for config_drive
 iptables
 iputils
-kernel-modules # dist:f22,f23
+kernel-modules # dist:f23,f24
 kpartx
 kvm # NOPRIME
 libvirt-bin # NOPRIME
diff --git a/files/rpms/swift b/files/rpms/swift
index 46dc59d..bd249ee 100644
--- a/files/rpms/swift
+++ b/files/rpms/swift
@@ -2,7 +2,7 @@
 liberasurecode-devel
 memcached
 pyxattr
-rsync-daemon # dist:f22,f23
+rsync-daemon # dist:f23,f24
 sqlite
 xfsprogs
 xinetd
diff --git a/functions b/functions
index 1bfb8a5..5856578 100644
--- a/functions
+++ b/functions
@@ -41,6 +41,9 @@
     file=${file#$RC_DIR/}
     printf "%-40s " "$file:${called[1]}:${called[0]}"
 }
+# PS4 is exported to child shells and uses the 'short_source' function, so
+# export it so child shells have access to the 'short_source' function also.
+export -f short_source
 
 
 # Retrieve an image from a URL and upload into Glance.
@@ -83,7 +86,7 @@
     # OpenVZ-format images are provided as .tar.gz, but not decompressed prior to loading
     if [[ "$image_url" =~ 'openvz' ]]; then
         image_name="${image_fname%.tar.gz}"
-        openstack --os-cloud=devstack-admin image create "$image_name" --public --container-format ami --disk-format ami < "${image}"
+        openstack --os-cloud=devstack-admin --os-region-name="$REGION_NAME" image create "$image_name" --public --container-format ami --disk-format ami < "${image}"
         return
     fi
 
@@ -197,7 +200,7 @@
         vmdk_adapter_type="${props[1]:-$vmdk_adapter_type}"
         vmdk_net_adapter="${props[2]:-$vmdk_net_adapter}"
 
-        openstack --os-cloud=devstack-admin image create "$image_name" --public --container-format bare --disk-format vmdk --property vmware_disktype="$vmdk_disktype" --property vmware_adaptertype="$vmdk_adapter_type" --property hw_vif_model="$vmdk_net_adapter" < "${image}"
+        openstack --os-cloud=devstack-admin --os-region-name="$REGION_NAME" image create "$image_name" --public --container-format bare --disk-format vmdk --property vmware_disktype="$vmdk_disktype" --property vmware_adaptertype="$vmdk_adapter_type" --property hw_vif_model="$vmdk_net_adapter" < "${image}"
         return
     fi
 
@@ -214,7 +217,7 @@
             force_vm_mode="--property vm_mode=xen"
         fi
         openstack \
-            --os-cloud=devstack-admin \
+            --os-cloud=devstack-admin --os-region-name="$REGION_NAME" \
             image create \
             "$image_name" --public \
             --container-format=ovf --disk-format=vhd \
@@ -228,7 +231,7 @@
     if [[ "$image_url" =~ '.xen-raw.tgz' ]]; then
         image_name="${image_fname%.xen-raw.tgz}"
         openstack \
-            --os-cloud=devstack-admin \
+            --os-cloud=devstack-admin --os-region-name="$REGION_NAME" \
             image create \
             "$image_name" --public \
             --container-format=tgz --disk-format=raw \
@@ -244,10 +247,11 @@
         fi
 
         openstack \
-            --os-cloud=devstack-admin \
+            --os-cloud=devstack-admin --os-region-name="$REGION_NAME" \
             image create \
             "$image_name" --public \
             --container-format=bare --disk-format=ploop \
+            --property hypervisor_type=vz \
             --property vm_mode=$vm_mode < "${image}"
         return
     fi
@@ -295,6 +299,12 @@
             container_format=bare
             unpack=zcat
             ;;
+        *.img.bz2)
+            image_name=$(basename "$image" ".img.bz2")
+            disk_format=qcow2
+            container_format=bare
+            unpack=bunzip2
+            ;;
         *.qcow2)
             image_name=$(basename "$image" ".qcow2")
             disk_format=qcow2
@@ -322,14 +332,16 @@
     fi
 
     if is_arch "aarch64"; then
-        img_property="--property hw_machine_type=virt --property hw_cdrom_bus=virtio --property os_command_line='console=ttyAMA0'"
+        img_property="--property hw_machine_type=virt --property hw_cdrom_bus=scsi --property hw_scsi_model=virtio-scsi --property os_command_line='console=ttyAMA0'"
     fi
 
     if [ "$container_format" = "bare" ]; then
         if [ "$unpack" = "zcat" ]; then
-            openstack --os-cloud=devstack-admin image create "$image_name" $img_property --public --container-format=$container_format --disk-format $disk_format < <(zcat --force "${image}")
+            openstack --os-cloud=devstack-admin --os-region-name="$REGION_NAME" image create "$image_name" $img_property --public --container-format=$container_format --disk-format $disk_format < <(zcat --force "${image}")
+        elif [ "$unpack" = "bunzip2" ]; then
+            openstack --os-cloud=devstack-admin --os-region-name="$REGION_NAME" image create "$image_name" $img_property --public --container-format=$container_format --disk-format $disk_format < <(bunzip2 -cdk "${image}")
         else
-            openstack --os-cloud=devstack-admin image create "$image_name" $img_property --public --container-format=$container_format --disk-format $disk_format < "${image}"
+            openstack --os-cloud=devstack-admin --os-region-name="$REGION_NAME" image create "$image_name" $img_property --public --container-format=$container_format --disk-format $disk_format < "${image}"
         fi
     else
         # Use glance client to add the kernel the root filesystem.
@@ -337,12 +349,12 @@
         # kernel for use when uploading the root filesystem.
         local kernel_id="" ramdisk_id="";
         if [ -n "$kernel" ]; then
-            kernel_id=$(openstack --os-cloud=devstack-admin image create "$image_name-kernel" $img_property --public --container-format aki --disk-format aki < "$kernel" | grep ' id ' | get_field 2)
+            kernel_id=$(openstack --os-cloud=devstack-admin --os-region-name="$REGION_NAME" image create "$image_name-kernel" $img_property --public --container-format aki --disk-format aki < "$kernel" | grep ' id ' | get_field 2)
         fi
         if [ -n "$ramdisk" ]; then
-            ramdisk_id=$(openstack --os-cloud=devstack-admin image create "$image_name-ramdisk" $img_property --public --container-format ari --disk-format ari < "$ramdisk" | grep ' id ' | get_field 2)
+            ramdisk_id=$(openstack --os-cloud=devstack-admin --os-region-name="$REGION_NAME" image create "$image_name-ramdisk" $img_property --public --container-format ari --disk-format ari < "$ramdisk" | grep ' id ' | get_field 2)
         fi
-        openstack --os-cloud=devstack-admin image create "${image_name%.img}" $img_property --public --container-format ami --disk-format ami ${kernel_id:+--property kernel_id=$kernel_id} ${ramdisk_id:+--property ramdisk_id=$ramdisk_id} < "${image}"
+        openstack --os-cloud=devstack-admin --os-region-name="$REGION_NAME" image create "${image_name%.img}" $img_property --public --container-format ami --disk-format ami ${kernel_id:+--property kernel_id=$kernel_id} ${ramdisk_id:+--property ramdisk_id=$ramdisk_id} < "${image}"
     fi
 }
 
@@ -370,12 +382,24 @@
 
 # Wait for an HTTP server to start answering requests
 # wait_for_service timeout url
+#
+# If the service we want is behind a proxy, the proxy may be available
+# before the service. Compliant proxies will return a 503 in this case
+# Loop until we get something else.
+# Also check for the case where there is no proxy and the service just
+# hasn't started yet. curl returns 7 for Failed to connect to host.
 function wait_for_service {
     local timeout=$1
     local url=$2
+    local rval=0
     time_start "wait_for_service"
-    timeout $timeout sh -c "while ! $CURL_GET -k --noproxy '*' -s $url >/dev/null; do sleep 1; done"
+    timeout $timeout bash -x <<EOF || rval=$?
+        while [[ \$( ${CURL_GET} -k --noproxy '*' -s -o /dev/null -w '%{http_code}' ${url} ) == 503 || \$? -eq 7 ]]; do
+            sleep 1
+        done
+EOF
     time_stop "wait_for_service"
+    return $rval
 }
 
 
@@ -500,61 +524,6 @@
 }
 
 
-# This function recursively compares versions, and is not meant to be
-# called by anything other than vercmp_numbers below. This function does
-# not work with alphabetic versions.
-#
-# _vercmp_r sep ver1 ver2
-function _vercmp_r {
-    typeset sep
-    typeset -a ver1=() ver2=()
-    sep=$1; shift
-    ver1=("${@:1:sep}")
-    ver2=("${@:sep+1}")
-
-    if ((ver1 > ver2)); then
-        echo 1; return 0
-    elif ((ver2 > ver1)); then
-        echo -1; return 0
-    fi
-
-    if ((sep <= 1)); then
-        echo 0; return 0
-    fi
-
-    _vercmp_r $((sep-1)) "${ver1[@]:1}" "${ver2[@]:1}"
-}
-
-
-# This function compares two versions and is meant to be called by
-# external callers. Please note the function assumes non-alphabetic
-# versions. For example, this will work:
-#
-#   vercmp_numbers 1.10 1.4
-#
-# The above will return "1", as 1.10 is greater than 1.4.
-#
-#   vercmp_numbers 5.2 6.4
-#
-# The above will return "-1", as 5.2 is less than 6.4.
-#
-#   vercmp_numbers 4.0 4.0
-#
-# The above will return "0", as the versions are equal.
-#
-# vercmp_numbers ver1 ver2
-function vercmp_numbers {
-    typeset v1=$1 v2=$2 sep
-    typeset -a ver1 ver2
-
-    deprecated "vercmp_numbers is deprecated for more generic vercmp"
-
-    IFS=. read -ra ver1 <<< "$v1"
-    IFS=. read -ra ver2 <<< "$v2"
-
-    _vercmp_r "${#ver1[@]}" "${ver1[@]}" "${ver2[@]}"
-}
-
 # vercmp ver1 op ver2
 #  Compare VER1 to VER2
 #   - op is one of < <= == >= >
@@ -668,6 +637,15 @@
     fi
 }
 
+
+# set_mtu - Set MTU on a device
+function set_mtu {
+    local dev=$1
+    local mtu=$2
+    sudo ip link set mtu $mtu dev $dev
+}
+
+
 # Restore xtrace
 $_XTRACE_FUNCTIONS
 
diff --git a/functions-common b/functions-common
index b0352d3..3fdd71b 100644
--- a/functions-common
+++ b/functions-common
@@ -123,7 +123,7 @@
         --os-project-name admin
 
     # CLean up any old clouds.yaml files we had laying around
-    rm -f ~$STACK_USER/.config/openstack/clouds.yaml
+    rm -f $(eval echo ~"$STACK_USER")/.config/openstack/clouds.yaml
 }
 
 # trueorfalse <True|False> <VAR>
@@ -380,7 +380,8 @@
         DISTRO="sle${os_RELEASE%.*}"
     elif [[ "$os_VENDOR" =~ (Red.*Hat) || \
         "$os_VENDOR" =~ (CentOS) || \
-        "$os_VENDOR" =~ (OracleLinux) || \
+        "$os_VENDOR" =~ (Scientific) || \
+        "$os_VENDOR" =~ (OracleServer) || \
         "$os_VENDOR" =~ (Virtuozzo) ]]; then
         # Drop the . release as we assume it's compatible
         # XXX re-evaluate when we get RHEL10
@@ -427,7 +428,7 @@
         GetOSVersion
     fi
 
-    [ "$os_VENDOR" = "OracleLinux" ]
+    [ "$os_VENDOR" = "OracleServer" ]
 }
 
 
@@ -441,7 +442,7 @@
 
     [ "$os_VENDOR" = "Fedora" ] || [ "$os_VENDOR" = "Red Hat" ] || \
         [ "$os_VENDOR" = "RedHatEnterpriseServer" ] || \
-        [ "$os_VENDOR" = "CentOS" ] || [ "$os_VENDOR" = "OracleLinux" ] || \
+        [ "$os_VENDOR" = "CentOS" ] || [ "$os_VENDOR" = "OracleServer" ] || \
         [ "$os_VENDOR" = "Virtuozzo" ] || [ "$os_VENDOR" = "kvmibm" ]
 }
 
@@ -840,27 +841,49 @@
     echo $role_id
 }
 
+# Returns the domain parts of a function call if present
+# Usage: _get_domain_args [<user_domain> <project_domain>]
+function _get_domain_args {
+    local domain
+    domain=""
+
+    if [[ -n "$1" ]]; then
+        domain="$domain --user-domain $1"
+    fi
+    if [[ -n "$2" ]]; then
+        domain="$domain --project-domain $2"
+    fi
+
+    echo $domain
+}
+
 # Gets or adds user role to project
-# Usage: get_or_add_user_project_role <role> <user> <project>
+# Usage: get_or_add_user_project_role <role> <user> <project> [<user_domain> <project_domain>]
 function get_or_add_user_project_role {
     local user_role_id
+
+    domain_args=$(_get_domain_args $4 $5)
+
     # Gets user role id
     user_role_id=$(openstack role list \
         --user $2 \
         --column "ID" \
         --project $3 \
         --column "Name" \
+        $domain_args \
         | grep " $1 " | get_field 1)
     if [[ -z "$user_role_id" ]]; then
         # Adds role to user and get it
         openstack role add $1 \
             --user $2 \
-            --project $3
+            --project $3 \
+            $domain_args
         user_role_id=$(openstack role list \
             --user $2 \
             --column "ID" \
             --project $3 \
             --column "Name" \
+            $domain_args \
             | grep " $1 " | get_field 1)
     fi
     echo $user_role_id
@@ -2041,14 +2064,14 @@
         # TODO(dtroyer): Remove these legacy special-cases after the is_XXX_enabled()
         #                are implemented
 
-        [[ ${service} == n-cell-* && ${ENABLED_SERVICES} =~ "n-cell" ]] && enabled=0
-        [[ ${service} == n-cpu-* && ${ENABLED_SERVICES} =~ "n-cpu" ]] && enabled=0
-        [[ ${service} == "nova" && ${ENABLED_SERVICES} =~ "n-" ]] && enabled=0
-        [[ ${service} == "glance" && ${ENABLED_SERVICES} =~ "g-" ]] && enabled=0
-        [[ ${service} == "neutron" && ${ENABLED_SERVICES} =~ "q-" ]] && enabled=0
-        [[ ${service} == "trove" && ${ENABLED_SERVICES} =~ "tr-" ]] && enabled=0
-        [[ ${service} == "swift" && ${ENABLED_SERVICES} =~ "s-" ]] && enabled=0
-        [[ ${service} == s-* && ${ENABLED_SERVICES} =~ "swift" ]] && enabled=0
+        [[ ${service} == n-cell-* && ,${ENABLED_SERVICES} =~ ,"n-cell" ]] && enabled=0
+        [[ ${service} == n-cpu-* && ,${ENABLED_SERVICES} =~ ,"n-cpu" ]] && enabled=0
+        [[ ${service} == "nova" && ,${ENABLED_SERVICES} =~ ,"n-" ]] && enabled=0
+        [[ ${service} == "glance" && ,${ENABLED_SERVICES} =~ ,"g-" ]] && enabled=0
+        [[ ${service} == "neutron" && ,${ENABLED_SERVICES} =~ ,"q-" ]] && enabled=0
+        [[ ${service} == "trove" && ,${ENABLED_SERVICES} =~ ,"tr-" ]] && enabled=0
+        [[ ${service} == "swift" && ,${ENABLED_SERVICES} =~ ,"s-" ]] && enabled=0
+        [[ ${service} == s-* && ,${ENABLED_SERVICES} =~ ,"swift" ]] && enabled=0
     done
 
     $xtrace
@@ -2241,11 +2264,12 @@
 # Service wrapper to restart services
 # restart_service service-name
 function restart_service {
-    if is_ubuntu; then
-        sudo /usr/sbin/service $1 restart
+    if [ -x /bin/systemctl ]; then
+        sudo /bin/systemctl restart $1
     else
-        sudo /sbin/service $1 restart
+        sudo service $1 restart
     fi
+
 }
 
 # Only change permissions of a file or directory if it is not on an
@@ -2263,20 +2287,20 @@
 # Service wrapper to start services
 # start_service service-name
 function start_service {
-    if is_ubuntu; then
-        sudo /usr/sbin/service $1 start
+    if [ -x /bin/systemctl ]; then
+        sudo /bin/systemctl start $1
     else
-        sudo /sbin/service $1 start
+        sudo service $1 start
     fi
 }
 
 # Service wrapper to stop services
 # stop_service service-name
 function stop_service {
-    if is_ubuntu; then
-        sudo /usr/sbin/service $1 stop
+    if [ -x /bin/systemctl ]; then
+        sudo /bin/systemctl stop $1
     else
-        sudo /sbin/service $1 stop
+        sudo service $1 stop
     fi
 }
 
@@ -2347,7 +2371,7 @@
 function time_stop {
     local name
     local end_time
-    local elpased_time
+    local elapsed_time
     local total
     local start_time
 
diff --git a/inc/ini-config b/inc/ini-config
index 1f12343..68d48d1 100644
--- a/inc/ini-config
+++ b/inc/ini-config
@@ -274,6 +274,170 @@
     $xtrace
 }
 
+# Set a localrc var
+function localrc_set {
+    local file=$1
+    local group="local"
+    local conf="localrc"
+    local section=""
+    local option=$2
+    local value=$3
+    localconf_set "$file" "$group" "$conf" "$section" "$option" "$value"
+}
+
+# Check if local.conf has section.
+function localconf_has_section {
+    local file=$1
+    local group=$2
+    local conf=$3
+    local section=$4
+    local sep
+    sep=$(echo -ne "\x01")
+    local line
+    line=$(sed -ne "\\${sep}^\[\[${group}|${conf}\]\]${sep},\\${sep}\[\[.*\]\]${sep}{
+        /\[${section}\]/p
+    }" "$file")
+    [ -n "$line" ]
+}
+
+# Check if local.conf has option.
+function localconf_has_option {
+    local file=$1
+    local group=$2
+    local conf=$3
+    local section=$4
+    local option=$5
+    local sep
+    sep=$(echo -ne "\x01")
+    local line
+    if [[ -z "$section" ]]; then
+        line=$(sed -ne "\\${sep}^\[\[${group}|${conf}\]\]${sep},\\${sep}\[\[.*\]\]${sep}{
+            /${option}[ \t]*=.*$/p
+        }" "$file")
+    else
+        line=$(sed -ne "\\${sep}^\[\[${group}|${conf}\]\]${sep},\\${sep}\[\[.*\]\]${sep}{
+            /\[${section}\]/,/\[\[.*\]\]\|\[.*\]/{
+                /${option}[ \t]*=.*$/p}
+        }" "$file")
+    fi
+    [ -n "$line" ]
+}
+
+# Update option in local.conf.
+function localconf_update_option {
+    local sudo=$1
+    local file=$2
+    local group=$3
+    local conf=$4
+    local section=$5
+    local option=$6
+    local value=$7
+    local sep
+    sep=$(echo -ne "\x01")
+    if [[ -z "$section" ]]; then
+        $sudo sed -i -e "\\${sep}^\[\[${group}|${conf}\]\]${sep},\\${sep}\[\[.*\]\]${sep}{
+            s${sep}^\(${option}[ \t]*=[ \t]*\).*\$${sep}\1${value}${sep}
+        }" "$file"
+    else
+        $sudo sed -i -e "\\${sep}^\[\[${group}|${conf}\]\]${sep},\\${sep}\[\[.*\]\]${sep}{
+            /\[${section}\]/,/\[\[.*\]\]\|\[.*\]/s${sep}^\(${option}[ \t]*=[ \t]*\).*\$${sep}\1${value}${sep}
+        }" "$file"
+    fi
+}
+
+# Add option in local.conf.
+function localconf_add_option {
+    local sudo=$1
+    local file=$2
+    local group=$3
+    local conf=$4
+    local section=$5
+    local option=$6
+    local value=$7
+    local sep
+    sep=$(echo -ne "\x01")
+    if [[ -z "$section" ]]; then
+        $sudo sed -i -e "\\${sep}^\[\[${group}|${conf}\]\]${sep} a $option=$value" "$file"
+    else
+        $sudo sed -i -e "\\${sep}^\[\[${group}|${conf}\]\]${sep},\\${sep}\[\[.*\]\]${sep}{
+            /\[${section}\]/ a $option=$value
+        }" "$file"
+    fi
+}
+
+# Add section and option in local.conf.
+function localconf_add_section_and_option {
+    local sudo=$1
+    local file=$2
+    local group=$3
+    local conf=$4
+    local section=$5
+    local option=$6
+    local value=$7
+    local sep
+    sep=$(echo -ne "\x01")
+    $sudo sed -i -e "\\${sep}^\[\[${group}|${conf}\]\]${sep} {
+        a [$section]
+        a $option=$value
+    }" "$file"
+}
+
+# Set an option in a local.conf file.
+# localconf_set [-sudo] config-file group conf-name section option value
+#  - if the file does not exist, it is created
+function localconf_set {
+    local xtrace
+    xtrace=$(set +o | grep xtrace)
+    set +o xtrace
+    local sep
+    sep=$(echo -ne "\x01")
+    local sudo=""
+    if [ $1 == "-sudo" ]; then
+        sudo="sudo "
+        shift
+    fi
+    local file=$1
+    local group=$2
+    local conf=$3
+    local section=$4
+    local option=$5
+    local value=$6
+
+    if [[ -z $group || -z $conf || -z $option || -z $value ]]; then
+        $xtrace
+        return
+    fi
+
+    if ! grep -q "^\[\[${group}|${conf}\]\]" "$file" 2>/dev/null; then
+        # Add meta section at the end if it does not exist
+        echo -e "\n[[${group}|${conf}]]" | $sudo tee --append "$file" > /dev/null
+        # Add section at the end
+        if [[ -n "$section" ]]; then
+            echo -e "[$section]" | $sudo tee --append "$file" > /dev/null
+        fi
+        # Add option at the end
+        echo -e "$option=$value" | $sudo tee --append "$file" > /dev/null
+    elif [[ -z "$section" ]]; then
+        if ! localconf_has_option "$file" "$group" "$conf" "$section" "$option"; then
+            # Add option
+            localconf_add_option "$sudo" "$file" "$group" "$conf" "$section" "$option" "$value"
+        else
+            # Replace it
+            localconf_update_option "$sudo" "$file" "$group" "$conf" "$section" "$option" "$value"
+        fi
+    elif ! localconf_has_section "$file" "$group" "$conf" "$section"; then
+        # Add section and option in specified meta section
+        localconf_add_section_and_option "$sudo" "$file" "$group" "$conf" "$section" "$option" "$value"
+    elif ! localconf_has_option "$file" "$group" "$conf" "$section" "$option"; then
+        # Add option
+        localconf_add_option "$sudo" "$file" "$group" "$conf" "$section" "$option" "$value"
+    else
+        # Replace it
+        localconf_update_option "$sudo" "$file" "$group" "$conf" "$section" "$option" "$value"
+    fi
+    $xtrace
+}
+
 # Restore xtrace
 $INC_CONF_TRACE
 
diff --git a/inc/python b/inc/python
index 495150d..9de2831 100644
--- a/inc/python
+++ b/inc/python
@@ -148,11 +148,15 @@
     fi
 
     $xtrace
+    # adding SETUPTOOLS_SYS_PATH_TECHNIQUE is a workaround to keep
+    # the same behaviour of setuptools before version 25.0.0.
+    # related issue: https://github.com/pypa/pip/issues/3874
     $sudo_pip \
         http_proxy="${http_proxy:-}" \
         https_proxy="${https_proxy:-}" \
         no_proxy="${no_proxy:-}" \
         PIP_FIND_LINKS=$PIP_FIND_LINKS \
+        SETUPTOOLS_SYS_PATH_TECHNIQUE=rewrite \
         $cmd_pip $upgrade \
         $@
     result=$?
@@ -192,7 +196,7 @@
 function use_library_from_git {
     local name=$1
     local enabled=1
-    [[ ,${LIBS_FROM_GIT}, =~ ,${name}, ]] && enabled=0
+    [[ ${LIBS_FROM_GIT} = 'ALL' ]] || [[ ,${LIBS_FROM_GIT}, =~ ,${name}, ]] && enabled=0
     return $enabled
 }
 
diff --git a/lib/ceph b/lib/ceph
index 3e0839a..1e55c48 100644
--- a/lib/ceph
+++ b/lib/ceph
@@ -116,7 +116,7 @@
 
 # check_os_support_ceph() - Check if the operating system provides a decent version of Ceph
 function check_os_support_ceph {
-    if [[ ! ${DISTRO} =~ (trusty|f22|f23) ]]; then
+    if [[ ! ${DISTRO} =~ (trusty|f23|f24) ]]; then
         echo "WARNING: your distro $DISTRO does not provide (at least) the Firefly release. Please use Ubuntu Trusty or Fedora 20 (and higher)"
         if [[ "$FORCE_CEPH_INSTALL" != "yes" ]]; then
             die $LINENO "If you wish to install Ceph on this distribution anyway run with FORCE_CEPH_INSTALL=yes"
@@ -301,7 +301,6 @@
     iniset $NOVA_CONF libvirt rbd_user ${CINDER_CEPH_USER}
     iniset $NOVA_CONF libvirt rbd_secret_uuid ${CINDER_CEPH_UUID}
     iniset $NOVA_CONF libvirt inject_key false
-    iniset $NOVA_CONF libvirt inject_partition -2
     iniset $NOVA_CONF libvirt disk_cachemodes "network=writeback"
     iniset $NOVA_CONF libvirt images_type rbd
     iniset $NOVA_CONF libvirt images_rbd_pool ${NOVA_CEPH_POOL}
diff --git a/lib/cinder b/lib/cinder
index 4df7de8..a87f395 100644
--- a/lib/cinder
+++ b/lib/cinder
@@ -39,7 +39,7 @@
 
 # set up default directories
 GITDIR["python-cinderclient"]=$DEST/python-cinderclient
-GITDIR["os-brick"]=$DEST/os-brick
+GITDIR["python-brick-cinderclient-ext"]=$DEST/python-brick-cinderclient-ext
 CINDER_DIR=$DEST/cinder
 
 # Cinder virtual environment
@@ -269,11 +269,10 @@
     iniset $CINDER_CONF DEFAULT state_path $CINDER_STATE_PATH
     iniset $CINDER_CONF oslo_concurrency lock_path $CINDER_STATE_PATH
     iniset $CINDER_CONF DEFAULT periodic_interval $CINDER_PERIODIC_INTERVAL
+    iniset $CINDER_CONF DEFAULT my_ip "$HOST_IP"
 
     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=""
@@ -342,6 +341,10 @@
         iniset $CINDER_CONF DEFAULT glance_ca_certificates_file $SSL_BUNDLE_FILE
     fi
 
+    if [ "$GLANCE_V1_ENABLED" != "True" ]; then
+        iniset $CINDER_CONF DEFAULT glance_api_version 2
+    fi
+
     # Register SSL certificates if provided
     if is_ssl_enabled_service cinder; then
         ensure_certificates CINDER
@@ -386,6 +389,14 @@
             "$CINDER_SERVICE_PROTOCOL://$CINDER_SERVICE_HOST:$CINDER_SERVICE_PORT/v2/\$(project_id)s" \
             "$CINDER_SERVICE_PROTOCOL://$CINDER_SERVICE_HOST:$CINDER_SERVICE_PORT/v2/\$(project_id)s" \
             "$CINDER_SERVICE_PROTOCOL://$CINDER_SERVICE_HOST:$CINDER_SERVICE_PORT/v2/\$(project_id)s"
+
+        get_or_create_service "cinderv3" "volumev3" "Cinder Volume Service V3"
+        get_or_create_endpoint \
+            "volumev3" \
+            "$REGION_NAME" \
+            "$CINDER_SERVICE_PROTOCOL://$CINDER_SERVICE_HOST:$CINDER_SERVICE_PORT/v3/\$(project_id)s" \
+            "$CINDER_SERVICE_PROTOCOL://$CINDER_SERVICE_HOST:$CINDER_SERVICE_PORT/v3/\$(project_id)s" \
+            "$CINDER_SERVICE_PROTOCOL://$CINDER_SERVICE_HOST:$CINDER_SERVICE_PORT/v3/\$(project_id)s"
     fi
 }
 
@@ -407,7 +418,7 @@
         recreate_database cinder
 
         # Migrate cinder database
-        $CINDER_BIN_DIR/cinder-manage db sync
+        $CINDER_BIN_DIR/cinder-manage --config-file $CINDER_CONF db sync
     fi
 
     if is_service_enabled c-vol && [[ -n "$CINDER_ENABLED_BACKENDS" ]]; then
@@ -431,13 +442,6 @@
 
 # install_cinder() - Collect source and prepare
 function install_cinder {
-    # Install os-brick from git so we make sure we're testing
-    # the latest code.
-    if use_library_from_git "os-brick"; then
-        git_clone_by_name "os-brick"
-        setup_dev_lib "os-brick"
-    fi
-
     git_clone $CINDER_REPO $CINDER_DIR $CINDER_BRANCH
     setup_develop $CINDER_DIR
     if [ "$CINDER_ISCSI_HELPER" = "tgtadm" ]; then
@@ -458,6 +462,11 @@
 
 # install_cinderclient() - Collect source and prepare
 function install_cinderclient {
+    if use_library_from_git "python-brick-cinderclient-ext"; then
+        git_clone_by_name "python-brick-cinderclient-ext"
+        setup_dev_lib "python-brick-cinderclient-ext"
+    fi
+
     if use_library_from_git "python-cinderclient"; then
         git_clone_by_name "python-cinderclient"
         setup_dev_lib "python-cinderclient"
@@ -552,7 +561,7 @@
         local be be_name
         for be in ${CINDER_ENABLED_BACKENDS//,/ }; do
             be_name=${be##*:}
-            openstack volume type create --property volume_backend_name="${be_name}" ${be_name}
+            openstack --os-region-name="$REGION_NAME" volume type create --property volume_backend_name="${be_name}" ${be_name}
         done
     fi
 }
diff --git a/lib/dlm b/lib/dlm
index 74eb67e..e391535 100644
--- a/lib/dlm
+++ b/lib/dlm
@@ -93,6 +93,8 @@
     if is_dlm_enabled; then
         if is_ubuntu; then
             install_package zookeeperd
+        elif is_fedora; then
+            install_package zookeeper
         else
             die $LINENO "Don't know how to install zookeeper on this platform"
         fi
diff --git a/lib/glance b/lib/glance
index 3743e16..8d95aad 100644
--- a/lib/glance
+++ b/lib/glance
@@ -57,6 +57,7 @@
 GLANCE_SWIFT_STORE_CONF=$GLANCE_CONF_DIR/glance-swift-store.conf
 GLANCE_GLARE_CONF=$GLANCE_CONF_DIR/glance-glare.conf
 GLANCE_GLARE_PASTE_INI=$GLANCE_CONF_DIR/glance-glare-paste.ini
+GLANCE_V1_ENABLED=${GLANCE_V1_ENABLED:-True}
 
 if is_ssl_enabled_service "glance" || is_service_enabled tls-proxy; then
     GLANCE_SERVICE_PROTOCOL="https"
@@ -134,6 +135,12 @@
         iniset $GLANCE_API_CONF DEFAULT disk_formats "ami,ari,aki,vhd,vmdk,raw,qcow2,vdi,iso,ploop"
     fi
 
+    # NOTE(flaper87): To uncomment as soon as all services consuming Glance are
+    # able to consume V2 entirely.
+    if [ "$GLANCE_V1_ENABLED" != "True" ]; then
+        iniset $GLANCE_API_CONF DEFAULT enable_v1_api False
+    fi
+
     # Store specific configs
     iniset $GLANCE_API_CONF glance_store filesystem_store_datadir $GLANCE_IMAGE_DIR/
     if is_service_enabled g-glare; then
@@ -143,6 +150,13 @@
 
     iniset $GLANCE_API_CONF DEFAULT workers "$API_WORKERS"
 
+    # CORS feature support - to allow calls from Horizon by default
+    if [ -n "$GLANCE_CORS_ALLOWED_ORIGIN" ]; then
+        iniset $GLANCE_API_CONF cors allowed_origin "$GLANCE_CORS_ALLOWED_ORIGIN"
+    else
+        iniset $GLANCE_API_CONF cors allowed_origin "http://$SERVICE_HOST"
+    fi
+
     # Store the images in swift if enabled.
     if is_service_enabled s-proxy; then
         iniset $GLANCE_API_CONF glance_store default_store swift
@@ -173,8 +187,8 @@
 
         iniset $GLANCE_SWIFT_STORE_CONF ref1 key $SERVICE_PASSWORD
         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 user_domain_name $SERVICE_DOMAIN_NAME
+        iniset $GLANCE_SWIFT_STORE_CONF ref1 project_domain_name $SERVICE_DOMAIN_NAME
         iniset $GLANCE_SWIFT_STORE_CONF ref1 auth_version 3
 
         # commenting is not strictly necessary but it's confusing to have bad values in conf
@@ -288,11 +302,7 @@
 
         # required for swift access
         if is_service_enabled s-proxy; then
-
-            local glance_swift_user
-            glance_swift_user=$(get_or_create_user "glance-swift" \
-                "$SERVICE_PASSWORD" "default" "glance-swift@example.com")
-            get_or_add_user_project_role "ResellerAdmin" $glance_swift_user $SERVICE_PROJECT_NAME
+            create_service_user "glance-swift" "ResellerAdmin"
         fi
 
         get_or_create_service "glance" "image" "Glance Image Service"
@@ -338,10 +348,10 @@
     recreate_database glance
 
     # Migrate glance database
-    $GLANCE_BIN_DIR/glance-manage db_sync
+    $GLANCE_BIN_DIR/glance-manage --config-file $GLANCE_CONF_DIR/glance-api.conf db_sync
 
     # Load metadata definitions
-    $GLANCE_BIN_DIR/glance-manage db_load_metadefs
+    $GLANCE_BIN_DIR/glance-manage --config-file $GLANCE_CONF_DIR/glance-api.conf db_load_metadefs
 
     create_glance_cache_dir
 }
@@ -366,11 +376,6 @@
 
     git_clone $GLANCE_REPO $GLANCE_DIR $GLANCE_BRANCH
 
-    if is_service_enabled g-search; then
-        ${TOP_DIR}/pkg/elasticsearch.sh download
-        ${TOP_DIR}/pkg/elasticsearch.sh install
-    fi
-
     setup_develop $GLANCE_DIR
 }
 
@@ -390,7 +395,7 @@
         die $LINENO "g-api did not start"
     fi
 
-    #Start g-glare after g-reg/g-api/g-search
+    #Start g-glare after g-reg/g-api
     if is_service_enabled g-glare; then
         run_process g-glare "$GLANCE_BIN_DIR/glance-glare --config-file=$GLANCE_CONF_DIR/glance-glare.conf"
         echo "Waiting for Glare [g-glare] ($GLANCE_GLARE_HOSTPORT) to start..."
diff --git a/lib/heat b/lib/heat
index 4326321..c841e0a 100644
--- a/lib/heat
+++ b/lib/heat
@@ -156,7 +156,7 @@
     # If HEAT_DEFERRED_AUTH is unset or explicitly set to trusts, configure
     # the section for the client plugin associated with the trustee
     if [ -z "$HEAT_DEFERRED_AUTH" -o "trusts" == "$HEAT_DEFERRED_AUTH" ]; then
-        iniset $HEAT_CONF trustee auth_plugin password
+        iniset $HEAT_CONF trustee auth_type password
         iniset $HEAT_CONF trustee auth_url $KEYSTONE_AUTH_URI
         iniset $HEAT_CONF trustee username $HEAT_TRUSTEE_USER
         iniset $HEAT_CONF trustee password $HEAT_TRUSTEE_PASSWORD
@@ -241,7 +241,7 @@
     # (re)create heat database
     recreate_database heat
 
-    $HEAT_BIN_DIR/heat-manage db_sync
+    $HEAT_BIN_DIR/heat-manage --config-file $HEAT_CONF db_sync
     create_heat_cache_dir
 }
 
diff --git a/lib/horizon b/lib/horizon
index abc1f6d..0517e32 100644
--- a/lib/horizon
+++ b/lib/horizon
@@ -96,7 +96,7 @@
     _horizon_config_set $local_settings "" OPENSTACK_HOST \"${KEYSTONE_SERVICE_HOST}\"
 
     _horizon_config_set $local_settings "" OPENSTACK_API_VERSIONS {\"identity\":3}
-    _horizon_config_set $local_settings "" OPENSTACK_KEYSTONE_URL "\"${KEYSTONE_SERVICE_PROTOCOL}://${KEYSTONE_SERVICE_HOST}:${KEYSTONE_SERVICE_PORT}/v3\""
+    _horizon_config_set $local_settings "" OPENSTACK_KEYSTONE_URL "\"${KEYSTONE_SERVICE_URI}/v3\""
 
     if [ -f $SSL_BUNDLE_FILE ]; then
         _horizon_config_set $local_settings "" OPENSTACK_SSL_CACERT \"${SSL_BUNDLE_FILE}\"
diff --git a/lib/keystone b/lib/keystone
index f058114..6198e43 100644
--- a/lib/keystone
+++ b/lib/keystone
@@ -106,9 +106,14 @@
 
 # Bind hosts
 KEYSTONE_ADMIN_BIND_HOST=${KEYSTONE_ADMIN_BIND_HOST:-$KEYSTONE_SERVICE_HOST}
-# Set the tenant for service accounts in Keystone
-SERVICE_TENANT_NAME=${SERVICE_TENANT_NAME:-service}
-SERVICE_PROJECT_NAME=${SERVICE_TENANT_NAME:-service}
+
+# Set the project for service accounts in Keystone
+SERVICE_DOMAIN_NAME=${SERVICE_DOMAIN_NAME:-Default}
+SERVICE_PROJECT_NAME=${SERVICE_PROJECT_NAME:-service}
+
+# Note 2016-03 : SERVICE_TENANT_NAME is kept for backwards
+# compatibility; we should be using SERVICE_PROJECT_NAME now
+SERVICE_TENANT_NAME=${SERVICE_PROJECT_NAME:-service}
 
 # if we are running with SSL use https protocols
 if is_ssl_enabled_service "key" || is_service_enabled tls-proxy; then
@@ -117,8 +122,14 @@
 fi
 
 # complete URIs
-KEYSTONE_AUTH_URI=${KEYSTONE_AUTH_PROTOCOL}://${KEYSTONE_AUTH_HOST}:${KEYSTONE_AUTH_PORT}
-KEYSTONE_SERVICE_URI=${KEYSTONE_SERVICE_PROTOCOL}://${KEYSTONE_SERVICE_HOST}:${KEYSTONE_SERVICE_PORT}
+if [ "$KEYSTONE_DEPLOY" == "mod_wsgi" ]; then
+    # If running in Apache, use path access rather than port.
+    KEYSTONE_AUTH_URI=${KEYSTONE_AUTH_PROTOCOL}://${KEYSTONE_AUTH_HOST}/identity_v2_admin
+    KEYSTONE_SERVICE_URI=${KEYSTONE_SERVICE_PROTOCOL}://${KEYSTONE_SERVICE_HOST}/identity
+else
+    KEYSTONE_AUTH_URI=${KEYSTONE_AUTH_PROTOCOL}://${KEYSTONE_AUTH_HOST}:${KEYSTONE_AUTH_PORT}
+    KEYSTONE_SERVICE_URI=${KEYSTONE_SERVICE_PROTOCOL}://${KEYSTONE_SERVICE_HOST}:${KEYSTONE_SERVICE_PORT}
+fi
 
 # V3 URIs
 KEYSTONE_AUTH_URI_V3=$KEYSTONE_AUTH_URI/v3
@@ -235,7 +246,7 @@
     # Enable caching
     iniset $KEYSTONE_CONF cache enabled "True"
     iniset $KEYSTONE_CONF cache backend "oslo_cache.memcache_pool"
-    iniset $KEYSTONE_CONF cache memcache_servers $SERVICE_HOST:11211
+    iniset $KEYSTONE_CONF cache memcache_servers localhost:11211
 
     # Do not cache the catalog backend due to https://bugs.launchpad.net/keystone/+bug/1537617
     iniset $KEYSTONE_CONF catalog caching "False"
@@ -254,7 +265,15 @@
         # Set the service ports for a proxy to take the originals
         service_port=$KEYSTONE_SERVICE_PORT_INT
         auth_port=$KEYSTONE_AUTH_PORT_INT
+    fi
 
+    # Override the endpoints advertised by keystone (the public_endpoint and
+    # admin_endpoint) so that clients use the correct endpoint. By default, the
+    # keystone server uses the public_port and admin_port which isn't going to
+    # work when you want to use a different port (in the case of proxy), or you
+    # don't want the port (in the case of putting keystone on a path in
+    # apache).
+    if is_service_enabled tls-proxy || [ "$KEYSTONE_DEPLOY" == "mod_wsgi" ]; then
         iniset $KEYSTONE_CONF DEFAULT public_endpoint $KEYSTONE_SERVICE_URI
         iniset $KEYSTONE_CONF DEFAULT admin_endpoint $KEYSTONE_AUTH_URI
     fi
@@ -299,10 +318,10 @@
         fi
 
         iniset "$KEYSTONE_PUBLIC_UWSGI_FILE" uwsgi wsgi-file "$KEYSTONE_BIN_DIR/keystone-wsgi-public"
-        iniset "$KEYSTONE_PUBLIC_UWSGI_FILE" uwsgi threads $(nproc)
+        iniset "$KEYSTONE_PUBLIC_UWSGI_FILE" uwsgi processes $(nproc)
 
         iniset "$KEYSTONE_ADMIN_UWSGI_FILE" uwsgi wsgi-file "$KEYSTONE_BIN_DIR/keystone-wsgi-admin"
-        iniset "$KEYSTONE_ADMIN_UWSGI_FILE" uwsgi threads $API_WORKERS
+        iniset "$KEYSTONE_ADMIN_UWSGI_FILE" uwsgi processes $API_WORKERS
 
         # Common settings
         for file in "$KEYSTONE_PUBLIC_UWSGI_FILE" "$KEYSTONE_ADMIN_UWSGI_FILE"; do
@@ -329,13 +348,13 @@
     # 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_domain_name Default
     iniset $KEYSTONE_CONF resource admin_project_name admin
 }
 
 # create_keystone_accounts() - Sets up common required keystone accounts
 
-# Tenant               User       Roles
+# Project              User       Roles
 # ------------------------------------------------------------------
 # admin                admin      admin
 # service              --         --
@@ -348,7 +367,7 @@
 # alt_demo             alt_demo   Member, anotherrole
 # invisible_to_admin   demo       Member
 
-# Group                Users            Roles                 Tenant
+# Group                Users            Roles                 Project
 # ------------------------------------------------------------------
 # admins               admin            admin                 admin
 # nonadmins            demo, alt_demo   Member, anotherrole   demo, alt_demo
@@ -360,8 +379,8 @@
     # The keystone bootstrapping process (performed via keystone-manage bootstrap)
     # creates an admin user, admin role and admin project. As a sanity check
     # we exercise the CLI to retrieve the IDs for these values.
-    local admin_tenant
-    admin_tenant=$(openstack project show "admin" -f value -c id)
+    local admin_project
+    admin_project=$(openstack project show "admin" -f value -c id)
     local admin_user
     admin_user=$(openstack user show "admin" -f value -c id)
     local admin_role
@@ -370,14 +389,15 @@
     get_or_add_user_domain_role $admin_role $admin_user default
 
     # Create service project/role
-    get_or_create_project "$SERVICE_PROJECT_NAME" default
+    get_or_create_domain "$SERVICE_DOMAIN_NAME"
+    get_or_create_project "$SERVICE_PROJECT_NAME" "$SERVICE_DOMAIN_NAME"
 
     # Service role, so service users do not have to be admins
     get_or_create_role service
 
     # The ResellerAdmin role is used by Nova and Ceilometer so we need to keep it.
-    # The admin role in swift allows a user to act as an admin for their tenant,
-    # but ResellerAdmin is needed for a user to act as any tenant. The name of this
+    # The admin role in swift allows a user to act as an admin for their project,
+    # but ResellerAdmin is needed for a user to act as any project. The name of this
     # role is also configurable in swift-proxy.conf
     get_or_create_role ResellerAdmin
 
@@ -390,32 +410,32 @@
     local another_role
     another_role=$(get_or_create_role "anotherrole")
 
-    # invisible tenant - admin can't see this one
-    local invis_tenant
-    invis_tenant=$(get_or_create_project "invisible_to_admin" default)
+    # invisible project - admin can't see this one
+    local invis_project
+    invis_project=$(get_or_create_project "invisible_to_admin" default)
 
     # demo
-    local demo_tenant
-    demo_tenant=$(get_or_create_project "demo" default)
+    local demo_project
+    demo_project=$(get_or_create_project "demo" default)
     local demo_user
     demo_user=$(get_or_create_user "demo" \
         "$ADMIN_PASSWORD" "default" "demo@example.com")
 
-    get_or_add_user_project_role $member_role $demo_user $demo_tenant
-    get_or_add_user_project_role $admin_role $admin_user $demo_tenant
-    get_or_add_user_project_role $another_role $demo_user $demo_tenant
-    get_or_add_user_project_role $member_role $demo_user $invis_tenant
+    get_or_add_user_project_role $member_role $demo_user $demo_project
+    get_or_add_user_project_role $admin_role $admin_user $demo_project
+    get_or_add_user_project_role $another_role $demo_user $demo_project
+    get_or_add_user_project_role $member_role $demo_user $invis_project
 
     # alt_demo
-    local alt_demo_tenant
-    alt_demo_tenant=$(get_or_create_project "alt_demo" default)
+    local alt_demo_project
+    alt_demo_project=$(get_or_create_project "alt_demo" default)
     local alt_demo_user
     alt_demo_user=$(get_or_create_user "alt_demo" \
         "$ADMIN_PASSWORD" "default" "alt_demo@example.com")
 
-    get_or_add_user_project_role $member_role $alt_demo_user $alt_demo_tenant
-    get_or_add_user_project_role $admin_role $admin_user $alt_demo_tenant
-    get_or_add_user_project_role $another_role $alt_demo_user $alt_demo_tenant
+    get_or_add_user_project_role $member_role $alt_demo_user $alt_demo_project
+    get_or_add_user_project_role $admin_role $admin_user $alt_demo_project
+    get_or_add_user_project_role $another_role $alt_demo_user $alt_demo_project
 
     # groups
     local admin_group
@@ -425,11 +445,11 @@
     non_admin_group=$(get_or_create_group "nonadmins" \
         "default" "non-admin group")
 
-    get_or_add_group_project_role $member_role $non_admin_group $demo_tenant
-    get_or_add_group_project_role $another_role $non_admin_group $demo_tenant
-    get_or_add_group_project_role $member_role $non_admin_group $alt_demo_tenant
-    get_or_add_group_project_role $another_role $non_admin_group $alt_demo_tenant
-    get_or_add_group_project_role $admin_role $admin_group $admin_tenant
+    get_or_add_group_project_role $member_role $non_admin_group $demo_project
+    get_or_add_group_project_role $another_role $non_admin_group $demo_project
+    get_or_add_group_project_role $member_role $non_admin_group $alt_demo_project
+    get_or_add_group_project_role $another_role $non_admin_group $alt_demo_project
+    get_or_add_group_project_role $admin_role $admin_group $admin_project
 }
 
 # Create a user that is capable of verifying keystone tokens for use with auth_token middleware.
@@ -442,9 +462,8 @@
 function create_service_user {
     local role=${2:-service}
 
-    local user
-    user=$(get_or_create_user "$1" "$SERVICE_PASSWORD" default)
-    get_or_add_user_project_role "$role" "$user" "$SERVICE_PROJECT_NAME"
+    get_or_create_user "$1" "$SERVICE_PASSWORD" "$SERVICE_DOMAIN_NAME"
+    get_or_add_user_project_role "$role" "$1" "$SERVICE_PROJECT_NAME" "$SERVICE_DOMAIN_NAME" "$SERVICE_DOMAIN_NAME"
 }
 
 # Configure the service to use the auth token middleware.
@@ -464,9 +483,9 @@
     iniset $conf_file $section auth_url $KEYSTONE_AUTH_URI
     iniset $conf_file $section username $admin_user
     iniset $conf_file $section password $SERVICE_PASSWORD
-    iniset $conf_file $section user_domain_id default
+    iniset $conf_file $section user_domain_name "$SERVICE_DOMAIN_NAME"
     iniset $conf_file $section project_name $SERVICE_PROJECT_NAME
-    iniset $conf_file $section project_domain_id default
+    iniset $conf_file $section project_domain_name "$SERVICE_DOMAIN_NAME"
 
     iniset $conf_file $section auth_uri $KEYSTONE_SERVICE_URI
     iniset $conf_file $section cafile $SSL_BUNDLE_FILE
@@ -484,16 +503,16 @@
     recreate_database keystone
 
     # Initialize keystone database
-    $KEYSTONE_BIN_DIR/keystone-manage db_sync
+    $KEYSTONE_BIN_DIR/keystone-manage --config-file $KEYSTONE_CONF db_sync
 
     if [[ "$KEYSTONE_TOKEN_FORMAT" == "pki" || "$KEYSTONE_TOKEN_FORMAT" == "pkiz" ]]; then
         # Set up certificates
         rm -rf $KEYSTONE_CONF_DIR/ssl
-        $KEYSTONE_BIN_DIR/keystone-manage pki_setup
+        $KEYSTONE_BIN_DIR/keystone-manage --config-file $KEYSTONE_CONF pki_setup
     fi
     if [[ "$KEYSTONE_TOKEN_FORMAT" == "fernet" ]]; then
         rm -rf "$KEYSTONE_CONF_DIR/fernet-keys/"
-        $KEYSTONE_BIN_DIR/keystone-manage fernet_setup
+        $KEYSTONE_BIN_DIR/keystone-manage --config-file $KEYSTONE_CONF fernet_setup
     fi
 }
 
@@ -577,7 +596,14 @@
     # Check that the keystone service is running. Even if the tls tunnel
     # should be enabled, make sure the internal port is checked using
     # unencryted traffic at this point.
-    if ! wait_for_service $SERVICE_TIMEOUT $auth_protocol://$KEYSTONE_SERVICE_HOST:$service_port/v$IDENTITY_API_VERSION/; then
+    # If running in Apache, use the path rather than port.
+
+    local service_uri=$auth_protocol://$KEYSTONE_SERVICE_HOST:$service_port/v$IDENTITY_API_VERSION/
+    if [ "$KEYSTONE_DEPLOY" == "mod_wsgi" ]; then
+        service_uri=$auth_protocol://$KEYSTONE_SERVICE_HOST/identity/v$IDENTITY_API_VERSION/
+    fi
+
+    if ! wait_for_service $SERVICE_TIMEOUT $service_uri; then
         die $LINENO "keystone did not start"
     fi
 
@@ -620,8 +646,8 @@
         --bootstrap-service-name keystone \
         --bootstrap-region-id "$REGION_NAME" \
         --bootstrap-admin-url "$KEYSTONE_AUTH_URI" \
-        --bootstrap-public-url "$KEYSTONE_SERVICE_PROTOCOL://$KEYSTONE_SERVICE_HOST:$KEYSTONE_SERVICE_PORT" \
-        --bootstrap-internal-url "$KEYSTONE_SERVICE_PROTOCOL://$KEYSTONE_SERVICE_HOST:$KEYSTONE_SERVICE_PORT"
+        --bootstrap-public-url "$KEYSTONE_SERVICE_URI" \
+        --bootstrap-internal-url "$KEYSTONE_SERVICE_URI"
 }
 
 # Restore xtrace
diff --git a/lib/neutron b/lib/neutron
new file mode 100644
index 0000000..f36e564
--- /dev/null
+++ b/lib/neutron
@@ -0,0 +1,572 @@
+#!/bin/bash
+#
+# lib/neutron
+# Install and start **Neutron** network services
+
+# Dependencies:
+#
+# ``functions`` file
+# ``DEST`` must be defined
+
+# ``stack.sh`` calls the entry points in this order:
+#
+# - is_XXXX_enabled
+# - install_XXXX
+# - configure_XXXX
+# - init_XXXX
+# - start_XXXX
+# - stop_XXXX
+# - cleanup_XXXX
+
+# Save trace setting
+XTRACE=$(set +o | grep xtrace)
+set +o xtrace
+
+# Defaults
+# --------
+
+# Set up default directories
+GITDIR["python-neutronclient"]=$DEST/python-neutronclient
+
+NEUTRON_AGENT=${NEUTRON_AGENT:-openvswitch}
+NEUTRON_DIR=$DEST/neutron
+NEUTRON_AUTH_CACHE_DIR=${NEUTRON_AUTH_CACHE_DIR:-/var/cache/neutron}
+
+NEUTRON_BIN_DIR=$(get_python_exec_prefix)
+NEUTRON_DHCP_BINARY="neutron-dhcp-agent"
+
+NEUTRON_CONF_DIR=/etc/neutron
+NEUTRON_CONF=$NEUTRON_CONF_DIR/neutron.conf
+NEUTRON_META_CONF=$NEUTRON_CONF_DIR/metadata_agent.ini
+
+NEUTRON_DHCP_CONF=$NEUTRON_CONF_DIR/dhcp_agent.ini
+NEUTRON_L3_CONF=$NEUTRON_CONF_DIR/l3_agent.ini
+NEUTRON_AGENT_CONF=$NEUTRON_CONF_DIR/
+
+NEUTRON_STATE_PATH=${NEUTRON_STATE_PATH:=$DATA_DIR/neutron}
+NEUTRON_AUTH_CACHE_DIR=${NEUTRON_AUTH_CACHE_DIR:-/var/cache/neutron}
+
+# By default, use the ML2 plugin
+NEUTRON_PLUGIN=${NEUTRON_PLUGIN:-ml2}
+NEUTRON_PLUGIN_CONF_FILENAME=${NEUTRON_PLUGIN_CONF_FILENAME:-ml2_conf.ini}
+NEUTRON_PLUGIN_CONF_PATH=$NEUTRON_CONF_DIR/plugins/$NEUTRON_PLUGIN
+NEUTRON_PLUGIN_CONF=$NEUTRON_PLUGIN_CONF_PATH/$NEUTRON_PLUGIN_CONF_FILENAME
+
+NEUTRON_AGENT_BINARY=${NEUTRON_AGENT_BINARY:-neutron-$NEUTRON_AGENT-agent}
+NEUTRON_L3_BINARY=${NEUTRON_L3_BINARY:-neutron-l3-agent}
+NEUTRON_META_BINARY=${NEUTRON_META_BINARY:-neutron-metadata-agent}
+
+# Public facing bits
+if is_ssl_enabled_service "neutron" || is_service_enabled tls-proxy; then
+    NEUTRON_SERVICE_PROTOCOL="https"
+fi
+NEUTRON_SERVICE_HOST=${NEUTRON_SERVICE_HOST:-$SERVICE_HOST}
+NEUTRON_SERVICE_PORT=${NEUTRON_SERVICE_PORT:-9696}
+NEUTRON_SERVICE_PORT_INT=${NEUTRON_SERVICE_PORT_INT:-19696}
+NEUTRON_SERVICE_PROTOCOL=${NEUTRON_SERVICE_PROTOCOL:-$SERVICE_PROTOCOL}
+
+NEUTRON_AUTH_STRATEGY=${NEUTRON_AUTH_STRATEGY:-keystone}
+NEUTRON_ROOTWRAP=$(get_rootwrap_location neutron)
+NEUTRON_ROOTWRAP_CONF_FILE=$NEUTRON_CONF_DIR/rootwrap.conf
+NEUTRON_ROOTWRAP_DAEMON_CMD="sudo $NEUTRON_ROOTWRAP-daemon $NEUTRON_ROOTWRAP_CONF_FILE"
+
+# Add all enabled config files to a single config arg
+NEUTRON_CONFIG_ARG=${NEUTRON_CONFIG_ARG:-""}
+
+# Functions
+# ---------
+
+# Test if any Neutron services are enabled
+# is_neutron_enabled
+function is_neutron_enabled {
+    [[ ,${ENABLED_SERVICES} =~ ,"neutron-" || ,${ENABLED_SERVICES} =~ ,"q-" ]] && return 0
+    return 1
+}
+
+# Test if any Neutron services are enabled
+# is_neutron_enabled
+function is_neutron_legacy_enabled {
+    [[ ,${ENABLED_SERVICES} =~ ,"q-" ]] && return 0
+    return 1
+}
+
+# cleanup_neutron() - Remove residual data files, anything left over from previous
+# runs that a clean run would need to clean up
+function cleanup_neutron_new {
+    source $TOP_DIR/lib/neutron_plugins/${NEUTRON_AGENT}_agent
+    if is_neutron_ovs_base_plugin; then
+        neutron_ovs_base_cleanup
+    fi
+
+    if [[ $NEUTRON_AGENT == "linuxbridge" ]]; then
+        neutron_lb_cleanup
+    fi
+    # delete all namespaces created by neutron
+    for ns in $(sudo ip netns list | grep -o -E '(qdhcp|qrouter|qlbaas|fip|snat)-[0-9a-f-]*'); do
+        sudo ip netns delete ${ns}
+    done
+}
+
+# configure_neutron() - Set config files, create data dirs, etc
+function configure_neutron_new {
+    sudo install -d -o $STACK_USER $NEUTRON_CONF_DIR
+
+    (cd $NEUTRON_DIR && exec ./tools/generate_config_file_samples.sh)
+
+    cp $NEUTRON_DIR/etc/neutron.conf.sample $NEUTRON_CONF
+
+    configure_neutron_rootwrap
+
+    mkdir -p $NEUTRON_PLUGIN_CONF_PATH
+
+    cp $NEUTRON_DIR/etc/neutron/plugins/$NEUTRON_PLUGIN/$NEUTRON_PLUGIN_CONF_FILENAME.sample $NEUTRON_PLUGIN_CONF
+
+    iniset $NEUTRON_CONF database connection `database_connection_url neutron`
+    iniset $NEUTRON_CONF DEFAULT state_path $NEUTRON_STATE_PATH
+    iniset $NEUTRON_CONF oslo_concurrency lock_path $NEUTRON_STATE_PATH/lock
+    iniset $NEUTRON_CONF DEFAULT use_syslog $SYSLOG
+
+    iniset $NEUTRON_CONF DEFAULT debug True
+
+    iniset_rpc_backend neutron $NEUTRON_CONF
+
+    # Neutron API server & Neutron plugin
+    if is_service_enabled neutron-api; then
+        local policy_file=$NEUTRON_CONF_DIR/policy.json
+        cp $NEUTRON_DIR/etc/policy.json $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' $policy_file
+
+        cp $NEUTRON_DIR/etc/api-paste.ini $NEUTRON_CONF_DIR/api-paste.ini
+
+        iniset $NEUTRON_CONF DEFAULT core_plugin ml2
+
+        iniset $NEUTRON_CONF DEFAULT policy_file $policy_file
+        iniset $NEUTRON_CONF DEFAULT allow_overlapping_ips True
+
+        iniset $NEUTRON_CONF DEFAULT auth_strategy $NEUTRON_AUTH_STRATEGY
+        configure_auth_token_middleware $NEUTRON_CONF neutron $NEUTRON_AUTH_CACHE_DIR keystone_authtoken
+
+        # Configuration for neutron notifations to nova.
+        iniset $NEUTRON_CONF DEFAULT notify_nova_on_port_status_changes $Q_NOTIFY_NOVA_PORT_STATUS_CHANGES
+        iniset $NEUTRON_CONF DEFAULT notify_nova_on_port_data_changes $Q_NOTIFY_NOVA_PORT_DATA_CHANGES
+
+        iniset $NEUTRON_CONF nova auth_type password
+        iniset $NEUTRON_CONF nova auth_url "$KEYSTONE_SERVICE_PROTOCOL://$KEYSTONE_SERVICE_HOST:$KEYSTONE_AUTH_PORT/v3"
+        iniset $NEUTRON_CONF nova username nova
+        iniset $NEUTRON_CONF nova password $SERVICE_PASSWORD
+        iniset $NEUTRON_CONF nova user_domain_id default
+        iniset $NEUTRON_CONF nova project_name $SERVICE_TENANT_NAME
+        iniset $NEUTRON_CONF nova project_domain_id default
+        iniset $NEUTRON_CONF nova region_name $REGION_NAME
+
+        # Configure VXLAN
+        # TODO(sc68cal) not hardcode?
+        iniset $NEUTRON_PLUGIN_CONF ml2 tenant_network_types vxlan
+        iniset $NEUTRON_PLUGIN_CONF ml2 type_drivers vxlan
+        iniset $NEUTRON_PLUGIN_CONF ml2 mechanism_drivers openvswitch,linuxbridge
+        iniset $NEUTRON_PLUGIN_CONF ml2_type_vxlan vni_ranges 1001:2000
+    fi
+
+    # Neutron OVS or LB agent
+    if is_service_enabled neutron-agent; then
+        iniset $NEUTRON_PLUGIN_CONF agent tunnel_types vxlan
+        iniset $NEUTRON_PLUGIN_CONF DEFAULT debug True
+
+        # Configure the neutron agent
+        if [[ $NEUTRON_AGENT == "linuxbridge" ]]; then
+            iniset $NEUTRON_PLUGIN_CONF securitygroup iptables
+            iniset $NEUTRON_PLUGIN_CONF vxlan local_ip $HOST_IP
+        else
+            iniset $NEUTRON_PLUGIN_CONF securitygroup iptables_hybrid
+            iniset $NEUTRON_PLUGIN_CONF ovs local_ip $HOST_IP
+        fi
+    fi
+
+    # DHCP Agent
+    if is_service_enabled neutron-dhcp; then
+        cp $NEUTRON_DIR/etc/dhcp_agent.ini.sample $NEUTRON_DHCP_CONF
+
+        iniset $NEUTRON_DHCP_CONF DEFAULT debug True
+        # make it so we have working DNS from guests
+        iniset $NEUTRON_DHCP_CONF DEFAULT dnsmasq_local_resolv True
+
+        iniset $NEUTRON_DHCP_CONF agent root_helper_daemon "$NEUTRON_ROOTWRAP_DAEMON_CMD"
+        iniset $NEUTRON_DHCP_CONF DEFAULT interface_driver $NEUTRON_AGENT
+        neutron_plugin_configure_dhcp_agent $NEUTRON_DHCP_CONF
+    fi
+
+    if is_service_enabled neutron-l3; then
+        cp $NEUTRON_DIR/etc/l3_agent.ini.sample $NEUTRON_L3_CONF
+        iniset $NEUTRON_L3_CONF DEFAULT interface_driver $NEUTRON_AGENT
+        iniset $NEUTRON_CONF DEFAULT service_plugins router
+        iniset $NEUTRON_L3_CONF agent root_helper_daemon "$NEUTRON_ROOTWRAP_DAEMON_CMD"
+        iniset $NEUTRON_L3_CONF DEFAULT debug True
+        neutron_plugin_configure_l3_agent $NEUTRON_L3_CONF
+    fi
+
+    # Metadata
+    if is_service_enabled neutron-metadata-agent; then
+        cp $NEUTRON_DIR/etc/metadata_agent.ini.sample $NEUTRON_META_CONF
+
+        iniset $NEUTRON_META_CONF DEFAULT debug True
+        iniset $NEUTRON_META_CONF DEFAULT nova_metadata_ip $SERVICE_HOST
+        iniset $NEUTRON_META_CONF agent root_helper_daemon "$NEUTRON_ROOTWRAP_DAEMON_CMD"
+
+        # TODO(dtroyer): remove the v2.0 hard code below
+        iniset $NEUTRON_META_CONF DEFAULT auth_url $KEYSTONE_SERVICE_URI/v2.0
+        configure_auth_token_middleware $NEUTRON_META_CONF neutron $NEUTRON_AUTH_CACHE_DIR DEFAULT
+    fi
+
+    # Format logging
+    if [ "$LOG_COLOR" == "True" ] && [ "$SYSLOG" == "False" ]; then
+        setup_colorized_logging $NEUTRON_CONF DEFAULT project_id
+    else
+        # Show user_name and project_name by default
+        iniset $NEUTRON_CONF DEFAULT logging_context_format_string "%(asctime)s.%(msecs)03d %(levelname)s %(name)s [%(request_id)s %(user_name)s %(project_name)s] %(instance)s%(message)s"
+    fi
+
+    if is_service_enabled tls-proxy; then
+        # Set the service port for a proxy to take the original
+        iniset $NEUTRON_CONF DEFAULT bind_port "$NEUTRON_SERVICE_PORT_INT"
+    fi
+
+    if is_ssl_enabled_service "nova"; then
+        iniset $NEUTRON_CONF nova cafile $SSL_BUNDLE_FILE
+    fi
+
+    if is_ssl_enabled_service "neutron"; then
+        ensure_certificates NEUTRON
+
+        iniset $NEUTRON_CONF DEFAULT use_ssl True
+        iniset $NEUTRON_CONF DEFAULT ssl_cert_file "$NEUTRON_SSL_CERT"
+        iniset $NEUTRON_CONF DEFAULT ssl_key_file "$NEUTRON_SSL_KEY"
+    fi
+
+    # Metering
+    if is_service_enabled neutron-metering; then
+        source $TOP_DIR/lib/neutron_plugins/services/metering
+        neutron_agent_metering_configure_common
+        neutron_agent_metering_configure_agent
+        # TODO(sc68cal) hack because we don't pass around
+        # $Q_SERVICE_PLUGIN_CLASSES like -legacy does
+        local plugins=""
+        plugins=$(iniget $NEUTRON_CONF DEFAULT service_plugins)
+        plugins+=",metering"
+        iniset $NEUTRON_CONF DEFAULT service_plugins $plugins
+    fi
+
+}
+
+# configure_neutron_rootwrap() - configure Neutron's rootwrap
+function configure_neutron_rootwrap {
+    # Set the paths of certain binaries
+    neutron_rootwrap=$(get_rootwrap_location neutron)
+
+    # Specify ``rootwrap.conf`` as first parameter to neutron-rootwrap
+    local rootwrap_sudoer_cmd="${neutron_rootwrap} $NEUTRON_CONF_DIR/rootwrap.conf"
+
+    # Deploy new rootwrap filters files (owned by root).
+    # Wipe any existing rootwrap.d files first
+    if [[ -d $NEUTRON_CONF_DIR/rootwrap.d ]]; then
+        sudo rm -rf $NEUTRON_CONF_DIR/rootwrap.d
+    fi
+
+    # Deploy filters to /etc/neutron/rootwrap.d
+    sudo install -d -o root -g root -m 755 $NEUTRON_CONF_DIR/rootwrap.d
+    sudo install -o root -g root -m 644 $NEUTRON_DIR/etc/neutron/rootwrap.d/*.filters $NEUTRON_CONF_DIR/rootwrap.d
+
+    # Set up ``rootwrap.conf``, pointing to ``$NEUTRON_CONF_DIR/rootwrap.d``
+    sudo install -o root -g root -m 644 $NEUTRON_DIR/etc/rootwrap.conf $NEUTRON_CONF_DIR
+    sudo sed -e "s:^filters_path=.*$:filters_path=$NEUTRON_CONF_DIR/rootwrap.d:" -i $NEUTRON_CONF_DIR/rootwrap.conf
+
+    # Set up the rootwrap sudoers for Neutron
+    tempfile=`mktemp`
+    echo "$STACK_USER ALL=(root) NOPASSWD: $rootwrap_sudoer_cmd *" >$tempfile
+    chmod 0440 $tempfile
+    sudo chown root:root $tempfile
+    sudo mv $tempfile /etc/sudoers.d/neutron-rootwrap
+}
+
+# Make Neutron-required changes to nova.conf
+function configure_neutron_nova_new {
+    iniset $NOVA_CONF DEFAULT use_neutron True
+    iniset $NOVA_CONF neutron auth_type "password"
+    iniset $NOVA_CONF neutron auth_url "$KEYSTONE_SERVICE_PROTOCOL://$KEYSTONE_SERVICE_HOST:$KEYSTONE_AUTH_PORT/v3"
+    iniset $NOVA_CONF neutron username neutron
+    iniset $NOVA_CONF neutron password "$SERVICE_PASSWORD"
+    iniset $NOVA_CONF neutron user_domain_name "Default"
+    iniset $NOVA_CONF neutron project_name "$SERVICE_TENANT_NAME"
+    iniset $NOVA_CONF neutron project_domain_name "Default"
+    iniset $NOVA_CONF neutron auth_strategy $NEUTRON_AUTH_STRATEGY
+    iniset $NOVA_CONF neutron region_name "$REGION_NAME"
+    iniset $NOVA_CONF neutron url $NEUTRON_SERVICE_PROTOCOL://$NEUTRON_SERVICE_HOST:$NEUTRON_SERVICE_PORT
+
+    iniset $NOVA_CONF DEFAULT firewall_driver nova.virt.firewall.NoopFirewallDriver
+
+    if is_service_enabled neutron-metadata-agent; then
+        iniset $NOVA_CONF neutron service_metadata_proxy "True"
+    fi
+
+}
+
+# Tenant               User       Roles
+# ------------------------------------------------------------------
+# service              neutron    admin        # if enabled
+
+# create_neutron_accounts() - Create required service accounts
+function create_neutron_accounts_new {
+    if [[ "$ENABLED_SERVICES" =~ "neutron-api" ]]; then
+
+        create_service_user "neutron"
+
+        neutron_service=$(get_or_create_service "neutron" \
+            "network" "Neutron Service")
+        get_or_create_endpoint $neutron_service \
+            "$REGION_NAME" \
+            "$NEUTRON_SERVICE_PROTOCOL://$NEUTRON_SERVICE_HOST:$NEUTRON_SERVICE_PORT/" \
+            "$NEUTRON_SERVICE_PROTOCOL://$NEUTRON_SERVICE_HOST:$NEUTRON_SERVICE_PORT/" \
+            "$NEUTRON_SERVICE_PROTOCOL://$NEUTRON_SERVICE_HOST:$NEUTRON_SERVICE_PORT/"
+    fi
+}
+
+# create_neutron_cache_dir() - Part of the init_neutron() process
+function create_neutron_cache_dir {
+    # Create cache dir
+    sudo install -d -o $STACK_USER $NEUTRON_AUTH_CACHE_DIR
+    rm -f $NEUTRON_AUTH_CACHE_DIR/*
+}
+
+# init_neutron() - Initialize databases, etc.
+function init_neutron_new {
+
+    recreate_database neutron
+
+    # Run Neutron db migrations
+    $NEUTRON_BIN_DIR/neutron-db-manage $NEUTRON_CONFIG_ARG upgrade heads
+
+    create_neutron_cache_dir
+}
+
+# install_neutron() - Collect source and prepare
+function install_neutron_new {
+    git_clone $NEUTRON_REPO $NEUTRON_DIR $NEUTRON_BRANCH
+    setup_develop $NEUTRON_DIR
+
+    # Install neutron-lib from git so we make sure we're testing
+    # the latest code.
+    if use_library_from_git "neutron-lib"; then
+        git_clone_by_name "neutron-lib"
+        setup_dev_lib "neutron-lib"
+    fi
+
+    # L3 service requires radvd
+    if is_service_enabled neutron-l3; then
+        install_package radvd
+    fi
+
+    if is_service_enabled neutron-agent neutron-dhcp neutron-l3; then
+        #TODO(sc68cal) - kind of ugly
+        source $TOP_DIR/lib/neutron_plugins/${NEUTRON_AGENT}_agent
+        neutron_plugin_install_agent_packages
+    fi
+
+}
+
+# install_neutronclient() - Collect source and prepare
+function install_neutronclient {
+    if use_library_from_git "python-neutronclient"; then
+        git_clone_by_name "python-neutronclient"
+        setup_dev_lib "python-neutronclient"
+        sudo install -D -m 0644 -o $STACK_USER {${GITDIR["python-neutronclient"]}/tools/,/etc/bash_completion.d/}neutron.bash_completion
+    fi
+}
+
+# start_neutron_api() - Start the API process ahead of other things
+function start_neutron_api {
+    local service_port=$NEUTRON_SERVICE_PORT
+    local service_protocol=$NEUTRON_SERVICE_PROTOCOL
+    if is_service_enabled tls-proxy; then
+        service_port=$NEUTRON_SERVICE_PORT_INT
+        service_protocol="http"
+    fi
+
+    # Start the Neutron service
+    # TODO(sc68cal) Stop hard coding this
+    run_process neutron-api "$NEUTRON_BIN_DIR/neutron-server --config-file $NEUTRON_CONF --config-file $NEUTRON_PLUGIN_CONF"
+
+    if is_ssl_enabled_service "neutron"; then
+        ssl_ca="--ca-certificate=${SSL_BUNDLE_FILE}"
+        local testcmd="wget ${ssl_ca} --no-proxy -q -O- $service_protocol://$NEUTRON_SERVICE_HOST:$service_port"
+        test_with_retry "$testcmd" "Neutron did not start" $SERVICE_TIMEOUT
+    else
+        if ! wait_for_service $SERVICE_TIMEOUT $service_protocol://$NEUTRON_SERVICE_HOST:$service_port; then
+            die $LINENO "neutron-api did not start"
+        fi
+    fi
+
+
+    # Start proxy if enabled
+    if is_service_enabled tls-proxy; then
+        start_tls_proxy '*' $NEUTRON_SERVICE_PORT $NEUTRON_SERVICE_HOST $NEUTRON_SERVICE_PORT_INT &
+    fi
+}
+
+# start_neutron() - Start running processes, including screen
+function start_neutron_new {
+    _set_config_files
+
+    # Start up the neutron agents if enabled
+    # TODO(sc68cal) Make this pluggable so different DevStack plugins for different Neutron plugins
+    # can resolve the $NEUTRON_AGENT_BINARY
+    if is_service_enabled neutron-agent; then
+        run_process neutron-agent "$NEUTRON_BIN_DIR/$NEUTRON_AGENT_BINARY $NEUTRON_CONFIG_ARG"
+    fi
+    if is_service_enabled neutron-dhcp; then
+        neutron_plugin_configure_dhcp_agent $NEUTRON_DHCP_CONF
+        run_process neutron-dhcp "$NEUTRON_BIN_DIR/$NEUTRON_DHCP_BINARY $NEUTRON_CONFIG_ARG"
+    fi
+    if is_service_enabled neutron-l3; then
+        run_process neutron-l3 "$NEUTRON_BIN_DIR/$NEUTRON_L3_BINARY $NEUTRON_CONFIG_ARG"
+    fi
+    # XXX(sc68cal) - Here's where plugins can wire up their own networks instead
+    # of the code in lib/neutron_plugins/services/l3
+    if type -p neutron_plugin_create_initial_networks > /dev/null; then
+        neutron_plugin_create_initial_networks
+    else
+        # XXX(sc68cal) Load up the built in Neutron networking code and build a topology
+        source $TOP_DIR/lib/neutron_plugins/services/l3
+        # Create the networks using servic
+        create_neutron_initial_network
+    fi
+    if is_service_enabled neutron-metadata-agent; then
+        run_process neutron-metadata-agent "$NEUTRON_BIN_DIR/$NEUTRON_META_BINARY $NEUTRON_CONFIG_ARG"
+    fi
+
+    if is_service_enabled neutron-metering; then
+        run_process neutron-metering "$AGENT_METERING_BINARY --config-file $NEUTRON_CONF --config-file $METERING_AGENT_CONF_FILENAME"
+    fi
+}
+
+# stop_neutron() - Stop running processes (non-screen)
+function stop_neutron_new {
+    for serv in neutron-api neutron-agent neutron-l3; do
+        stop_process $serv
+    done
+
+    if is_service_enabled neutron-dhcp; then
+        stop_process neutron-dhcp
+        pid=$(ps aux | awk '/[d]nsmasq.+interface=(tap|ns-)/ { print $2 }')
+        [ ! -z "$pid" ] && sudo kill -9 $pid
+    fi
+
+    if is_service_enabled neutron-metadata-agent; then
+        sudo pkill -9 -f neutron-ns-metadata-proxy || :
+        stop_process neutron-metadata-agent
+    fi
+}
+
+# Compile the lost of enabled config files
+function _set_config_files {
+
+    NEUTRON_CONFIG_ARG+=" --config-file $NEUTRON_CONF"
+
+    #TODO(sc68cal) OVS and LB agent uses settings in NEUTRON_PLUGIN_CONF (ml2_conf.ini) but others may not
+    if is_service_enabled neutron-agent; then
+        NEUTRON_CONFIG_ARG+=" --config-file $NEUTRON_PLUGIN_CONF"
+    fi
+
+    if is_service_enabled neutron-dhcp; then
+        NEUTRON_CONFIG_ARG+=" --config-file $NEUTRON_DHCP_CONF"
+    fi
+
+    if is_service_enabled neutron-l3; then
+        NEUTRON_CONFIG_ARG+=" --config-file $NEUTRON_L3_CONF"
+    fi
+
+    if is_service_enabled neutron-metadata-agent; then
+        NEUTRON_CONFIG_ARG+=" --config-file $NEUTRON_META_CONF"
+    fi
+
+}
+
+# Dispatch functions
+# These are needed for compatibility between the old and new implementations
+# where there are function name overlaps.  These will be removed when
+# neutron-legacy is removed.
+# TODO(sc68cal) Remove when neutron-legacy is no more.
+function cleanup_neutron {
+    if is_neutron_legacy_enabled; then
+        # Call back to old function
+        cleanup_mutnauq "$@"
+    else
+        cleanup_neutron_new "$@"
+    fi
+}
+
+function configure_neutron {
+    if is_neutron_legacy_enabled; then
+        # Call back to old function
+        configure_mutnauq "$@"
+    else
+        configure_neutron_new "$@"
+    fi
+}
+
+function configure_neutron_nova {
+    if is_neutron_legacy_enabled; then
+        # Call back to old function
+        create_nova_conf_neutron "$@"
+    else
+        configure_neutron_nova_new "$@"
+    fi
+}
+
+function create_neutron_accounts {
+    if is_neutron_legacy_enabled; then
+        # Call back to old function
+        create_mutnauq_accounts "$@"
+    else
+        create_neutron_accounts_new "$@"
+    fi
+}
+
+function init_neutron {
+    if is_neutron_legacy_enabled; then
+        # Call back to old function
+        init_mutnauq "$@"
+    else
+        init_neutron_new "$@"
+    fi
+}
+
+function install_neutron {
+    if is_neutron_legacy_enabled; then
+        # Call back to old function
+        install_mutnauq "$@"
+    else
+        install_neutron_new "$@"
+    fi
+}
+
+function start_neutron {
+    if is_neutron_legacy_enabled; then
+        # Call back to old function
+        start_mutnauq_l2_agent "$@"
+        start_mutnauq_other_agents "$@"
+    else
+        start_neutron_new "$@"
+    fi
+}
+
+function stop_neutron {
+    if is_neutron_legacy_enabled; then
+        # Call back to old function
+        stop_mutnauq "$@"
+    else
+        stop_neutron_new "$@"
+    fi
+}
+
+# Restore xtrace
+$XTRACE
diff --git a/lib/neutron-legacy b/lib/neutron-legacy
index f5a7a0a..25fb6b7 100644
--- a/lib/neutron-legacy
+++ b/lib/neutron-legacy
@@ -61,45 +61,12 @@
 # Neutron Network Configuration
 # -----------------------------
 
-# Subnet IP version
-IP_VERSION=${IP_VERSION:-"4+6"}
-# Validate IP_VERSION
-if [[ $IP_VERSION != "4" ]] && [[ $IP_VERSION != "6" ]] && [[ $IP_VERSION != "4+6" ]]; then
-    die $LINENO "IP_VERSION must be either 4, 6, or 4+6"
-fi
-# Gateway and subnet defaults, in case they are not customized in localrc
-NETWORK_GATEWAY=${NETWORK_GATEWAY:-10.0.0.1}
-PUBLIC_NETWORK_GATEWAY=${PUBLIC_NETWORK_GATEWAY:-172.24.4.1}
-PRIVATE_SUBNET_NAME=${PRIVATE_SUBNET_NAME:-"private-subnet"}
-PUBLIC_SUBNET_NAME=${PUBLIC_SUBNET_NAME:-"public-subnet"}
-
-# Subnetpool defaults
-SUBNETPOOL_NAME=${SUBNETPOOL_NAME:-"shared-default-subnetpool"}
-
-SUBNETPOOL_PREFIX_V4=${SUBNETPOOL_PREFIX_V4:-10.0.0.0/8}
-SUBNETPOOL_PREFIX_V6=${SUBNETPOOL_PREFIX_V6:-2001:db8:8000::/48}
-
-SUBNETPOOL_SIZE_V4=${SUBNETPOOL_SIZE_V4:-24}
-SUBNETPOOL_SIZE_V6=${SUBNETPOOL_SIZE_V6:-64}
-
+deprecated "Using lib/neutron-legacy is deprecated, and it will be removed in the future"
 
 if is_ssl_enabled_service "neutron" || is_service_enabled tls-proxy; then
     Q_PROTOCOL="https"
 fi
 
-# Generate 40-bit IPv6 Global ID to comply with RFC 4193
-IPV6_GLOBAL_ID=`uuidgen | sed s/-//g | cut -c 23- | sed -e "s/\(..\)\(....\)\(....\)/\1:\2:\3/"`
-
-# IPv6 gateway and subnet defaults, in case they are not customized in localrc
-IPV6_RA_MODE=${IPV6_RA_MODE:-slaac}
-IPV6_ADDRESS_MODE=${IPV6_ADDRESS_MODE:-slaac}
-IPV6_PUBLIC_SUBNET_NAME=${IPV6_PUBLIC_SUBNET_NAME:-ipv6-public-subnet}
-IPV6_PRIVATE_SUBNET_NAME=${IPV6_PRIVATE_SUBNET_NAME:-ipv6-private-subnet}
-FIXED_RANGE_V6=${FIXED_RANGE_V6:-fd$IPV6_GLOBAL_ID::/64}
-IPV6_PRIVATE_NETWORK_GATEWAY=${IPV6_PRIVATE_NETWORK_GATEWAY:-fd$IPV6_GLOBAL_ID::1}
-IPV6_PUBLIC_RANGE=${IPV6_PUBLIC_RANGE:-2001:db8::/64}
-IPV6_PUBLIC_NETWORK_GATEWAY=${IPV6_PUBLIC_NETWORK_GATEWAY:-2001:db8::2}
-IPV6_ROUTER_GW_IP=${IPV6_ROUTER_GW_IP:-2001:db8::1}
 
 # Set up default directories
 GITDIR["python-neutronclient"]=$DEST/python-neutronclient
@@ -107,7 +74,7 @@
 
 NEUTRON_DIR=$DEST/neutron
 NEUTRON_FWAAS_DIR=$DEST/neutron-fwaas
-NEUTRON_VPNAAS_DIR=$DEST/neutron-vpnaas
+NEUTRON_LBAAS_DIR=$DEST/neutron-lbaas
 NEUTRON_AUTH_CACHE_DIR=${NEUTRON_AUTH_CACHE_DIR:-/var/cache/neutron}
 
 # Support entry points installation of console scripts
@@ -121,8 +88,8 @@
 NEUTRON_CONF=$NEUTRON_CONF_DIR/neutron.conf
 export NEUTRON_TEST_CONFIG_FILE=${NEUTRON_TEST_CONFIG_FILE:-"$NEUTRON_CONF_DIR/debug.ini"}
 
-# Default provider for VPN service
-DEFAULT_VPN_PROVIDER=VPN:openswan:neutron_vpnaas.services.vpn.service_drivers.ipsec.IPsecVPNDriver:default
+# Default provider for load balancer service
+DEFAULT_LB_PROVIDER=LOADBALANCER:Haproxy:neutron_lbaas.services.loadbalancer.drivers.haproxy.plugin_driver.HaproxyOnHostPluginDriver:default
 
 # Agent binaries.  Note, binary paths for other agents are set in per-service
 # scripts in lib/neutron_plugins/services/
@@ -134,8 +101,6 @@
 # loaded from per-plugin  scripts in lib/neutron_plugins/
 Q_DHCP_CONF_FILE=$NEUTRON_CONF_DIR/dhcp_agent.ini
 Q_L3_CONF_FILE=$NEUTRON_CONF_DIR/l3_agent.ini
-Q_FWAAS_CONF_FILE=$NEUTRON_CONF_DIR/fwaas_driver.ini
-Q_VPN_CONF_FILE=$NEUTRON_CONF_DIR/vpn_agent.ini
 Q_META_CONF_FILE=$NEUTRON_CONF_DIR/metadata_agent.ini
 
 # Default name for Neutron database
@@ -164,73 +129,17 @@
 Q_META_DATA_IP=${Q_META_DATA_IP:-$SERVICE_HOST}
 # Allow Overlapping IP among subnets
 Q_ALLOW_OVERLAPPING_IP=${Q_ALLOW_OVERLAPPING_IP:-True}
-# Use neutron-debug command
-Q_USE_DEBUG_COMMAND=${Q_USE_DEBUG_COMMAND:-False}
 # The name of the default q-l3 router
 Q_ROUTER_NAME=${Q_ROUTER_NAME:-router1}
 Q_NOTIFY_NOVA_PORT_STATUS_CHANGES=${Q_NOTIFY_NOVA_PORT_STATUS_CHANGES:-True}
 Q_NOTIFY_NOVA_PORT_DATA_CHANGES=${Q_NOTIFY_NOVA_PORT_DATA_CHANGES:-True}
 VIF_PLUGGING_IS_FATAL=${VIF_PLUGGING_IS_FATAL:-True}
 VIF_PLUGGING_TIMEOUT=${VIF_PLUGGING_TIMEOUT:-300}
-# Specify if the initial private and external networks should be created
-NEUTRON_CREATE_INITIAL_NETWORKS=${NEUTRON_CREATE_INITIAL_NETWORKS:-True}
-
-## Provider Network Information
-PROVIDER_SUBNET_NAME=${PROVIDER_SUBNET_NAME:-"provider_net"}
-IPV6_PROVIDER_SUBNET_NAME=${IPV6_PROVIDER_SUBNET_NAME:-"provider_net_v6"}
-IPV6_PROVIDER_FIXED_RANGE=${IPV6_PROVIDER_FIXED_RANGE:-}
-IPV6_PROVIDER_NETWORK_GATEWAY=${IPV6_PROVIDER_NETWORK_GATEWAY:-}
-
-# Define the public bridge that will transmit traffic from VMs to the
-# physical network - used by both the OVS and Linux Bridge drivers.
-PUBLIC_BRIDGE=${PUBLIC_BRIDGE:-br-ex}
-
-# Use flat providernet for public network
-#
-# If Q_USE_PROVIDERNET_FOR_PUBLIC=True, use a flat provider network
-# for external interface of neutron l3-agent.  In that case,
-# PUBLIC_PHYSICAL_NETWORK specifies provider:physical_network value
-# used for the network.  In case of ofagent, you should add the
-# corresponding entry to your OFAGENT_PHYSICAL_INTERFACE_MAPPINGS.
-# For openvswitch agent, you should add the corresponding entry to
-# your OVS_BRIDGE_MAPPINGS.
-#
-# eg.  (ofagent)
-#    Q_USE_PROVIDERNET_FOR_PUBLIC=True
-#    Q_USE_PUBLIC_VETH=True
-#    PUBLIC_PHYSICAL_NETWORK=public
-#    OFAGENT_PHYSICAL_INTERFACE_MAPPINGS=public:veth-pub-int
-#
-# eg.  (openvswitch agent)
-#    Q_USE_PROVIDERNET_FOR_PUBLIC=True
-#    PUBLIC_PHYSICAL_NETWORK=public
-#    OVS_BRIDGE_MAPPINGS=public:br-ex
-Q_USE_PROVIDERNET_FOR_PUBLIC=${Q_USE_PROVIDERNET_FOR_PUBLIC:-False}
-PUBLIC_PHYSICAL_NETWORK=${PUBLIC_PHYSICAL_NETWORK:-public}
-
-# If Q_USE_PUBLIC_VETH=True, create and use a veth pair instead of
-# PUBLIC_BRIDGE.  This is intended to be used with
-# Q_USE_PROVIDERNET_FOR_PUBLIC=True.
-Q_USE_PUBLIC_VETH=${Q_USE_PUBLIC_VETH:-False}
-Q_PUBLIC_VETH_EX=${Q_PUBLIC_VETH_EX:-veth-pub-ex}
-Q_PUBLIC_VETH_INT=${Q_PUBLIC_VETH_INT:-veth-pub-int}
-
-# The next two variables are configured by plugin
-# e.g.  _configure_neutron_l3_agent or lib/neutron_plugins/*
-#
-# The plugin supports L3.
-Q_L3_ENABLED=${Q_L3_ENABLED:-False}
-# L3 routers exist per tenant
-Q_L3_ROUTER_PER_TENANT=${Q_L3_ROUTER_PER_TENANT:-True}
 
 # List of config file names in addition to the main plugin config file
 # See _configure_neutron_common() for details about setting it up
 declare -a Q_PLUGIN_EXTRA_CONF_FILES
 
-# List of (optional) config files for VPN device drivers to use with
-# the neutron-q-vpn agent
-declare -a Q_VPN_EXTRA_CONF_FILES
-
 
 Q_RR_CONF_FILE=$NEUTRON_CONF_DIR/rootwrap.conf
 if [[ "$Q_USE_ROOTWRAP" == "False" ]]; then
@@ -269,9 +178,9 @@
 # GRE tunnels are only supported by the openvswitch.
 ENABLE_TENANT_TUNNELS=${ENABLE_TENANT_TUNNELS:-True}
 
-# If using GRE tunnels for tenant networks, specify the range of
-# tunnel IDs from which tenant networks are allocated. Can be
-# overridden in ``localrc`` in necessary.
+# If using GRE, VXLAN or GENEVE tunnels for tenant networks,
+# specify the range of IDs from which tenant networks are
+# allocated. Can be overridden in ``localrc`` if necessary.
 TENANT_TUNNEL_RANGES=${TENANT_TUNNEL_RANGES:-1:1000}
 
 # To use VLANs for tenant networks, set to True in localrc. VLANs
@@ -343,21 +252,20 @@
     source $TOP_DIR/lib/neutron_plugins/$Q_PLUGIN
 fi
 
+# Agent loadbalancer service plugin functions
+# -------------------------------------------
+
+# Hardcoding for 1 service plugin for now
+source $TOP_DIR/lib/neutron_plugins/services/loadbalancer
+
 # Agent metering service plugin functions
 # -------------------------------------------
 
 # Hardcoding for 1 service plugin for now
 source $TOP_DIR/lib/neutron_plugins/services/metering
 
-# VPN service plugin functions
-# -------------------------------------------
-# Hardcoding for 1 service plugin for now
-source $TOP_DIR/lib/neutron_plugins/services/vpn
-
-# Firewall Service Plugin functions
-# ---------------------------------
-source $TOP_DIR/lib/neutron_plugins/services/firewall
-
+# L3 Service functions
+source $TOP_DIR/lib/neutron_plugins/services/l3
 # Use security group or not
 if has_neutron_plugin_security_group; then
     Q_USE_SECGROUP=${Q_USE_SECGROUP:-True}
@@ -377,29 +285,13 @@
     local cfg_file
     local opts="--config-file $NEUTRON_CONF --config-file /$Q_PLUGIN_CONF_FILE"
     for cfg_file in ${Q_PLUGIN_EXTRA_CONF_FILES[@]}; do
-        opts+=" --config-file /$cfg_file"
-    done
-    echo "$opts"
-}
-
-function _determine_config_vpn {
-    local cfg_file
-    local opts="--config-file $NEUTRON_CONF --config-file=$Q_L3_CONF_FILE --config-file=$Q_VPN_CONF_FILE"
-    if is_service_enabled q-fwaas; then
-        opts+=" --config-file $Q_FWAAS_CONF_FILE"
-    fi
-    for cfg_file in ${Q_VPN_EXTRA_CONF_FILES[@]}; do
         opts+=" --config-file $cfg_file"
     done
     echo "$opts"
-
 }
 
 function _determine_config_l3 {
-    local opts="--config-file $NEUTRON_CONF --config-file=$Q_L3_CONF_FILE"
-    if is_service_enabled q-fwaas; then
-        opts+=" --config-file $Q_FWAAS_CONF_FILE"
-    fi
+    local opts="--config-file $NEUTRON_CONF --config-file $Q_L3_CONF_FILE"
     echo "$opts"
 }
 
@@ -409,7 +301,6 @@
     local opts=""
     case "$1" in
         "neutron-server") opts="$(_determine_config_server)" ;;
-        "neutron-vpn-agent") opts="$(_determine_config_vpn)" ;;
         "neutron-l3-agent") opts="$(_determine_config_l3)" ;;
     esac
     if [ -z "$opts" ] ; then
@@ -418,31 +309,20 @@
     echo "$opts"
 }
 
-# Test if any Neutron services are enabled
-# is_neutron_enabled
-function is_neutron_enabled {
-    [[ ,${ENABLED_SERVICES} =~ ,"q-" ]] && return 0
-    return 1
-}
-
-# configure_neutron()
+# configure_mutnauq()
 # Set common config for all neutron server and agents.
-function configure_neutron {
+function configure_mutnauq {
     _configure_neutron_common
     iniset_rpc_backend neutron $NEUTRON_CONF
 
     # goes before q-svc to init Q_SERVICE_PLUGIN_CLASSES
+    if is_service_enabled q-lbaas; then
+        deprecated "Configuring q-lbaas through devstack is deprecated"
+        _configure_neutron_lbaas
+    fi
     if is_service_enabled q-metering; then
         _configure_neutron_metering
     fi
-    if is_service_enabled q-vpn; then
-        deprecated "Configuring q-vpn through devstack is deprecated"
-        _configure_neutron_vpn
-    fi
-    if is_service_enabled q-fwaas; then
-        deprecated "Configuring q-fwaas through devstack is deprecated"
-        _configure_neutron_fwaas
-    fi
     if is_service_enabled q-agt q-svc; then
         _configure_neutron_service
     fi
@@ -466,20 +346,18 @@
         _configure_neutron_ceilometer_notifications
     fi
 
-    _configure_neutron_debug_command
-
     iniset $NEUTRON_CONF DEFAULT api_workers "$API_WORKERS"
 }
 
 function create_nova_conf_neutron {
     iniset $NOVA_CONF DEFAULT use_neutron True
     iniset $NOVA_CONF neutron auth_type "password"
-    iniset $NOVA_CONF neutron auth_url "$KEYSTONE_SERVICE_PROTOCOL://$KEYSTONE_SERVICE_HOST:$KEYSTONE_AUTH_PORT/v3"
+    iniset $NOVA_CONF neutron auth_url "$KEYSTONE_AUTH_URI/v3"
     iniset $NOVA_CONF neutron username "$Q_ADMIN_USERNAME"
     iniset $NOVA_CONF neutron password "$SERVICE_PASSWORD"
-    iniset $NOVA_CONF neutron user_domain_name "Default"
+    iniset $NOVA_CONF neutron user_domain_name "$SERVICE_DOMAIN_NAME"
     iniset $NOVA_CONF neutron project_name "$SERVICE_PROJECT_NAME"
-    iniset $NOVA_CONF neutron project_domain_name "Default"
+    iniset $NOVA_CONF neutron project_domain_name "$SERVICE_DOMAIN_NAME"
     iniset $NOVA_CONF neutron auth_strategy "$Q_AUTH_STRATEGY"
     iniset $NOVA_CONF neutron region_name "$REGION_NAME"
     iniset $NOVA_CONF neutron url "${Q_PROTOCOL}://$Q_HOST:$Q_PORT"
@@ -500,21 +378,14 @@
     iniset $NOVA_CONF DEFAULT vif_plugging_timeout "$VIF_PLUGGING_TIMEOUT"
 }
 
-# create_neutron_cache_dir() - Part of the _neutron_setup_keystone() process
-function create_neutron_cache_dir {
-    # Create cache dir
-    sudo install -d -o $STACK_USER $NEUTRON_AUTH_CACHE_DIR
-    rm -f $NEUTRON_AUTH_CACHE_DIR/*
-}
-
-# create_neutron_accounts() - Set up common required neutron accounts
+# create_mutnauq_accounts() - Set up common required neutron accounts
 
 # Tenant               User       Roles
 # ------------------------------------------------------------------
 # service              neutron    admin        # if enabled
 
 # Migrated from keystone_data.sh
-function create_neutron_accounts {
+function create_mutnauq_accounts {
     if [[ "$ENABLED_SERVICES" =~ "q-svc" ]]; then
 
         create_service_user "neutron"
@@ -529,107 +400,15 @@
     fi
 }
 
-function create_neutron_initial_network {
-    local project_id
-    project_id=$(openstack project list | grep " demo " | get_field 1)
-    die_if_not_set $LINENO project_id "Failure retrieving project_id for demo"
-
-    # Allow drivers that need to create an initial network to do so here
-    if type -p neutron_plugin_create_initial_network_profile > /dev/null; then
-        neutron_plugin_create_initial_network_profile $PHYSICAL_NETWORK
-    fi
-
-    if is_provider_network; then
-        die_if_not_set $LINENO PHYSICAL_NETWORK "You must specify the PHYSICAL_NETWORK"
-        die_if_not_set $LINENO PROVIDER_NETWORK_TYPE "You must specify the PROVIDER_NETWORK_TYPE"
-        NET_ID=$(neutron net-create $PHYSICAL_NETWORK --tenant_id $project_id --provider:network_type $PROVIDER_NETWORK_TYPE --provider:physical_network "$PHYSICAL_NETWORK" ${SEGMENTATION_ID:+--provider:segmentation_id $SEGMENTATION_ID} --shared | grep ' id ' | get_field 2)
-        die_if_not_set $LINENO NET_ID "Failure creating NET_ID for $PHYSICAL_NETWORK $project_id"
-
-        if [[ "$IP_VERSION" =~ 4.* ]]; then
-            SUBNET_ID=$(neutron subnet-create --tenant_id $project_id --ip_version 4 ${ALLOCATION_POOL:+--allocation-pool $ALLOCATION_POOL} --name $PROVIDER_SUBNET_NAME --gateway $NETWORK_GATEWAY $NET_ID $FIXED_RANGE | grep ' id ' | get_field 2)
-            die_if_not_set $LINENO SUBNET_ID "Failure creating SUBNET_ID for $PROVIDER_SUBNET_NAME $project_id"
-        fi
-
-        if [[ "$IP_VERSION" =~ .*6 ]] && [[ -n "$IPV6_PROVIDER_FIXED_RANGE" ]] && [[ -n "$IPV6_PROVIDER_NETWORK_GATEWAY" ]]; then
-            SUBNET_V6_ID=$(neutron subnet-create --tenant_id $project_id --ip_version 6 --ipv6-address-mode $IPV6_ADDRESS_MODE --gateway $IPV6_PROVIDER_NETWORK_GATEWAY --name $IPV6_PROVIDER_SUBNET_NAME $NET_ID $IPV6_PROVIDER_FIXED_RANGE | grep 'id' | get_field 2)
-            die_if_not_set $LINENO SUBNET_V6_ID "Failure creating SUBNET_V6_ID for $IPV6_PROVIDER_SUBNET_NAME $project_id"
-        fi
-
-        if [[ $Q_AGENT == "openvswitch" ]]; then
-            sudo ip link set $OVS_PHYSICAL_BRIDGE up
-            sudo ip link set br-int up
-            sudo ip link set $PUBLIC_INTERFACE up
-        fi
-    else
-        NET_ID=$(neutron net-create --tenant-id $project_id "$PRIVATE_NETWORK_NAME" | grep ' id ' | get_field 2)
-        die_if_not_set $LINENO NET_ID "Failure creating NET_ID for $PRIVATE_NETWORK_NAME $project_id"
-
-        if [[ "$IP_VERSION" =~ 4.* ]]; then
-            # Create IPv4 private subnet
-            SUBNET_ID=$(_neutron_create_private_subnet_v4 $project_id)
-        fi
-
-        if [[ "$IP_VERSION" =~ .*6 ]]; then
-            # Create IPv6 private subnet
-            IPV6_SUBNET_ID=$(_neutron_create_private_subnet_v6 $project_id)
-        fi
-    fi
-
-    AUTO_ALLOCATE_EXT=$(neutron ext-list | grep 'auto-allocated-topology' | get_field 1)
-    SUBNETPOOL_EXT=$(neutron ext-list | grep 'subnet_allocation' | get_field 1)
-    if [[ "$Q_L3_ENABLED" == "True" ]]; then
-        # Create a router, and add the private subnet as one of its interfaces
-        if [[ "$Q_L3_ROUTER_PER_TENANT" == "True" ]]; then
-            # create a tenant-owned router.
-            ROUTER_ID=$(neutron router-create --tenant-id $project_id $Q_ROUTER_NAME | grep ' id ' | get_field 2)
-            die_if_not_set $LINENO ROUTER_ID "Failure creating ROUTER_ID for $project_id $Q_ROUTER_NAME"
-        else
-            # Plugin only supports creating a single router, which should be admin owned.
-            ROUTER_ID=$(neutron router-create $Q_ROUTER_NAME | grep ' id ' | get_field 2)
-            die_if_not_set $LINENO ROUTER_ID "Failure creating ROUTER_ID for $Q_ROUTER_NAME"
-        fi
-
-        # if the extension is available, then mark the external
-        # network as default, and provision default subnetpools
-        EXTERNAL_NETWORK_FLAGS="--router:external"
-        if [[ -n $AUTO_ALLOCATE_EXT && -n $SUBNETPOOL_EXT ]]; then
-            EXTERNAL_NETWORK_FLAGS="$EXTERNAL_NETWORK_FLAGS --is-default"
-            if [[ "$IP_VERSION" =~ 4.* ]]; then
-                SUBNETPOOL_V4_ID=$(neutron subnetpool-create $SUBNETPOOL_NAME --default-prefixlen $SUBNETPOOL_SIZE_V4 --pool-prefix $SUBNETPOOL_PREFIX_V4 --shared --is-default=True | grep ' id ' | get_field 2)
-            fi
-            if [[ "$IP_VERSION" =~ .*6 ]]; then
-                SUBNETPOOL_V6_ID=$(neutron subnetpool-create $SUBNETPOOL_NAME --default-prefixlen $SUBNETPOOL_SIZE_V6 --pool-prefix $SUBNETPOOL_PREFIX_V6 --shared --is-default=True | grep ' id ' | get_field 2)
-            fi
-        fi
-        # Create an external network, and a subnet. Configure the external network as router gw
-        if [ "$Q_USE_PROVIDERNET_FOR_PUBLIC" = "True" ]; then
-            EXT_NET_ID=$(neutron net-create "$PUBLIC_NETWORK_NAME" -- $EXTERNAL_NETWORK_FLAGS --provider:network_type=flat --provider:physical_network=${PUBLIC_PHYSICAL_NETWORK} | grep ' id ' | get_field 2)
-        else
-            EXT_NET_ID=$(neutron net-create "$PUBLIC_NETWORK_NAME" -- $EXTERNAL_NETWORK_FLAGS | grep ' id ' | get_field 2)
-        fi
-        die_if_not_set $LINENO EXT_NET_ID "Failure creating EXT_NET_ID for $PUBLIC_NETWORK_NAME"
-
-        if [[ "$IP_VERSION" =~ 4.* ]]; then
-            # Configure router for IPv4 public access
-            _neutron_configure_router_v4
-        fi
-
-        if [[ "$IP_VERSION" =~ .*6 ]]; then
-            # Configure router for IPv6 public access
-            _neutron_configure_router_v6
-        fi
-    fi
-}
-
-# init_neutron() - Initialize databases, etc.
-function init_neutron {
+# init_mutnauq() - Initialize databases, etc.
+function init_mutnauq {
     recreate_database $Q_DB_NAME
     # 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
-function install_neutron {
+# install_mutnauq() - Collect source and prepare
+function install_mutnauq {
     # Install neutron-lib from git so we make sure we're testing
     # the latest code.
     if use_library_from_git "neutron-lib"; then
@@ -639,13 +418,9 @@
 
     git_clone $NEUTRON_REPO $NEUTRON_DIR $NEUTRON_BRANCH
     setup_develop $NEUTRON_DIR
-    if is_service_enabled q-fwaas; then
-        git_clone $NEUTRON_FWAAS_REPO $NEUTRON_FWAAS_DIR $NEUTRON_FWAAS_BRANCH
-        setup_develop $NEUTRON_FWAAS_DIR
-    fi
-    if is_service_enabled q-vpn; then
-        git_clone $NEUTRON_VPNAAS_REPO $NEUTRON_VPNAAS_DIR $NEUTRON_VPNAAS_BRANCH
-        setup_develop $NEUTRON_VPNAAS_DIR
+    if is_service_enabled q-lbaas; then
+        git_clone $NEUTRON_LBAAS_REPO $NEUTRON_LBAAS_DIR $NEUTRON_LBAAS_BRANCH
+        setup_develop $NEUTRON_LBAAS_DIR
     fi
 
     if [ "$VIRT_DRIVER" == 'xenserver' ]; then
@@ -667,15 +442,6 @@
     fi
 }
 
-# install_neutronclient() - Collect source and prepare
-function install_neutronclient {
-    if use_library_from_git "python-neutronclient"; then
-        git_clone_by_name "python-neutronclient"
-        setup_dev_lib "python-neutronclient"
-        sudo install -D -m 0644 -o $STACK_USER {${GITDIR["python-neutronclient"]}/tools/,/etc/bash_completion.d/}neutron.bash_completion
-    fi
-}
-
 # install_neutron_agent_packages() - Collect source and prepare
 function install_neutron_agent_packages {
     # radvd doesn't come with the OS. Install it if the l3 service is enabled.
@@ -686,6 +452,10 @@
     if is_service_enabled q-agt q-dhcp q-l3; then
         neutron_plugin_install_agent_packages
     fi
+
+    if is_service_enabled q-lbaas; then
+        neutron_agent_lbaas_install_agent_packages
+    fi
 }
 
 # Start running processes, including screen
@@ -718,7 +488,7 @@
 
 # Control of the l2 agent is separated out to make it easier to test partial
 # upgrades (everything upgraded except the L2 agent)
-function start_neutron_l2_agent {
+function start_mutnauq_l2_agent {
     run_process q-agt "$AGENT_BINARY --config-file $NEUTRON_CONF --config-file /$Q_PLUGIN_CONF_FILE"
 
     if is_provider_network && [[ $Q_AGENT == "openvswitch" ]]; then
@@ -736,18 +506,17 @@
     fi
 }
 
-function start_neutron_other_agents {
-    run_process q-dhcp "$AGENT_DHCP_BINARY --config-file $NEUTRON_CONF --config-file=$Q_DHCP_CONF_FILE"
+function start_mutnauq_other_agents {
+    run_process q-dhcp "$AGENT_DHCP_BINARY --config-file $NEUTRON_CONF --config-file $Q_DHCP_CONF_FILE"
 
     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 "$AGENT_L3_BINARY $(determine_config_files neutron-l3-agent)"
     fi
 
-    run_process q-meta "$AGENT_META_BINARY --config-file $NEUTRON_CONF --config-file=$Q_META_CONF_FILE"
+    run_process q-meta "$AGENT_META_BINARY --config-file $NEUTRON_CONF --config-file $Q_META_CONF_FILE"
+    run_process q-lbaas "$AGENT_LBAAS_BINARY --config-file $NEUTRON_CONF --config-file $LBAAS_AGENT_CONF_FILENAME"
     run_process q-metering "$AGENT_METERING_BINARY --config-file $NEUTRON_CONF --config-file $METERING_AGENT_CONF_FILENAME"
 
     if [ "$VIRT_DRIVER" = 'xenserver' ]; then
@@ -759,15 +528,16 @@
 # Start running processes, including screen
 function start_neutron_agents {
     # Start up the neutron agents if enabled
-    start_neutron_l2_agent
-    start_neutron_other_agents
+    start_mutnauq_l2_agent
+    start_mutnauq_other_agents
 }
 
-function stop_neutron_l2_agent {
+function stop_mutnauq_l2_agent {
     stop_process q-agt
 }
 
-function stop_neutron_other {
+# stop_mutnauq_other() - Stop running processes (non-screen)
+function stop_mutnauq_other {
     if is_service_enabled q-dhcp; then
         stop_process q-dhcp
         pid=$(ps aux | awk '/[d]nsmasq.+interface=(tap|ns-)/ { print $2 }')
@@ -786,11 +556,8 @@
         stop_process q-meta
     fi
 
-    if is_service_enabled q-fwaas; then
-        neutron_fwaas_stop
-    fi
-    if is_service_enabled q-vpn; then
-        neutron_vpn_stop
+    if is_service_enabled q-lbaas; then
+        neutron_lbaas_stop
     fi
     if is_service_enabled q-metering; then
         neutron_metering_stop
@@ -802,9 +569,9 @@
 }
 
 # stop_neutron() - Stop running processes (non-screen)
-function stop_neutron {
-    stop_neutron_other
-    stop_neutron_l2_agent
+function stop_mutnauq {
+    stop_mutnauq_other
+    stop_mutnauq_l2_agent
 }
 
 # _move_neutron_addresses_route() - Move the primary IP to the OVS bridge
@@ -823,13 +590,14 @@
         # on configure we will also add $from_intf as a port on $to_intf,
         # assuming it is an OVS bridge.
 
-        local IP_ADD=""
+        local IP_REPLACE=""
         local IP_DEL=""
         local IP_UP=""
         local DEFAULT_ROUTE_GW
         DEFAULT_ROUTE_GW=$(ip -f $af r | awk "/default.+$from_intf/ { print \$3; exit }")
         local ADD_OVS_PORT=""
         local DEL_OVS_PORT=""
+        local ARP_CMD=""
 
         IP_BRD=$(ip -f $af a s dev $from_intf scope global primary | grep inet | awk '{ print $2, $3, $4; exit }')
 
@@ -847,19 +615,23 @@
 
         if [[ "$IP_BRD" != "" ]]; then
             IP_DEL="sudo ip addr del $IP_BRD dev $from_intf"
-            IP_ADD="sudo ip addr add $IP_BRD dev $to_intf"
+            IP_REPLACE="sudo ip addr replace $IP_BRD dev $to_intf"
             IP_UP="sudo ip link set $to_intf up"
+            if [[ "$af" == "inet" ]]; then
+                IP=$(echo $IP_BRD | awk '{ print $1; exit }' | grep -o -E '(.*)/' | cut -d "/" -f1)
+                ARP_CMD="arping -A -c 3 -w 4.5 -I $to_intf $IP "
+            fi
         fi
 
         # The add/del OVS port calls have to happen either before or
         # after the address is moved in order to not leave it orphaned.
-        $DEL_OVS_PORT; $IP_DEL; $IP_ADD; $IP_UP; $ADD_OVS_PORT; $ADD_DEFAULT_ROUTE
+        $DEL_OVS_PORT; $IP_DEL; $IP_REPLACE; $IP_UP; $ADD_OVS_PORT; $ADD_DEFAULT_ROUTE; $ARP_CMD
     fi
 }
 
-# cleanup_neutron() - Remove residual data files, anything left over from previous
+# cleanup_mutnauq() - Remove residual data files, anything left over from previous
 # runs that a clean run would need to clean up
-function cleanup_neutron {
+function cleanup_mutnauq {
 
     if [[ -n "$OVS_PHYSICAL_BRIDGE" ]]; then
         _move_neutron_addresses_route "$OVS_PHYSICAL_BRIDGE" "$PUBLIC_INTERFACE" False True "inet"
@@ -890,7 +662,7 @@
     fi
 
     # delete all namespaces created by neutron
-    for ns in $(sudo ip netns list | grep -o -E '(qdhcp|qrouter|fip|snat)-[0-9a-f-]*'); do
+    for ns in $(sudo ip netns list | grep -o -E '(qdhcp|qrouter|qlbaas|fip|snat)-[0-9a-f-]*'); do
         sudo ip netns delete ${ns}
     done
 }
@@ -920,10 +692,11 @@
 
     # 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``,
+    # For additional plugin config files, set ``Q_PLUGIN_EXTRA_CONF_PATH`` and
     # ``Q_PLUGIN_EXTRA_CONF_FILES``.  For example:
     #
-    #    ``Q_PLUGIN_EXTRA_CONF_FILES=(file1, file2)``
+    #    ``Q_PLUGIN_EXTRA_CONF_PATH=/path/to/plugins``
+    #    ``Q_PLUGIN_EXTRA_CONF_FILES=(file1 file2)``
     neutron_plugin_configure_common
 
     if [[ "$Q_PLUGIN_CONF_PATH" == '' || "$Q_PLUGIN_CONF_FILENAME" == '' || "$Q_PLUGIN_CLASS" == '' ]]; then
@@ -947,6 +720,9 @@
     iniset $NEUTRON_CONF DEFAULT bind_host $Q_LISTEN_ADDRESS
     iniset $NEUTRON_CONF oslo_concurrency lock_path $DATA_DIR/neutron/lock
 
+    # NOTE(freerunner): Need to adjust Region Name for nova in multiregion installation
+    iniset $NEUTRON_CONF nova region_name $REGION_NAME
+
     # If addition config files are set, make sure their path name is set as well
     if [[ ${#Q_PLUGIN_EXTRA_CONF_FILES[@]} > 0 && $Q_PLUGIN_EXTRA_CONF_PATH == '' ]]; then
         die $LINENO "Neutron additional plugin config not set.. exiting"
@@ -998,29 +774,13 @@
     _neutron_setup_rootwrap
 }
 
-function _configure_neutron_debug_command {
-    if [[ "$Q_USE_DEBUG_COMMAND" != "True" ]]; then
-        return
-    fi
-
-    cp $NEUTRON_DIR/etc/l3_agent.ini.sample $NEUTRON_TEST_CONFIG_FILE
-
-    iniset $NEUTRON_TEST_CONFIG_FILE DEFAULT debug False
-    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"
-    fi
-
-    _neutron_setup_interface_driver $NEUTRON_TEST_CONFIG_FILE
-
-    neutron_plugin_configure_debug_command
-}
-
 function _configure_neutron_dhcp_agent {
 
     cp $NEUTRON_DIR/etc/dhcp_agent.ini.sample $Q_DHCP_CONF_FILE
 
     iniset $Q_DHCP_CONF_FILE DEFAULT debug $ENABLE_DEBUG_LOG_LEVEL
+    # make it so we have working DNS from guests
+    iniset $Q_DHCP_CONF_FILE DEFAULT dnsmasq_local_resolv True
     iniset $Q_DHCP_CONF_FILE AGENT root_helper "$Q_RR_COMMAND"
     if [[ "$Q_USE_ROOTWRAP_DAEMON" == "True" ]]; then
         iniset $Q_DHCP_CONF_FILE AGENT root_helper_daemon "$Q_RR_DAEMON_COMMAND"
@@ -1039,34 +799,9 @@
 
     _neutron_setup_interface_driver $Q_DHCP_CONF_FILE
 
-    neutron_plugin_configure_dhcp_agent
+    neutron_plugin_configure_dhcp_agent $Q_DHCP_CONF_FILE
 }
 
-function _configure_neutron_l3_agent {
-    Q_L3_ENABLED=True
-
-    if is_service_enabled q-vpn; then
-        neutron_vpn_configure_agent
-    fi
-
-    cp $NEUTRON_DIR/etc/l3_agent.ini.sample $Q_L3_CONF_FILE
-
-    iniset $Q_L3_CONF_FILE DEFAULT debug $ENABLE_DEBUG_LOG_LEVEL
-    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"
-    fi
-
-    _neutron_setup_interface_driver $Q_L3_CONF_FILE
-
-    neutron_plugin_configure_l3_agent
-
-    _move_neutron_addresses_route "$PUBLIC_INTERFACE" "$OVS_PHYSICAL_BRIDGE" True False "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 False "inet6"
-    fi
-}
 
 function _configure_neutron_metadata_agent {
     cp $NEUTRON_DIR/etc/metadata_agent.ini.sample $Q_META_CONF_FILE
@@ -1083,30 +818,23 @@
     iniset $NEUTRON_CONF oslo_messaging_notifications driver messaging
 }
 
+function _configure_neutron_lbaas {
+    # Uses oslo config generator to generate LBaaS sample configuration files
+    (cd $NEUTRON_LBAAS_DIR && exec ./tools/generate_config_file_samples.sh)
+
+    if [ -f $NEUTRON_LBAAS_DIR/etc/neutron_lbaas.conf.sample ]; then
+        cp $NEUTRON_LBAAS_DIR/etc/neutron_lbaas.conf.sample $NEUTRON_CONF_DIR/neutron_lbaas.conf
+        iniset $NEUTRON_CONF_DIR/neutron_lbaas.conf service_providers service_provider $DEFAULT_LB_PROVIDER
+    fi
+    neutron_agent_lbaas_configure_common
+    neutron_agent_lbaas_configure_agent
+}
+
 function _configure_neutron_metering {
     neutron_agent_metering_configure_common
     neutron_agent_metering_configure_agent
 }
 
-function _configure_neutron_fwaas {
-    if [ -f $NEUTRON_FWAAS_DIR/etc/neutron_fwaas.conf ]; then
-        cp $NEUTRON_FWAAS_DIR/etc/neutron_fwaas.conf $NEUTRON_CONF_DIR
-    fi
-    neutron_fwaas_configure_common
-    neutron_fwaas_configure_driver
-}
-
-function _configure_neutron_vpn {
-    # Uses oslo config generator to generate VPNaaS sample configuration files
-    (cd $NEUTRON_VPNAAS_DIR && exec ./tools/generate_config_file_samples.sh)
-    if [ -f $NEUTRON_VPNAAS_DIR/etc/neutron_vpnaas.conf.sample ]; then
-        cp $NEUTRON_VPNAAS_DIR/etc/neutron_vpnaas.conf.sample $NEUTRON_CONF_DIR/neutron_vpnaas.conf
-        iniset $NEUTRON_CONF_DIR/neutron_vpnaas.conf service_providers service_provider $DEFAULT_VPN_PROVIDER
-    fi
-    neutron_vpn_install_agent_packages
-    neutron_vpn_configure_common
-}
-
 function _configure_dvr {
     iniset $NEUTRON_CONF DEFAULT router_distributed True
     iniset $Q_L3_CONF_FILE DEFAULT agent_mode $Q_DVR_MODE
@@ -1240,164 +968,6 @@
 
     neutron_plugin_setup_interface_driver $1
 }
-
-# Create private IPv4 subnet
-function _neutron_create_private_subnet_v4 {
-    local project_id=$1
-    local subnet_params="--tenant-id $project_id "
-    subnet_params+="--ip_version 4 "
-    subnet_params+="--gateway $NETWORK_GATEWAY "
-    subnet_params+="--name $PRIVATE_SUBNET_NAME "
-    subnet_params+="$NET_ID $FIXED_RANGE"
-    local subnet_id
-    subnet_id=$(neutron subnet-create $subnet_params | grep ' id ' | get_field 2)
-    die_if_not_set $LINENO subnet_id "Failure creating private IPv4 subnet for $project_id"
-    echo $subnet_id
-}
-
-# Create private IPv6 subnet
-function _neutron_create_private_subnet_v6 {
-    local project_id=$1
-    die_if_not_set $LINENO IPV6_RA_MODE "IPV6 RA Mode not set"
-    die_if_not_set $LINENO IPV6_ADDRESS_MODE "IPV6 Address Mode not set"
-    local ipv6_modes="--ipv6-ra-mode $IPV6_RA_MODE --ipv6-address-mode $IPV6_ADDRESS_MODE"
-    local subnet_params="--tenant-id $project_id "
-    subnet_params+="--ip_version 6 "
-    subnet_params+="--gateway $IPV6_PRIVATE_NETWORK_GATEWAY "
-    subnet_params+="--name $IPV6_PRIVATE_SUBNET_NAME "
-    subnet_params+="$NET_ID $FIXED_RANGE_V6 $ipv6_modes"
-    local ipv6_subnet_id
-    ipv6_subnet_id=$(neutron subnet-create $subnet_params | grep ' id ' | get_field 2)
-    die_if_not_set $LINENO ipv6_subnet_id "Failure creating private IPv6 subnet for $project_id"
-    echo $ipv6_subnet_id
-}
-
-# Create public IPv4 subnet
-function _neutron_create_public_subnet_v4 {
-    local subnet_params+="--ip_version 4 "
-    subnet_params+="${Q_FLOATING_ALLOCATION_POOL:+--allocation-pool $Q_FLOATING_ALLOCATION_POOL} "
-    subnet_params+="--gateway $PUBLIC_NETWORK_GATEWAY "
-    subnet_params+="--name $PUBLIC_SUBNET_NAME "
-    subnet_params+="$EXT_NET_ID $FLOATING_RANGE "
-    subnet_params+="-- --enable_dhcp=False"
-    local id_and_ext_gw_ip
-    id_and_ext_gw_ip=$(neutron subnet-create $subnet_params | grep -e 'gateway_ip' -e ' id ')
-    die_if_not_set $LINENO id_and_ext_gw_ip "Failure creating public IPv4 subnet"
-    echo $id_and_ext_gw_ip
-}
-
-# Create public IPv6 subnet
-function _neutron_create_public_subnet_v6 {
-    local subnet_params="--ip_version 6 "
-    subnet_params+="--gateway $IPV6_PUBLIC_NETWORK_GATEWAY "
-    subnet_params+="--name $IPV6_PUBLIC_SUBNET_NAME "
-    subnet_params+="$EXT_NET_ID $IPV6_PUBLIC_RANGE "
-    subnet_params+="-- --enable_dhcp=False"
-    local ipv6_id_and_ext_gw_ip
-    ipv6_id_and_ext_gw_ip=$(neutron subnet-create $subnet_params | grep -e 'gateway_ip' -e ' id ')
-    die_if_not_set $LINENO ipv6_id_and_ext_gw_ip "Failure creating an IPv6 public subnet"
-    echo $ipv6_id_and_ext_gw_ip
-}
-
-# Configure neutron router for IPv4 public access
-function _neutron_configure_router_v4 {
-    neutron router-interface-add $ROUTER_ID $SUBNET_ID
-    # Create a public subnet on the external network
-    local id_and_ext_gw_ip
-    id_and_ext_gw_ip=$(_neutron_create_public_subnet_v4 $EXT_NET_ID)
-    local ext_gw_ip
-    ext_gw_ip=$(echo $id_and_ext_gw_ip  | get_field 2)
-    PUB_SUBNET_ID=$(echo $id_and_ext_gw_ip | get_field 5)
-    # Configure the external network as the default router gateway
-    neutron router-gateway-set $ROUTER_ID $EXT_NET_ID
-
-    # This logic is specific to using the l3-agent for layer 3
-    if is_service_enabled q-l3; then
-        # Configure and enable public bridge
-        local ext_gw_interface="none"
-        if is_neutron_ovs_base_plugin; then
-            ext_gw_interface=$(_neutron_get_ext_gw_interface)
-        elif [[ "$Q_AGENT" = "linuxbridge" ]]; then
-            # Search for the brq device the neutron router and network for $FIXED_RANGE
-            # will be using.
-            # e.x. brq3592e767-da for NET_ID 3592e767-da66-4bcb-9bec-cdb03cd96102
-            ext_gw_interface=brq${EXT_NET_ID:0:11}
-        fi
-        if [[ "$ext_gw_interface" != "none" ]]; then
-            local cidr_len=${FLOATING_RANGE#*/}
-            local testcmd="ip -o link | grep -q $ext_gw_interface"
-            test_with_retry "$testcmd" "$ext_gw_interface creation failed"
-            if [[ $(ip addr show dev $ext_gw_interface | grep -c $ext_gw_ip) == 0 && ( $Q_USE_PROVIDERNET_FOR_PUBLIC == "False" || $Q_USE_PUBLIC_VETH == "True" ) ]]; then
-                sudo ip addr add $ext_gw_ip/$cidr_len dev $ext_gw_interface
-                sudo ip link set $ext_gw_interface up
-            fi
-            ROUTER_GW_IP=`neutron port-list -c fixed_ips -c device_owner | grep router_gateway | awk -F'ip_address'  '{ print $2 }' | cut -f3 -d\" | tr '\n' ' '`
-            die_if_not_set $LINENO ROUTER_GW_IP "Failure retrieving ROUTER_GW_IP"
-            sudo ip route replace  $FIXED_RANGE via $ROUTER_GW_IP
-        fi
-        _neutron_set_router_id
-    fi
-}
-
-# Configure neutron router for IPv6 public access
-function _neutron_configure_router_v6 {
-    neutron router-interface-add $ROUTER_ID $IPV6_SUBNET_ID
-    # Create a public subnet on the external network
-    local ipv6_id_and_ext_gw_ip
-    ipv6_id_and_ext_gw_ip=$(_neutron_create_public_subnet_v6 $EXT_NET_ID)
-    local ipv6_ext_gw_ip
-    ipv6_ext_gw_ip=$(echo $ipv6_id_and_ext_gw_ip | get_field 2)
-    local ipv6_pub_subnet_id
-    ipv6_pub_subnet_id=$(echo $ipv6_id_and_ext_gw_ip | get_field 5)
-
-    # If the external network has not already been set as the default router
-    # gateway when configuring an IPv4 public subnet, do so now
-    if [[ "$IP_VERSION" == "6" ]]; then
-        neutron router-gateway-set $ROUTER_ID $EXT_NET_ID
-    fi
-
-    # This logic is specific to using the l3-agent for layer 3
-    if is_service_enabled q-l3; then
-        # Ensure IPv6 forwarding is enabled on the host
-        sudo sysctl -w net.ipv6.conf.all.forwarding=1
-        # Configure and enable public bridge
-        # Override global IPV6_ROUTER_GW_IP with the true value from neutron
-        IPV6_ROUTER_GW_IP=`neutron port-list -c fixed_ips | grep $ipv6_pub_subnet_id | awk -F'ip_address' '{ print $2 }' | cut -f3 -d\" | tr '\n' ' '`
-        die_if_not_set $LINENO IPV6_ROUTER_GW_IP "Failure retrieving IPV6_ROUTER_GW_IP"
-
-        if is_neutron_ovs_base_plugin; then
-            local ext_gw_interface
-            ext_gw_interface=$(_neutron_get_ext_gw_interface)
-            local ipv6_cidr_len=${IPV6_PUBLIC_RANGE#*/}
-
-            # Configure interface for public bridge
-            sudo ip -6 addr add $ipv6_ext_gw_ip/$ipv6_cidr_len dev $ext_gw_interface
-            sudo ip -6 route replace $FIXED_RANGE_V6 via $IPV6_ROUTER_GW_IP dev $ext_gw_interface
-        fi
-        _neutron_set_router_id
-    fi
-}
-
-# Explicitly set router id in l3 agent configuration
-function _neutron_set_router_id {
-    if [[ "$Q_L3_ROUTER_PER_TENANT" == "False" ]]; then
-        iniset $Q_L3_CONF_FILE DEFAULT router_id $ROUTER_ID
-    fi
-}
-
-# Get ext_gw_interface depending on value of Q_USE_PUBLIC_VETH
-function _neutron_get_ext_gw_interface {
-    if [[ "$Q_USE_PUBLIC_VETH" == "True" ]]; then
-        echo $Q_PUBLIC_VETH_EX
-    else
-        # Disable in-band as we are going to use local port
-        # to communicate with VMs
-        sudo ovs-vsctl set Bridge $PUBLIC_BRIDGE \
-            other_config:disable-in-band=true
-        echo $PUBLIC_BRIDGE
-    fi
-}
-
 # Functions for Neutron Exercises
 #--------------------------------
 
@@ -1408,26 +978,8 @@
     neutron-debug --os-tenant-name admin --os-username admin probe-delete $probe_id
 }
 
-function setup_neutron_debug {
-    if [[ "$Q_USE_DEBUG_COMMAND" == "True" ]]; then
-        public_net_id=`_get_net_id $PUBLIC_NETWORK_NAME`
-        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`
-        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
-}
-
-function teardown_neutron_debug {
-    delete_probe $PUBLIC_NETWORK_NAME
-    delete_probe $PRIVATE_NETWORK_NAME
-}
-
 function _get_net_id {
-    neutron --os-tenant-name admin --os-username admin --os-password $ADMIN_PASSWORD net-list | grep $1 | awk '{print $2}'
+    neutron --os-cloud devstack-admin --os-region "$REGION_NAME" --os-tenant-name admin --os-username admin --os-password $ADMIN_PASSWORD net-list | grep $1 | awk '{print $2}'
 }
 
 function _get_probe_cmd_prefix {
@@ -1450,63 +1002,6 @@
     test_with_retry "$testcmd" "server $ip didn't become ssh-able" $timeout_sec
 }
 
-# Neutron 3rd party programs
-#---------------------------
-
-# please refer to ``lib/neutron_thirdparty/README.md`` for details
-NEUTRON_THIRD_PARTIES=""
-for f in $TOP_DIR/lib/neutron_thirdparty/*; do
-    third_party=$(basename $f)
-    if is_service_enabled $third_party; then
-        source $TOP_DIR/lib/neutron_thirdparty/$third_party
-        NEUTRON_THIRD_PARTIES="$NEUTRON_THIRD_PARTIES,$third_party"
-    fi
-done
-
-function _neutron_third_party_do {
-    for third_party in ${NEUTRON_THIRD_PARTIES//,/ }; do
-        ${1}_${third_party}
-    done
-}
-
-# configure_neutron_third_party() - Set config files, create data dirs, etc
-function configure_neutron_third_party {
-    _neutron_third_party_do configure
-}
-
-# init_neutron_third_party() - Initialize databases, etc.
-function init_neutron_third_party {
-    _neutron_third_party_do init
-}
-
-# install_neutron_third_party() - Collect source and prepare
-function install_neutron_third_party {
-    _neutron_third_party_do install
-}
-
-# start_neutron_third_party() - Start running processes, including screen
-function start_neutron_third_party {
-    _neutron_third_party_do start
-}
-
-# stop_neutron_third_party - Stop running processes (non-screen)
-function stop_neutron_third_party {
-    _neutron_third_party_do stop
-}
-
-# check_neutron_third_party_integration() - Check that third party integration is sane
-function check_neutron_third_party_integration {
-    _neutron_third_party_do check
-}
-
-function is_provider_network {
-    if [ "$Q_USE_PROVIDER_NETWORKING" == "True" ] && [ "$Q_L3_ENABLED" == "False" ]; then
-        return 0
-    fi
-    return 1
-}
-
-
 # Restore xtrace
 $_XTRACE_NEUTRON
 
diff --git a/lib/neutron_plugins/linuxbridge_agent b/lib/neutron_plugins/linuxbridge_agent
index 096722b..e5a7b76 100644
--- a/lib/neutron_plugins/linuxbridge_agent
+++ b/lib/neutron_plugins/linuxbridge_agent
@@ -43,13 +43,16 @@
 }
 
 function neutron_plugin_configure_dhcp_agent {
-    iniset $Q_DHCP_CONF_FILE DEFAULT dhcp_agent_manager neutron.agent.dhcp_agent.DhcpAgentWithStateReport
+    local conf_file=$1
+    iniset $conf_file DEFAULT dhcp_agent_manager neutron.agent.dhcp_agent.DhcpAgentWithStateReport
 }
 
 function neutron_plugin_configure_l3_agent {
+    local conf_file=$1
     sudo brctl addbr $PUBLIC_BRIDGE
-    iniset $Q_L3_CONF_FILE DEFAULT external_network_bridge
-    iniset $Q_L3_CONF_FILE DEFAULT l3_agent_manager neutron.agent.l3_agent.L3NATAgentWithStateReport
+    set_mtu $PUBLIC_BRIDGE $PUBLIC_BRIDGE_MTU
+    iniset $conf_file DEFAULT external_network_bridge
+    iniset $conf_file DEFAULT l3_agent_manager neutron.agent.l3_agent.L3NATAgentWithStateReport
 }
 
 function neutron_plugin_configure_plugin_agent {
diff --git a/lib/neutron_plugins/ml2 b/lib/neutron_plugins/ml2
index 30e1b03..2ece210 100644
--- a/lib/neutron_plugins/ml2
+++ b/lib/neutron_plugins/ml2
@@ -25,20 +25,22 @@
 
 # List of MechanismDrivers to load
 Q_ML2_PLUGIN_MECHANISM_DRIVERS=${Q_ML2_PLUGIN_MECHANISM_DRIVERS:-openvswitch,linuxbridge}
-# 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
 Q_ML2_PLUGIN_GRE_TYPE_OPTIONS=${Q_ML2_PLUGIN_GRE_TYPE_OPTIONS:-tunnel_id_ranges=$TENANT_TUNNEL_RANGES}
 # Default VXLAN TypeDriver options
-Q_ML2_PLUGIN_VXLAN_TYPE_OPTIONS=${Q_ML2_PLUGIN_VXLAN_TYPE_OPTIONS:-vni_ranges=1001:2000}
+Q_ML2_PLUGIN_VXLAN_TYPE_OPTIONS=${Q_ML2_PLUGIN_VXLAN_TYPE_OPTIONS:-vni_ranges=$TENANT_TUNNEL_RANGES}
 # Default VLAN TypeDriver options
 Q_ML2_PLUGIN_VLAN_TYPE_OPTIONS=${Q_ML2_PLUGIN_VLAN_TYPE_OPTIONS:-}
+# Default GENEVE TypeDriver options
+Q_ML2_PLUGIN_GENEVE_TYPE_OPTIONS=${Q_ML2_PLUGIN_GENEVE_TYPE_OPTIONS:-vni_ranges=$TENANT_TUNNEL_RANGES}
 # List of extension drivers to load, use '-' instead of ':-' to allow people to
 # explicitly override this to blank
 Q_ML2_PLUGIN_EXT_DRIVERS=${Q_ML2_PLUGIN_EXT_DRIVERS-port_security}
 
 # L3 Plugin to load for ML2
-ML2_L3_PLUGIN=${ML2_L3_PLUGIN:-neutron.services.l3_router.l3_router_plugin.L3RouterPlugin}
+# For some flat network environment, they not want to extend L3 plugin.
+# Make sure it is able to set empty to ML2_L3_PLUGIN.
+ML2_L3_PLUGIN=${ML2_L3_PLUGIN-neutron.services.l3_router.l3_router_plugin.L3RouterPlugin}
 
 function populate_ml2_config {
     CONF=$1
@@ -111,7 +113,9 @@
 
     populate_ml2_config /$Q_PLUGIN_CONF_FILE ml2 mechanism_drivers=$Q_ML2_PLUGIN_MECHANISM_DRIVERS
 
-    populate_ml2_config /$Q_PLUGIN_CONF_FILE ml2 type_drivers=$Q_ML2_PLUGIN_TYPE_DRIVERS
+    if [[ -n "$Q_ML2_PLUGIN_TYPE_DRIVERS" ]]; then
+        populate_ml2_config /$Q_PLUGIN_CONF_FILE ml2 type_drivers=$Q_ML2_PLUGIN_TYPE_DRIVERS
+    fi
 
     populate_ml2_config /$Q_PLUGIN_CONF_FILE ml2 extension_drivers=$Q_ML2_PLUGIN_EXT_DRIVERS
 
@@ -125,6 +129,8 @@
 
     populate_ml2_config /$Q_PLUGIN_CONF_FILE ml2_type_vlan $Q_ML2_PLUGIN_VLAN_TYPE_OPTIONS
 
+    populate_ml2_config /$Q_PLUGIN_CONF_FILE ml2_type_geneve $Q_ML2_PLUGIN_GENEVE_TYPE_OPTIONS
+
     if [[ "$Q_DVR_MODE" != "legacy" ]]; then
         populate_ml2_config /$Q_PLUGIN_CONF_FILE agent l2_population=True
         populate_ml2_config /$Q_PLUGIN_CONF_FILE agent tunnel_types=vxlan
diff --git a/lib/neutron_plugins/openvswitch_agent b/lib/neutron_plugins/openvswitch_agent
index aba2587..b4a53e4 100644
--- a/lib/neutron_plugins/openvswitch_agent
+++ b/lib/neutron_plugins/openvswitch_agent
@@ -28,12 +28,14 @@
 }
 
 function neutron_plugin_configure_dhcp_agent {
-    iniset $Q_DHCP_CONF_FILE DEFAULT dhcp_agent_manager neutron.agent.dhcp_agent.DhcpAgentWithStateReport
+    local conf_file=$1
+    iniset $conf_file DEFAULT dhcp_agent_manager neutron.agent.dhcp_agent.DhcpAgentWithStateReport
 }
 
 function neutron_plugin_configure_l3_agent {
+    local conf_file=$1
     _neutron_ovs_base_configure_l3_agent
-    iniset $Q_L3_CONF_FILE DEFAULT l3_agent_manager neutron.agent.l3_agent.L3NATAgentWithStateReport
+    iniset $conf_file DEFAULT l3_agent_manager neutron.agent.l3_agent.L3NATAgentWithStateReport
 }
 
 function neutron_plugin_configure_plugin_agent {
@@ -102,7 +104,7 @@
         sudo ovs-vsctl -- --may-exist add-port "br-$VLAN_INTERFACE" $VLAN_INTERFACE
 
         # Create external bridge and add port
-        _neutron_ovs_base_add_bridge $PUBLIC_BRIDGE
+        _neutron_ovs_base_add_public_bridge
         sudo ovs-vsctl -- --may-exist add-port $PUBLIC_BRIDGE $PUBLIC_INTERFACE
 
         # Set bridge mappings to "physnet1:br-$GUEST_INTERFACE_DEFAULT"
diff --git a/lib/neutron_plugins/ovs_base b/lib/neutron_plugins/ovs_base
index 59c7737..f6d10ea 100644
--- a/lib/neutron_plugins/ovs_base
+++ b/lib/neutron_plugins/ovs_base
@@ -19,7 +19,7 @@
 
 function _neutron_ovs_base_add_bridge {
     local bridge=$1
-    local addbr_cmd="sudo ovs-vsctl --no-wait -- --may-exist add-br $bridge"
+    local addbr_cmd="sudo ovs-vsctl -- --may-exist add-br $bridge"
 
     if [ "$OVS_DATAPATH_TYPE" != "system" ] ; then
         addbr_cmd="$addbr_cmd -- set Bridge $bridge datapath_type=${OVS_DATAPATH_TYPE}"
@@ -54,7 +54,7 @@
     local kernel_major_minor
     kernel_major_minor=`echo $kernel_version | cut -d. -f1-2`
     # From kernel 3.13 on, openvswitch-datapath-dkms is not needed
-    if [ `vercmp_numbers "$kernel_major_minor" "3.13"` -lt "0" ]; then
+    if vercmp "$kernel_major_minor" "<" "3.13" ; then
         install_package "dkms openvswitch-datapath-dkms linux-headers-$kernel_version"
     fi
 }
@@ -105,11 +105,16 @@
         sudo ip link set $Q_PUBLIC_VETH_EX up
         sudo ip addr flush dev $Q_PUBLIC_VETH_EX
     else
-        _neutron_ovs_base_add_bridge $PUBLIC_BRIDGE
+        _neutron_ovs_base_add_public_bridge
         sudo ovs-vsctl br-set-external-id $PUBLIC_BRIDGE bridge-id $PUBLIC_BRIDGE
     fi
 }
 
+function _neutron_ovs_base_add_public_bridge {
+    _neutron_ovs_base_add_bridge $PUBLIC_BRIDGE
+    set_mtu $PUBLIC_BRIDGE $PUBLIC_BRIDGE_MTU
+}
+
 function _neutron_ovs_base_configure_nova_vif_driver {
     :
 }
diff --git a/lib/neutron_plugins/services/firewall b/lib/neutron_plugins/services/firewall
deleted file mode 100644
index 40968fa..0000000
--- a/lib/neutron_plugins/services/firewall
+++ /dev/null
@@ -1,33 +0,0 @@
-#!/bin/bash
-
-# Neutron firewall plugin
-# ---------------------------
-
-# Save trace setting
-_XTRACE_NEUTRON_FIREWALL=$(set +o | grep xtrace)
-set +o xtrace
-
-FWAAS_PLUGIN=${FWAAS_PLUGIN:-neutron_fwaas.services.firewall.fwaas_plugin.FirewallPlugin}
-FWAAS_DRIVER=${FWAAS_DRIVER:-neutron_fwaas.services.firewall.drivers.linux.iptables_fwaas.IptablesFwaasDriver}
-
-function neutron_fwaas_configure_common {
-    _neutron_service_plugin_class_add $FWAAS_PLUGIN
-}
-
-function neutron_fwaas_configure_driver {
-    # Uses oslo config generator to generate FWaaS sample configuration files
-    (cd $NEUTRON_FWAAS_DIR && exec ./tools/generate_config_file_samples.sh)
-
-    FWAAS_DRIVER_CONF_FILENAME=/etc/neutron/fwaas_driver.ini
-    cp $NEUTRON_FWAAS_DIR/etc/fwaas_driver.ini.sample $FWAAS_DRIVER_CONF_FILENAME
-
-    iniset_multiline $FWAAS_DRIVER_CONF_FILENAME fwaas enabled True
-    iniset_multiline $FWAAS_DRIVER_CONF_FILENAME fwaas driver "$FWAAS_DRIVER"
-}
-
-function neutron_fwaas_stop {
-    :
-}
-
-# Restore xtrace
-$_XTRACE_NEUTRON_FIREWALL
diff --git a/lib/neutron_plugins/services/l3 b/lib/neutron_plugins/services/l3
new file mode 100644
index 0000000..61b8402
--- /dev/null
+++ b/lib/neutron_plugins/services/l3
@@ -0,0 +1,381 @@
+#!/bin/bash
+# Subnet IP version
+IP_VERSION=${IP_VERSION:-"4+6"}
+# Validate IP_VERSION
+if [[ $IP_VERSION != "4" ]] && [[ $IP_VERSION != "6" ]] && [[ $IP_VERSION != "4+6" ]]; then
+    die $LINENO "IP_VERSION must be either 4, 6, or 4+6"
+fi
+# Specify if the initial private and external networks should be created
+NEUTRON_CREATE_INITIAL_NETWORKS=${NEUTRON_CREATE_INITIAL_NETWORKS:-True}
+
+## Provider Network Information
+PROVIDER_SUBNET_NAME=${PROVIDER_SUBNET_NAME:-"provider_net"}
+IPV6_PROVIDER_SUBNET_NAME=${IPV6_PROVIDER_SUBNET_NAME:-"provider_net_v6"}
+IPV6_PROVIDER_FIXED_RANGE=${IPV6_PROVIDER_FIXED_RANGE:-}
+IPV6_PROVIDER_NETWORK_GATEWAY=${IPV6_PROVIDER_NETWORK_GATEWAY:-}
+
+PUBLIC_BRIDGE=${PUBLIC_BRIDGE:-br-ex}
+PUBLIC_BRIDGE_MTU=${PUBLIC_BRIDGE_MTU:-1500}
+
+# If Q_USE_PUBLIC_VETH=True, create and use a veth pair instead of
+# PUBLIC_BRIDGE.  This is intended to be used with
+# Q_USE_PROVIDERNET_FOR_PUBLIC=True.
+Q_USE_PUBLIC_VETH=${Q_USE_PUBLIC_VETH:-False}
+Q_PUBLIC_VETH_EX=${Q_PUBLIC_VETH_EX:-veth-pub-ex}
+Q_PUBLIC_VETH_INT=${Q_PUBLIC_VETH_INT:-veth-pub-int}
+
+# The next variable is configured by plugin
+# e.g.  _configure_neutron_l3_agent or lib/neutron_plugins/*
+#
+# L3 routers exist per tenant
+Q_L3_ROUTER_PER_TENANT=${Q_L3_ROUTER_PER_TENANT:-True}
+
+
+# Use flat providernet for public network
+#
+# If Q_USE_PROVIDERNET_FOR_PUBLIC=True, use a flat provider network
+# for external interface of neutron l3-agent.  In that case,
+# PUBLIC_PHYSICAL_NETWORK specifies provider:physical_network value
+# used for the network.  In case of ofagent, you should add the
+# corresponding entry to your OFAGENT_PHYSICAL_INTERFACE_MAPPINGS.
+# For openvswitch agent, you should add the corresponding entry to
+# your OVS_BRIDGE_MAPPINGS.
+#
+# eg.  (ofagent)
+#    Q_USE_PROVIDERNET_FOR_PUBLIC=True
+#    Q_USE_PUBLIC_VETH=True
+#    PUBLIC_PHYSICAL_NETWORK=public
+#    OFAGENT_PHYSICAL_INTERFACE_MAPPINGS=public:veth-pub-int
+#
+# eg.  (openvswitch agent)
+#    Q_USE_PROVIDERNET_FOR_PUBLIC=True
+#    PUBLIC_PHYSICAL_NETWORK=public
+#    OVS_BRIDGE_MAPPINGS=public:br-ex
+Q_USE_PROVIDERNET_FOR_PUBLIC=${Q_USE_PROVIDERNET_FOR_PUBLIC:-False}
+PUBLIC_PHYSICAL_NETWORK=${PUBLIC_PHYSICAL_NETWORK:-public}
+
+# Generate 40-bit IPv6 Global ID to comply with RFC 4193
+IPV6_GLOBAL_ID=`uuidgen | sed s/-//g | cut -c 23- | sed -e "s/\(..\)\(....\)\(....\)/\1:\2:\3/"`
+
+# IPv6 gateway and subnet defaults, in case they are not customized in localrc
+IPV6_RA_MODE=${IPV6_RA_MODE:-slaac}
+IPV6_ADDRESS_MODE=${IPV6_ADDRESS_MODE:-slaac}
+IPV6_PUBLIC_SUBNET_NAME=${IPV6_PUBLIC_SUBNET_NAME:-ipv6-public-subnet}
+IPV6_PRIVATE_SUBNET_NAME=${IPV6_PRIVATE_SUBNET_NAME:-ipv6-private-subnet}
+FIXED_RANGE_V6=${FIXED_RANGE_V6:-fd$IPV6_GLOBAL_ID::/64}
+IPV6_PRIVATE_NETWORK_GATEWAY=${IPV6_PRIVATE_NETWORK_GATEWAY:-fd$IPV6_GLOBAL_ID::1}
+IPV6_PUBLIC_RANGE=${IPV6_PUBLIC_RANGE:-2001:db8::/64}
+IPV6_PUBLIC_NETWORK_GATEWAY=${IPV6_PUBLIC_NETWORK_GATEWAY:-2001:db8::2}
+IPV6_ROUTER_GW_IP=${IPV6_ROUTER_GW_IP:-2001:db8::1}
+
+# Gateway and subnet defaults, in case they are not customized in localrc
+NETWORK_GATEWAY=${NETWORK_GATEWAY:-10.0.0.1}
+PUBLIC_NETWORK_GATEWAY=${PUBLIC_NETWORK_GATEWAY:-172.24.4.1}
+PRIVATE_SUBNET_NAME=${PRIVATE_SUBNET_NAME:-"private-subnet"}
+PUBLIC_SUBNET_NAME=${PUBLIC_SUBNET_NAME:-"public-subnet"}
+
+# Subnetpool defaults
+SUBNETPOOL_NAME=${SUBNETPOOL_NAME:-"shared-default-subnetpool"}
+
+SUBNETPOOL_PREFIX_V4=${SUBNETPOOL_PREFIX_V4:-10.0.0.0/8}
+SUBNETPOOL_PREFIX_V6=${SUBNETPOOL_PREFIX_V6:-2001:db8:8000::/48}
+
+SUBNETPOOL_SIZE_V4=${SUBNETPOOL_SIZE_V4:-24}
+SUBNETPOOL_SIZE_V6=${SUBNETPOOL_SIZE_V6:-64}
+
+function _determine_config_l3 {
+    local opts="--config-file $NEUTRON_CONF --config-file $Q_L3_CONF_FILE"
+    echo "$opts"
+}
+
+function _configure_neutron_l3_agent {
+
+    cp $NEUTRON_DIR/etc/l3_agent.ini.sample $Q_L3_CONF_FILE
+
+    iniset $Q_L3_CONF_FILE DEFAULT debug $ENABLE_DEBUG_LOG_LEVEL
+    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"
+    fi
+
+    _neutron_setup_interface_driver $Q_L3_CONF_FILE
+
+    neutron_plugin_configure_l3_agent $Q_L3_CONF_FILE
+
+    # If we've given a PUBLIC_INTERFACE to take over, then we assume
+    # that we can own the whole thing, and privot it into the OVS
+    # bridge. If we are not, we're probably on a single interface
+    # machine, and we just setup NAT so that fixed guests can get out.
+    if [[ -n "$PUBLIC_INTERFACE" ]]; then
+        _move_neutron_addresses_route "$PUBLIC_INTERFACE" "$OVS_PHYSICAL_BRIDGE" True False "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 False "inet6"
+        fi
+    else
+        local default_dev=""
+        default_dev=$(ip route | grep ^default | awk '{print $5}')
+        sudo iptables -t nat -A POSTROUTING -o $default_dev -s $FLOATING_RANGE -j MASQUERADE
+    fi
+}
+
+# Explicitly set router id in l3 agent configuration
+function _neutron_set_router_id {
+    if [[ "$Q_L3_ROUTER_PER_TENANT" == "False" ]]; then
+        iniset $Q_L3_CONF_FILE DEFAULT router_id $ROUTER_ID
+    fi
+}
+
+# Get ext_gw_interface depending on value of Q_USE_PUBLIC_VETH
+function _neutron_get_ext_gw_interface {
+    if [[ "$Q_USE_PUBLIC_VETH" == "True" ]]; then
+        echo $Q_PUBLIC_VETH_EX
+    else
+        # Disable in-band as we are going to use local port
+        # to communicate with VMs
+        sudo ovs-vsctl set Bridge $PUBLIC_BRIDGE \
+            other_config:disable-in-band=true
+        echo $PUBLIC_BRIDGE
+    fi
+}
+
+function create_neutron_initial_network {
+    local project_id
+    project_id=$(openstack project list | grep " demo " | get_field 1)
+    die_if_not_set $LINENO project_id "Failure retrieving project_id for demo"
+
+    # Allow drivers that need to create an initial network to do so here
+    if type -p neutron_plugin_create_initial_network_profile > /dev/null; then
+        neutron_plugin_create_initial_network_profile $PHYSICAL_NETWORK
+    fi
+
+    if is_provider_network; then
+        die_if_not_set $LINENO PHYSICAL_NETWORK "You must specify the PHYSICAL_NETWORK"
+        die_if_not_set $LINENO PROVIDER_NETWORK_TYPE "You must specify the PROVIDER_NETWORK_TYPE"
+        NET_ID=$(neutron --os-cloud devstack-admin --os-region "$REGION_NAME" net-create $PHYSICAL_NETWORK --tenant_id $project_id --provider:network_type $PROVIDER_NETWORK_TYPE --provider:physical_network "$PHYSICAL_NETWORK" ${SEGMENTATION_ID:+--provider:segmentation_id $SEGMENTATION_ID} --shared | grep ' id ' | get_field 2)
+        die_if_not_set $LINENO NET_ID "Failure creating NET_ID for $PHYSICAL_NETWORK $project_id"
+
+        if [[ "$IP_VERSION" =~ 4.* ]]; then
+            SUBNET_ID=$(neutron --os-cloud devstack-admin --os-region "$REGION_NAME" subnet-create --tenant_id $project_id --ip_version 4 ${ALLOCATION_POOL:+--allocation-pool $ALLOCATION_POOL} --name $PROVIDER_SUBNET_NAME --gateway $NETWORK_GATEWAY $NET_ID $FIXED_RANGE | grep ' id ' | get_field 2)
+            die_if_not_set $LINENO SUBNET_ID "Failure creating SUBNET_ID for $PROVIDER_SUBNET_NAME $project_id"
+        fi
+
+        if [[ "$IP_VERSION" =~ .*6 ]]; then
+            die_if_not_set $LINENO IPV6_PROVIDER_FIXED_RANGE "IPV6_PROVIDER_FIXED_RANGE has not been set, but Q_USE_PROVIDERNET_FOR_PUBLIC is true and IP_VERSION includes 6"
+            die_if_not_set $LINENO IPV6_PROVIDER_NETWORK_GATEWAY "IPV6_PROVIDER_NETWORK_GATEWAY has not been set, but Q_USE_PROVIDERNET_FOR_PUBLIC is true and IP_VERSION includes 6"
+            SUBNET_V6_ID=$(neutron --os-cloud devstack-admin --os-region "$REGION_NAME" subnet-create --tenant_id $project_id --ip_version 6 --ipv6-address-mode $IPV6_ADDRESS_MODE --gateway $IPV6_PROVIDER_NETWORK_GATEWAY --name $IPV6_PROVIDER_SUBNET_NAME $NET_ID $IPV6_PROVIDER_FIXED_RANGE | grep 'id' | get_field 2)
+            die_if_not_set $LINENO SUBNET_V6_ID "Failure creating SUBNET_V6_ID for $IPV6_PROVIDER_SUBNET_NAME $project_id"
+        fi
+
+        if [[ $Q_AGENT == "openvswitch" ]]; then
+            sudo ip link set $OVS_PHYSICAL_BRIDGE up
+            sudo ip link set br-int up
+            sudo ip link set $PUBLIC_INTERFACE up
+        fi
+    else
+        NET_ID=$(neutron --os-cloud devstack-admin --os-region "$REGION_NAME" net-create --tenant-id $project_id "$PRIVATE_NETWORK_NAME" | grep ' id ' | get_field 2)
+        die_if_not_set $LINENO NET_ID "Failure creating NET_ID for $PRIVATE_NETWORK_NAME $project_id"
+
+        if [[ "$IP_VERSION" =~ 4.* ]]; then
+            # Create IPv4 private subnet
+            SUBNET_ID=$(_neutron_create_private_subnet_v4 $project_id)
+        fi
+
+        if [[ "$IP_VERSION" =~ .*6 ]]; then
+            # Create IPv6 private subnet
+            IPV6_SUBNET_ID=$(_neutron_create_private_subnet_v6 $project_id)
+        fi
+    fi
+
+    if is_networking_extension_supported "router" && is_networking_extension_supported "external-net"; then
+        # Create a router, and add the private subnet as one of its interfaces
+        if [[ "$Q_L3_ROUTER_PER_TENANT" == "True" ]]; then
+            # create a tenant-owned router.
+            ROUTER_ID=$(neutron --os-cloud devstack-admin --os-region "$REGION_NAME" router-create --tenant-id $project_id $Q_ROUTER_NAME | grep ' id ' | get_field 2)
+            die_if_not_set $LINENO ROUTER_ID "Failure creating ROUTER_ID for $project_id $Q_ROUTER_NAME"
+        else
+            # Plugin only supports creating a single router, which should be admin owned.
+            ROUTER_ID=$(neutron --os-cloud devstack-admin --os-region "$REGION_NAME" router-create $Q_ROUTER_NAME | grep ' id ' | get_field 2)
+            die_if_not_set $LINENO ROUTER_ID "Failure creating ROUTER_ID for $Q_ROUTER_NAME"
+        fi
+
+        EXTERNAL_NETWORK_FLAGS="--router:external"
+        if is_networking_extension_supported "auto-allocated-topology" && is_networking_extension_supported "subnet_allocation"; then
+            EXTERNAL_NETWORK_FLAGS="$EXTERNAL_NETWORK_FLAGS --is-default"
+            if [[ "$IP_VERSION" =~ 4.* ]]; then
+                SUBNETPOOL_V4_ID=$(neutron --os-cloud devstack-admin --os-region "$REGION_NAME" subnetpool-create $SUBNETPOOL_NAME --default-prefixlen $SUBNETPOOL_SIZE_V4 --pool-prefix $SUBNETPOOL_PREFIX_V4 --shared --is-default=True | grep ' id ' | get_field 2)
+            fi
+            if [[ "$IP_VERSION" =~ .*6 ]]; then
+                SUBNETPOOL_V6_ID=$(neutron --os-cloud devstack-admin --os-region "$REGION_NAME" subnetpool-create $SUBNETPOOL_NAME --default-prefixlen $SUBNETPOOL_SIZE_V6 --pool-prefix $SUBNETPOOL_PREFIX_V6 --shared --is-default=True | grep ' id ' | get_field 2)
+            fi
+        fi
+        # Create an external network, and a subnet. Configure the external network as router gw
+        if [ "$Q_USE_PROVIDERNET_FOR_PUBLIC" = "True" ]; then
+            EXT_NET_ID=$(neutron --os-cloud devstack-admin --os-region "$REGION_NAME" net-create "$PUBLIC_NETWORK_NAME" -- $EXTERNAL_NETWORK_FLAGS --provider:network_type=flat --provider:physical_network=${PUBLIC_PHYSICAL_NETWORK} | grep ' id ' | get_field 2)
+        else
+            EXT_NET_ID=$(neutron --os-cloud devstack-admin --os-region "$REGION_NAME" net-create "$PUBLIC_NETWORK_NAME" -- $EXTERNAL_NETWORK_FLAGS | grep ' id ' | get_field 2)
+        fi
+        die_if_not_set $LINENO EXT_NET_ID "Failure creating EXT_NET_ID for $PUBLIC_NETWORK_NAME"
+
+        if [[ "$IP_VERSION" =~ 4.* ]]; then
+            # Configure router for IPv4 public access
+            _neutron_configure_router_v4
+        fi
+
+        if [[ "$IP_VERSION" =~ .*6 ]]; then
+            # Configure router for IPv6 public access
+            _neutron_configure_router_v6
+        fi
+    fi
+}
+
+# Create private IPv4 subnet
+function _neutron_create_private_subnet_v4 {
+    local project_id=$1
+    local subnet_params="--tenant-id $project_id "
+    subnet_params+="--ip_version 4 "
+    subnet_params+="--gateway $NETWORK_GATEWAY "
+    subnet_params+="--name $PRIVATE_SUBNET_NAME "
+    subnet_params+="$NET_ID $FIXED_RANGE"
+    local subnet_id
+    subnet_id=$(neutron --os-cloud devstack-admin --os-region "$REGION_NAME" subnet-create $subnet_params | grep ' id ' | get_field 2)
+    die_if_not_set $LINENO subnet_id "Failure creating private IPv4 subnet for $project_id"
+    echo $subnet_id
+}
+
+# Create private IPv6 subnet
+function _neutron_create_private_subnet_v6 {
+    local project_id=$1
+    die_if_not_set $LINENO IPV6_RA_MODE "IPV6 RA Mode not set"
+    die_if_not_set $LINENO IPV6_ADDRESS_MODE "IPV6 Address Mode not set"
+    local ipv6_modes="--ipv6-ra-mode $IPV6_RA_MODE --ipv6-address-mode $IPV6_ADDRESS_MODE"
+    local subnet_params="--tenant-id $project_id "
+    subnet_params+="--ip_version 6 "
+    subnet_params+="--gateway $IPV6_PRIVATE_NETWORK_GATEWAY "
+    subnet_params+="--name $IPV6_PRIVATE_SUBNET_NAME "
+    subnet_params+="$NET_ID $FIXED_RANGE_V6 $ipv6_modes"
+    local ipv6_subnet_id
+    ipv6_subnet_id=$(neutron --os-cloud devstack-admin --os-region "$REGION_NAME" subnet-create $subnet_params | grep ' id ' | get_field 2)
+    die_if_not_set $LINENO ipv6_subnet_id "Failure creating private IPv6 subnet for $project_id"
+    echo $ipv6_subnet_id
+}
+
+# Create public IPv4 subnet
+function _neutron_create_public_subnet_v4 {
+    local subnet_params+="--ip_version 4 "
+    subnet_params+="${Q_FLOATING_ALLOCATION_POOL:+--allocation-pool $Q_FLOATING_ALLOCATION_POOL} "
+    subnet_params+="--gateway $PUBLIC_NETWORK_GATEWAY "
+    subnet_params+="--name $PUBLIC_SUBNET_NAME "
+    subnet_params+="$EXT_NET_ID $FLOATING_RANGE "
+    subnet_params+="-- --enable_dhcp=False"
+    local id_and_ext_gw_ip
+    id_and_ext_gw_ip=$(neutron --os-cloud devstack-admin --os-region "$REGION_NAME" subnet-create $subnet_params | grep -e 'gateway_ip' -e ' id ')
+    die_if_not_set $LINENO id_and_ext_gw_ip "Failure creating public IPv4 subnet"
+    echo $id_and_ext_gw_ip
+}
+
+# Create public IPv6 subnet
+function _neutron_create_public_subnet_v6 {
+    local subnet_params="--ip_version 6 "
+    subnet_params+="--gateway $IPV6_PUBLIC_NETWORK_GATEWAY "
+    subnet_params+="--name $IPV6_PUBLIC_SUBNET_NAME "
+    subnet_params+="$EXT_NET_ID $IPV6_PUBLIC_RANGE "
+    subnet_params+="-- --enable_dhcp=False"
+    local ipv6_id_and_ext_gw_ip
+    ipv6_id_and_ext_gw_ip=$(neutron --os-cloud devstack-admin --os-region "$REGION_NAME" subnet-create $subnet_params | grep -e 'gateway_ip' -e ' id ')
+    die_if_not_set $LINENO ipv6_id_and_ext_gw_ip "Failure creating an IPv6 public subnet"
+    echo $ipv6_id_and_ext_gw_ip
+}
+
+# Configure neutron router for IPv4 public access
+function _neutron_configure_router_v4 {
+    neutron --os-cloud devstack-admin --os-region "$REGION_NAME" router-interface-add $ROUTER_ID $SUBNET_ID
+    # Create a public subnet on the external network
+    local id_and_ext_gw_ip
+    id_and_ext_gw_ip=$(_neutron_create_public_subnet_v4 $EXT_NET_ID)
+    local ext_gw_ip
+    ext_gw_ip=$(echo $id_and_ext_gw_ip  | get_field 2)
+    PUB_SUBNET_ID=$(echo $id_and_ext_gw_ip | get_field 5)
+    # Configure the external network as the default router gateway
+    neutron --os-cloud devstack-admin --os-region "$REGION_NAME" router-gateway-set $ROUTER_ID $EXT_NET_ID
+
+    # This logic is specific to using the l3-agent for layer 3
+    if is_service_enabled q-l3 || is_service_enabled neutron-l3;  then
+        # Configure and enable public bridge
+        local ext_gw_interface="none"
+        if is_neutron_ovs_base_plugin; then
+            ext_gw_interface=$(_neutron_get_ext_gw_interface)
+        elif [[ "$Q_AGENT" = "linuxbridge" ]]; then
+            # Search for the brq device the neutron router and network for $FIXED_RANGE
+            # will be using.
+            # e.x. brq3592e767-da for NET_ID 3592e767-da66-4bcb-9bec-cdb03cd96102
+            ext_gw_interface=brq${EXT_NET_ID:0:11}
+        fi
+        if [[ "$ext_gw_interface" != "none" ]]; then
+            local cidr_len=${FLOATING_RANGE#*/}
+            local testcmd="ip -o link | grep -q $ext_gw_interface"
+            test_with_retry "$testcmd" "$ext_gw_interface creation failed"
+            if [[ $(ip addr show dev $ext_gw_interface | grep -c $ext_gw_ip) == 0 && ( $Q_USE_PROVIDERNET_FOR_PUBLIC == "False" || $Q_USE_PUBLIC_VETH == "True" ) ]]; then
+                sudo ip addr add $ext_gw_ip/$cidr_len dev $ext_gw_interface
+                sudo ip link set $ext_gw_interface up
+            fi
+            ROUTER_GW_IP=$(neutron --os-cloud devstack-admin --os-region "$REGION_NAME" port-list -c fixed_ips -c device_owner | grep router_gateway | awk -F'ip_address'  '{ print $2 }' | cut -f3 -d\" | tr '\n' ' ')
+            die_if_not_set $LINENO ROUTER_GW_IP "Failure retrieving ROUTER_GW_IP"
+            sudo ip route replace  $FIXED_RANGE via $ROUTER_GW_IP
+        fi
+        _neutron_set_router_id
+    fi
+}
+
+# Configure neutron router for IPv6 public access
+function _neutron_configure_router_v6 {
+    neutron --os-cloud devstack-admin --os-region "$REGION_NAME" router-interface-add $ROUTER_ID $IPV6_SUBNET_ID
+    # Create a public subnet on the external network
+    local ipv6_id_and_ext_gw_ip
+    ipv6_id_and_ext_gw_ip=$(_neutron_create_public_subnet_v6 $EXT_NET_ID)
+    local ipv6_ext_gw_ip
+    ipv6_ext_gw_ip=$(echo $ipv6_id_and_ext_gw_ip | get_field 2)
+    local ipv6_pub_subnet_id
+    ipv6_pub_subnet_id=$(echo $ipv6_id_and_ext_gw_ip | get_field 5)
+
+    # If the external network has not already been set as the default router
+    # gateway when configuring an IPv4 public subnet, do so now
+    if [[ "$IP_VERSION" == "6" ]]; then
+        neutron --os-cloud devstack-admin --os-region "$REGION_NAME" router-gateway-set $ROUTER_ID $EXT_NET_ID
+    fi
+
+    # This logic is specific to using the l3-agent for layer 3
+    if is_service_enabled q-l3 || is_service_enabled neutron-l3; then
+        # Ensure IPv6 forwarding is enabled on the host
+        sudo sysctl -w net.ipv6.conf.all.forwarding=1
+        # Configure and enable public bridge
+        # Override global IPV6_ROUTER_GW_IP with the true value from neutron
+        IPV6_ROUTER_GW_IP=$(neutron --os-cloud devstack-admin --os-region "$REGION_NAME" port-list -c fixed_ips | grep $ipv6_pub_subnet_id | awk -F'ip_address' '{ print $2 }' | cut -f3 -d\" | tr '\n' ' ')
+        die_if_not_set $LINENO IPV6_ROUTER_GW_IP "Failure retrieving IPV6_ROUTER_GW_IP"
+
+        if is_neutron_ovs_base_plugin; then
+            local ext_gw_interface
+            ext_gw_interface=$(_neutron_get_ext_gw_interface)
+            local ipv6_cidr_len=${IPV6_PUBLIC_RANGE#*/}
+
+            # Configure interface for public bridge
+            sudo ip -6 addr replace $ipv6_ext_gw_ip/$ipv6_cidr_len dev $ext_gw_interface
+            sudo ip -6 route replace $FIXED_RANGE_V6 via $IPV6_ROUTER_GW_IP dev $ext_gw_interface
+        fi
+        _neutron_set_router_id
+    fi
+}
+
+function is_provider_network {
+    if [ "$Q_USE_PROVIDER_NETWORKING" == "True" ]; then
+        return 0
+    fi
+    return 1
+}
+
+function is_networking_extension_supported {
+    local extension=$1
+    # TODO(sc68cal) cache this instead of calling every time
+    EXT_LIST=$(neutron --os-cloud devstack-admin --os-region "$REGION_NAME" ext-list -c alias -f value)
+    [[ $EXT_LIST =~ $extension ]] && return 0
+}
diff --git a/lib/neutron_plugins/services/loadbalancer b/lib/neutron_plugins/services/loadbalancer
new file mode 100644
index 0000000..30e9480
--- /dev/null
+++ b/lib/neutron_plugins/services/loadbalancer
@@ -0,0 +1,51 @@
+#!/bin/bash
+
+# Neutron loadbalancer plugin
+# ---------------------------
+
+# Save trace setting
+_XTRACE_NEUTRON_LB=$(set +o | grep xtrace)
+set +o xtrace
+
+
+AGENT_LBAAS_BINARY="$NEUTRON_BIN_DIR/neutron-lbaas-agent"
+LBAAS_PLUGIN=neutron_lbaas.services.loadbalancer.plugin.LoadBalancerPlugin
+
+function neutron_agent_lbaas_install_agent_packages {
+    if is_ubuntu || is_fedora || is_suse; then
+        install_package haproxy
+    fi
+}
+
+function neutron_agent_lbaas_configure_common {
+    _neutron_service_plugin_class_add $LBAAS_PLUGIN
+    _neutron_deploy_rootwrap_filters $NEUTRON_LBAAS_DIR
+}
+
+function neutron_agent_lbaas_configure_agent {
+    LBAAS_AGENT_CONF_PATH=/etc/neutron/services/loadbalancer/haproxy
+    mkdir -p $LBAAS_AGENT_CONF_PATH
+
+    LBAAS_AGENT_CONF_FILENAME="$LBAAS_AGENT_CONF_PATH/lbaas_agent.ini"
+
+    cp $NEUTRON_LBAAS_DIR/etc/lbaas_agent.ini.sample $LBAAS_AGENT_CONF_FILENAME
+
+    # ovs_use_veth needs to be set before the plugin configuration
+    # occurs to allow plugins to override the setting.
+    iniset $LBAAS_AGENT_CONF_FILENAME DEFAULT ovs_use_veth $Q_OVS_USE_VETH
+
+    neutron_plugin_setup_interface_driver $LBAAS_AGENT_CONF_FILENAME
+
+    if is_fedora; then
+        iniset $LBAAS_AGENT_CONF_FILENAME DEFAULT user_group "nobody"
+        iniset $LBAAS_AGENT_CONF_FILENAME haproxy user_group "nobody"
+    fi
+}
+
+function neutron_lbaas_stop {
+    pids=$(ps aux | awk '/haproxy/ { print $2 }')
+    [ ! -z "$pids" ] && sudo kill $pids || true
+}
+
+# Restore xtrace
+$_XTRACE_NEUTRON_LB
diff --git a/lib/neutron_plugins/services/vpn b/lib/neutron_plugins/services/vpn
deleted file mode 100644
index e790913..0000000
--- a/lib/neutron_plugins/services/vpn
+++ /dev/null
@@ -1,58 +0,0 @@
-#!/bin/bash
-
-# Neutron VPN plugin
-# ---------------------------
-
-# Save trace setting
-_XTRACE_NEUTRON_VPN=$(set +o | grep xtrace)
-set +o xtrace
-
-
-AGENT_VPN_BINARY="$NEUTRON_BIN_DIR/neutron-vpn-agent"
-VPN_PLUGIN=${VPN_PLUGIN:-"neutron_vpnaas.services.vpn.plugin.VPNDriverPlugin"}
-IPSEC_PACKAGE=${IPSEC_PACKAGE:-"openswan"}
-
-function neutron_vpn_install_agent_packages {
-    install_package $IPSEC_PACKAGE
-    if is_ubuntu && [[ "$IPSEC_PACKAGE" == "strongswan" ]]; then
-        sudo ln -sf /etc/apparmor.d/usr.lib.ipsec.charon /etc/apparmor.d/disable/
-        sudo ln -sf /etc/apparmor.d/usr.lib.ipsec.stroke /etc/apparmor.d/disable/
-        # NOTE: Due to https://bugs.launchpad.net/ubuntu/+source/apparmor/+bug/1387220
-        # one must use 'sudo start apparmor ACTION=reload' for Ubuntu 14.10
-        restart_service apparmor
-    fi
-}
-
-function neutron_vpn_configure_common {
-    _neutron_service_plugin_class_add $VPN_PLUGIN
-    _neutron_deploy_rootwrap_filters $NEUTRON_VPNAAS_DIR
-}
-
-function neutron_vpn_configure_agent {
-    # Uses oslo config generator to generate LBaaS sample configuration files
-    (cd $NEUTRON_VPNAAS_DIR && exec ./tools/generate_config_file_samples.sh)
-    cp $NEUTRON_VPNAAS_DIR/etc/vpn_agent.ini.sample $Q_VPN_CONF_FILE
-    if [[ "$IPSEC_PACKAGE" == "strongswan" ]]; then
-        iniset_multiline $Q_VPN_CONF_FILE vpnagent vpn_device_driver neutron_vpnaas.services.vpn.device_drivers.strongswan_ipsec.StrongSwanDriver
-        if is_fedora; then
-            iniset $Q_VPN_CONF_FILE strongswan default_config_area /usr/share/strongswan/templates/config/strongswan.d
-        fi
-    else
-        iniset_multiline $Q_VPN_CONF_FILE vpnagent vpn_device_driver neutron_vpnaas.services.vpn.device_drivers.ipsec.OpenSwanDriver
-    fi
-}
-
-function neutron_vpn_stop {
-    local ipsec_data_dir=$DATA_DIR/neutron/ipsec
-    local pids
-    if [ -d $ipsec_data_dir ]; then
-        pids=$(find $ipsec_data_dir -name 'pluto.pid' -exec cat {} \;)
-    fi
-    if [ -n "$pids" ]; then
-        sudo kill $pids
-    fi
-    stop_process q-vpn
-}
-
-# Restore xtrace
-$_XTRACE_NEUTRON_VPN
diff --git a/lib/neutron_thirdparty/README.md b/lib/neutron_thirdparty/README.md
deleted file mode 100644
index 905ae77..0000000
--- a/lib/neutron_thirdparty/README.md
+++ /dev/null
@@ -1,41 +0,0 @@
-Neutron third party specific files
-==================================
-Some Neutron plugins require third party programs to function.
-The files under the directory, ``lib/neutron_thirdparty/``, will be used
-when their service are enabled.
-Third party program specific configuration variables should be in this file.
-
-* filename: ``<third_party>``
-  * The corresponding file name should be same to service name, ``<third_party>``.
-
-functions
----------
-``lib/neutron-legacy`` calls the following functions when the ``<third_party>`` is enabled
-
-functions to be implemented
-* ``configure_<third_party>``:
-  set config files, create data dirs, etc
-  e.g.
-  sudo python setup.py deploy
-  iniset $XXXX_CONF...
-
-* ``init_<third_party>``:
-  initialize databases, etc
-
-* ``install_<third_party>``:
-  collect source and prepare
-  e.g.
-  git clone xxx
-
-* ``start_<third_party>``:
-  start running processes, including screen if USE_SCREEN=True
-  e.g.
-  run_process XXXX "$XXXX_DIR/bin/XXXX-bin"
-
-* ``stop_<third_party>``:
-  stop running processes (non-screen)
-  e.g.
-  stop_process XXXX
-
-* ``check_<third_party>``:
-  verify that the integration between neutron server and third-party components is sane
diff --git a/lib/neutron_thirdparty/bigswitch_floodlight b/lib/neutron_thirdparty/bigswitch_floodlight
deleted file mode 100644
index 45a4f2e..0000000
--- a/lib/neutron_thirdparty/bigswitch_floodlight
+++ /dev/null
@@ -1,54 +0,0 @@
-#!/bin/bash
-#
-# Big Switch/FloodLight  OpenFlow Controller
-# ------------------------------------------
-
-# Save trace setting
-_XTRACE_NEUTRON_BIGSWITCH=$(set +o | grep xtrace)
-set +o xtrace
-
-BS_FL_CONTROLLERS_PORT=${BS_FL_CONTROLLERS_PORT:-localhost:80}
-BS_FL_OF_PORT=${BS_FL_OF_PORT:-6633}
-
-function configure_bigswitch_floodlight {
-    :
-}
-
-function init_bigswitch_floodlight {
-    install_neutron_agent_packages
-
-    echo -n "Installing OVS managed by the openflow controllers:"
-    echo ${BS_FL_CONTROLLERS_PORT}
-
-    # Create local OVS bridge and configure it
-    sudo ovs-vsctl --no-wait -- --if-exists del-br ${OVS_BRIDGE}
-    sudo ovs-vsctl --no-wait add-br ${OVS_BRIDGE}
-    sudo ovs-vsctl --no-wait br-set-external-id ${OVS_BRIDGE} bridge-id ${OVS_BRIDGE}
-
-    ctrls=
-    for ctrl in `echo ${BS_FL_CONTROLLERS_PORT} | tr ',' ' '`; do
-        ctrl=${ctrl%:*}
-        ctrls="${ctrls} tcp:${ctrl}:${BS_FL_OF_PORT}"
-    done
-    echo "Adding Network conttrollers: " ${ctrls}
-    sudo ovs-vsctl --no-wait set-controller ${OVS_BRIDGE} ${ctrls}
-}
-
-function install_bigswitch_floodlight {
-    :
-}
-
-function start_bigswitch_floodlight {
-    :
-}
-
-function stop_bigswitch_floodlight {
-    :
-}
-
-function check_bigswitch_floodlight {
-    :
-}
-
-# Restore xtrace
-$_XTRACE_NEUTRON_BIGSWITCH
diff --git a/lib/neutron_thirdparty/vmware_nsx b/lib/neutron_thirdparty/vmware_nsx
deleted file mode 100644
index e182fca..0000000
--- a/lib/neutron_thirdparty/vmware_nsx
+++ /dev/null
@@ -1,4 +0,0 @@
-#!/bin/bash
-
-# REVISIT(roeyc): this file left empty so that 'enable_service vmware_nsx'
-# continues to work.
diff --git a/lib/nova b/lib/nova
index 8823e1d..1369c40 100644
--- a/lib/nova
+++ b/lib/nova
@@ -59,11 +59,6 @@
 
 NOVA_API_PASTE_INI=${NOVA_API_PASTE_INI:-$NOVA_CONF_DIR/api-paste.ini}
 
-# NOVA_V2_LEGACY defines whether we force the Nova v2.0 enpoint onto
-# the Nova v2.0 legacy code base. Remove this option once the Nova
-# v2.0 legacy codebase is removed.
-NOVA_V2_LEGACY=$(trueorfalse False NOVA_V2_LEGACY)
-
 if is_suse; then
     NOVA_WSGI_DIR=${NOVA_WSGI_DIR:-/srv/www/htdocs/nova}
 else
@@ -133,7 +128,7 @@
 # --------------------------
 
 NETWORK_MANAGER=${NETWORK_MANAGER:-${NET_MAN:-FlatDHCPManager}}
-PUBLIC_INTERFACE=${PUBLIC_INTERFACE:-$PUBLIC_INTERFACE_DEFAULT}
+
 VLAN_INTERFACE=${VLAN_INTERFACE:-$GUEST_INTERFACE_DEFAULT}
 FLAT_NETWORK_BRIDGE=${FLAT_NETWORK_BRIDGE:-$FLAT_NETWORK_BRIDGE_DEFAULT}
 
@@ -311,13 +306,6 @@
     if [[ "$ENABLED_SERVICES" =~ "n-api" ]]; then
         # Get the sample configuration file in place
         cp $NOVA_DIR/etc/nova/api-paste.ini $NOVA_CONF_DIR
-
-        # For setting up an environment where v2.0 is running on the
-        # v2.0 legacy code base.
-        if [[ "$NOVA_V2_LEGACY" == "True" ]]; then
-            sed -i s@"^/v2: openstack_compute_api_v21_legacy_v2_compatible$"@"/v2: openstack_compute_api_legacy_v2"@ \
-                "$NOVA_API_PASTE_INI"
-        fi
     fi
 
     if is_service_enabled n-cpu; then
@@ -439,7 +427,7 @@
         if is_service_enabled swift; then
             # Nova needs ResellerAdmin role to download images when accessing
             # swift through the s3 api.
-            get_or_add_user_project_role ResellerAdmin nova $SERVICE_PROJECT_NAME
+            get_or_add_user_project_role ResellerAdmin nova $SERVICE_PROJECT_NAME $SERVICE_DOMAIN_NAME $SERVICE_DOMAIN_NAME
         fi
     fi
 
@@ -466,7 +454,7 @@
     if [ "$NOVA_ALLOW_MOVE_TO_SAME_HOST" == "True" ]; then
         iniset $NOVA_CONF DEFAULT allow_resize_to_same_host "True"
     fi
-    iniset $NOVA_CONF DEFAULT api_paste_config "$NOVA_API_PASTE_INI"
+    iniset $NOVA_CONF wsgi api_paste_config "$NOVA_API_PASTE_INI"
     iniset $NOVA_CONF DEFAULT rootwrap_config "$NOVA_CONF_DIR/rootwrap.conf"
     iniset $NOVA_CONF DEFAULT scheduler_driver "$SCHEDULER"
     iniset $NOVA_CONF DEFAULT scheduler_default_filters "$FILTERS"
@@ -493,8 +481,6 @@
         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
@@ -601,11 +587,6 @@
 
     iniset $NOVA_CONF cinder os_region_name "$REGION_NAME"
 
-    if [[ "$NOVA_BACKEND" == "LVM" ]]; then
-        iniset $NOVA_CONF libvirt images_type "lvm"
-        iniset $NOVA_CONF libvirt images_volume_group $DEFAULT_VOLUME_GROUP_NAME
-    fi
-
     if is_ssl_enabled_service glance || is_service_enabled tls-proxy; then
         iniset $NOVA_CONF DEFAULT glance_protocol https
     fi
@@ -648,7 +629,7 @@
     if is_service_enabled n-cell; then
         cp $NOVA_CONF $NOVA_CELLS_CONF
         iniset $NOVA_CELLS_CONF database connection `database_connection_url $NOVA_CELLS_DB`
-        iniset $NOVA_CELLS_CONF oslo_messaging_rabbit rabbit_virtual_host child_cell
+        iniset_rpc_backend nova $NOVA_CELLS_CONF DEFAULT child_cell
         iniset $NOVA_CELLS_CONF DEFAULT dhcpbridge_flagfile $NOVA_CELLS_CONF
         iniset $NOVA_CELLS_CONF cells enable True
         iniset $NOVA_CELLS_CONF cells cell_type compute
@@ -678,8 +659,9 @@
 }
 
 function create_nova_conf_nova_network {
+    local public_interface=${PUBLIC_INTERFACE:-$PUBLIC_INTERFACE_DEFAULT}
     iniset $NOVA_CONF DEFAULT network_manager "nova.network.manager.$NETWORK_MANAGER"
-    iniset $NOVA_CONF DEFAULT public_interface "$PUBLIC_INTERFACE"
+    iniset $NOVA_CONF DEFAULT public_interface "$public_interface"
     iniset $NOVA_CONF DEFAULT vlan_interface "$VLAN_INTERFACE"
     iniset $NOVA_CONF DEFAULT flat_network_bridge "$FLAT_NETWORK_BRIDGE"
     if [ -n "$FLAT_INTERFACE" ]; then
@@ -702,18 +684,18 @@
         recreate_database nova
 
         # Migrate nova database
-        $NOVA_BIN_DIR/nova-manage db sync
+        $NOVA_BIN_DIR/nova-manage --config-file $NOVA_CONF db sync
 
         if is_service_enabled n-cell; then
             recreate_database $NOVA_CELLS_DB
         fi
 
         recreate_database $NOVA_API_DB
-        $NOVA_BIN_DIR/nova-manage api_db sync
+        $NOVA_BIN_DIR/nova-manage --config-file $NOVA_CONF api_db sync
 
         # Run online migrations on the new databases
         # Needed for flavor conversion
-        $NOVA_BIN_DIR/nova-manage db online_data_migrations
+        $NOVA_BIN_DIR/nova-manage --config-file $NOVA_CONF db online_data_migrations
     fi
 
     create_nova_cache_dir
@@ -935,21 +917,21 @@
 # create_instance_types(): Create default flavors
 function create_flavors {
     if is_service_enabled n-api; then
-        if ! openstack flavor list | grep -q ds512M; then
+        if ! openstack --os-region-name="$REGION_NAME" flavor list | grep -q ds512M; then
             # Note that danms hates these flavors and apologizes for sdague
-            openstack flavor create --id c1 --ram 256 --disk 0 --vcpus 1 cirros256
-            openstack flavor create --id d1 --ram 512 --disk 5 --vcpus 1 ds512M
-            openstack flavor create --id d2 --ram 1024 --disk 10 --vcpus 1 ds1G
-            openstack flavor create --id d3 --ram 2048 --disk 10 --vcpus 2 ds2G
-            openstack flavor create --id d4 --ram 4096 --disk 20 --vcpus 4 ds4G
+            openstack --os-region-name="$REGION_NAME" flavor create --id c1 --ram 256 --disk 0 --vcpus 1 cirros256
+            openstack --os-region-name="$REGION_NAME" flavor create --id d1 --ram 512 --disk 5 --vcpus 1 ds512M
+            openstack --os-region-name="$REGION_NAME" flavor create --id d2 --ram 1024 --disk 10 --vcpus 1 ds1G
+            openstack --os-region-name="$REGION_NAME" flavor create --id d3 --ram 2048 --disk 10 --vcpus 2 ds2G
+            openstack --os-region-name="$REGION_NAME" flavor create --id d4 --ram 4096 --disk 20 --vcpus 4 ds4G
         fi
 
-        if ! openstack flavor list | grep -q m1.tiny; then
-            openstack flavor create --id 1 --ram 512 --disk 1 --vcpus 1 m1.tiny
-            openstack flavor create --id 2 --ram 2048 --disk 20 --vcpus 1 m1.small
-            openstack flavor create --id 3 --ram 4096 --disk 40 --vcpus 2 m1.medium
-            openstack flavor create --id 4 --ram 8192 --disk 80 --vcpus 4 m1.large
-            openstack flavor create --id 5 --ram 16384 --disk 160 --vcpus 8 m1.xlarge
+        if ! openstack --os-region-name="$REGION_NAME" flavor list | grep -q m1.tiny; then
+            openstack --os-region-name="$REGION_NAME" flavor create --id 1 --ram 512 --disk 1 --vcpus 1 m1.tiny
+            openstack --os-region-name="$REGION_NAME" flavor create --id 2 --ram 2048 --disk 20 --vcpus 1 m1.small
+            openstack --os-region-name="$REGION_NAME" flavor create --id 3 --ram 4096 --disk 40 --vcpus 2 m1.medium
+            openstack --os-region-name="$REGION_NAME" flavor create --id 4 --ram 8192 --disk 80 --vcpus 4 m1.large
+            openstack --os-region-name="$REGION_NAME" flavor create --id 5 --ram 16384 --disk 160 --vcpus 8 m1.xlarge
         fi
     fi
 }
diff --git a/lib/nova_plugins/functions-libvirt b/lib/nova_plugins/functions-libvirt
index dbb4d4f..4e5a748 100644
--- a/lib/nova_plugins/functions-libvirt
+++ b/lib/nova_plugins/functions-libvirt
@@ -108,9 +108,9 @@
             # source file paths, not relative paths. This screws with the matching
             # of '1:libvirt' making everything turn on. So use libvirt.c for now.
             # This will have to be re-visited when Ubuntu ships libvirt >= 1.2.3
-            local log_filters="1:libvirt.c 1:qemu 1:conf 1:security 3:object 3:event 3:json 3:file 1:util 1:qemu_monitor"
+            local log_filters="1:libvirt.c 1:qemu 1:conf 1:security 3:object 3:event 3:json 3:file 1:util 1:cpu"
         else
-            local log_filters="1:libvirt 1:qemu 1:conf 1:security 3:object 3:event 3:json 3:file 1:util 1:qemu_monitor"
+            local log_filters="1:libvirt 1:qemu 1:conf 1:security 3:object 3:event 3:json 3:file 1:util 1:cpu"
         fi
         local log_outputs="1:file:/var/log/libvirt/libvirtd.log"
         if ! sudo grep -q "^log_filters=\"$log_filters\"" /etc/libvirt/libvirtd.conf; then
@@ -121,18 +121,9 @@
         fi
     fi
 
-    # Update the libvirt cpu map with a gate64 cpu model. This enables nova
-    # live migration for 64bit guest OSes on heterogenous cloud "hardware".
-    if [[ -f /usr/share/libvirt/cpu_map.xml ]] ; then
-        sudo $TOP_DIR/tools/cpu_map_update.py /usr/share/libvirt/cpu_map.xml
-    fi
-
-    # libvirt detects various settings on startup, as we potentially changed
-    # the system configuration (modules, filesystems), we need to restart
-    # libvirt to detect those changes. Use a stop start as otherwise the new
-    # cpu_map is not loaded properly on some systems (Ubuntu).
-    stop_service $LIBVIRT_DAEMON
-    start_service $LIBVIRT_DAEMON
+    # Service needs to be started on redhat/fedora -- do a restart for
+    # sanity after fiddling the config.
+    restart_service $LIBVIRT_DAEMON
 }
 
 
diff --git a/lib/nova_plugins/hypervisor-ironic b/lib/nova_plugins/hypervisor-ironic
index 43e7797..c40427c 100644
--- a/lib/nova_plugins/hypervisor-ironic
+++ b/lib/nova_plugins/hypervisor-ironic
@@ -39,7 +39,7 @@
     configure_libvirt
     LIBVIRT_FIREWALL_DRIVER=${LIBVIRT_FIREWALL_DRIVER:-"nova.virt.firewall.NoopFirewallDriver"}
 
-    iniset $NOVA_CONF DEFAULT compute_driver nova.virt.ironic.IronicDriver
+    iniset $NOVA_CONF DEFAULT compute_driver ironic.IronicDriver
     iniset $NOVA_CONF DEFAULT firewall_driver $LIBVIRT_FIREWALL_DRIVER
     iniset $NOVA_CONF DEFAULT scheduler_host_manager ironic_host_manager
     iniset $NOVA_CONF DEFAULT ram_allocation_ratio 1.0
diff --git a/lib/nova_plugins/hypervisor-libvirt b/lib/nova_plugins/hypervisor-libvirt
index 1b4f7ae..20dde8e 100644
--- a/lib/nova_plugins/hypervisor-libvirt
+++ b/lib/nova_plugins/hypervisor-libvirt
@@ -55,11 +55,16 @@
     if is_arch "aarch64"; then
         # arm64 architecture currently does not support graphical consoles.
         iniset $NOVA_CONF vnc enabled "false"
+        iniset $NOVA_CONF libvirt cpu_mode "host-passthrough"
     fi
 
-    # File injection is being disabled by default in the near future -
-    # disable it here for now to avoid surprises later.
-    iniset $NOVA_CONF libvirt inject_partition '-2'
+    if isset ENABLE_FILE_INJECTION; then
+        if [ "$ENABLE_FILE_INJECTION" == "True" ]; then
+            # -1 means use libguestfs to inspect the guest OS image for the
+            # root partition to use for file injection.
+            iniset $NOVA_CONF libvirt inject_partition '-1'
+        fi
+    fi
 
     if [[ "$LIBVIRT_TYPE" = "parallels" ]]; then
         iniset $NOVA_CONF libvirt connection_uri "parallels+unix:///system"
@@ -68,6 +73,12 @@
         iniset $NOVA_CONF vnc vncserver_proxyclient_address  $HOST_IP
         iniset $NOVA_CONF vnc vncserver_listen $HOST_IP
         iniset $NOVA_CONF vnc keymap
+    elif [[ "$NOVA_BACKEND" == "LVM" ]]; then
+        iniset $NOVA_CONF libvirt images_type "lvm"
+        iniset $NOVA_CONF libvirt images_volume_group $DEFAULT_VOLUME_GROUP_NAME
+        if isset LVM_VOLUME_CLEAR; then
+            iniset $NOVA_CONF libvirt volume_clear "$LVM_VOLUME_CLEAR"
+        fi
     fi
 }
 
diff --git a/lib/nova_plugins/hypervisor-xenserver b/lib/nova_plugins/hypervisor-xenserver
index 3eb9149..e75226a 100644
--- a/lib/nova_plugins/hypervisor-xenserver
+++ b/lib/nova_plugins/hypervisor-xenserver
@@ -24,12 +24,11 @@
 # Defaults
 # --------
 
-PUBLIC_INTERFACE_DEFAULT=eth2
-GUEST_INTERFACE_DEFAULT=eth1
 # Allow ``build_domU.sh`` to specify the flat network bridge via kernel args
 FLAT_NETWORK_BRIDGE_DEFAULT=$(sed -e 's/.* flat_network_bridge=\([[:alnum:]]*\).*$/\1/g' /proc/cmdline)
 if is_service_enabled neutron; then
-    XEN_INTEGRATION_BRIDGE=$(sed -e 's/.* xen_integration_bridge=\([[:alnum:]]*\).*$/\1/g' /proc/cmdline)
+    XEN_INTEGRATION_BRIDGE_DEFAULT=$(sed -e 's/.* xen_integration_bridge=\([[:alnum:]]*\).*$/\1/g' /proc/cmdline)
+    XEN_INTEGRATION_BRIDGE=${XEN_INTEGRATION_BRIDGE:-$XEN_INTEGRATION_BRIDGE_DEFAULT}
 fi
 
 VNCSERVER_PROXYCLIENT_ADDRESS=${VNCSERVER_PROXYCLIENT_ADDRESS=169.254.0.1}
diff --git a/lib/os_brick b/lib/os_brick
new file mode 100644
index 0000000..d1cca4a
--- /dev/null
+++ b/lib/os_brick
@@ -0,0 +1,32 @@
+#!/bin/bash
+#
+# lib/os_brick
+# Install **os-brick** python module from source
+
+# Dependencies:
+#
+# - functions
+# - DEST, DATA_DIR must be defined
+
+# stack.sh
+# ---------
+# - install_os_brick
+
+# Save trace setting
+_XTRACE_OS_BRICK=$(set +o | grep xtrace)
+set +o xtrace
+
+
+GITDIR["os-brick"]=$DEST/os-brick
+
+# Install os_brick from git only if requested, otherwise it will be pulled from
+# pip repositories by requirements of projects that need it.
+function install_os_brick {
+    if use_library_from_git "os-brick"; then
+        git_clone_by_name "os-brick"
+        setup_dev_lib "os-brick"
+    fi
+}
+
+# Restore xtrace
+$_XTRACE_OS_BRICK
\ No newline at end of file
diff --git a/lib/rpc_backend b/lib/rpc_backend
index 05e303e..0ee46dc 100644
--- a/lib/rpc_backend
+++ b/lib/rpc_backend
@@ -104,8 +104,9 @@
 
 # builds transport url string
 function get_transport_url {
+    local virtual_host=$1
     if is_service_enabled rabbit || { [ -n "$RABBIT_HOST" ] && [ -n "$RABBIT_PASSWORD" ]; }; then
-        echo "rabbit://$RABBIT_USERID:$RABBIT_PASSWORD@$RABBIT_HOST:5672/"
+        echo "rabbit://$RABBIT_USERID:$RABBIT_PASSWORD@$RABBIT_HOST:5672/$virtual_host"
     fi
 }
 
@@ -114,11 +115,9 @@
     local package=$1
     local file=$2
     local section=${3:-DEFAULT}
+    local virtual_host=$4
     if is_service_enabled rabbit || { [ -n "$RABBIT_HOST" ] && [ -n "$RABBIT_PASSWORD" ]; }; then
-        iniset $file $section rpc_backend "rabbit"
-        iniset $file oslo_messaging_rabbit rabbit_hosts $RABBIT_HOST
-        iniset $file oslo_messaging_rabbit rabbit_password $RABBIT_PASSWORD
-        iniset $file oslo_messaging_rabbit rabbit_userid $RABBIT_USERID
+        iniset $file $section transport_url $(get_transport_url "$virtual_host")
         if [ -n "$RABBIT_HEARTBEAT_TIMEOUT_THRESHOLD" ]; then
             iniset $file oslo_messaging_rabbit heartbeat_timeout_threshold $RABBIT_HEARTBEAT_TIMEOUT_THRESHOLD
         fi
diff --git a/lib/swift b/lib/swift
index b2fe755..0c74411 100644
--- a/lib/swift
+++ b/lib/swift
@@ -149,6 +149,11 @@
 # Toggle for deploying Swift under HTTPD + mod_wsgi
 SWIFT_USE_MOD_WSGI=${SWIFT_USE_MOD_WSGI:-False}
 
+# A space-separated list of storage node IPs that
+# should be used to create the Swift rings
+SWIFT_STORAGE_IPS=${SWIFT_STORAGE_IPS:-}
+
+
 # Functions
 # ---------
 
@@ -423,6 +428,7 @@
     sed -i "/^pipeline/ { s/proxy-server/${SWIFT_EXTRAS_MIDDLEWARE_LAST} proxy-server/ ; }" ${SWIFT_CONFIG_PROXY_SERVER}
 
     iniset ${SWIFT_CONFIG_PROXY_SERVER} app:proxy-server account_autocreate true
+    iniset ${SWIFT_CONFIG_PROXY_SERVER} app:proxy-server allow_account_management true
 
     # Configure Crossdomain
     iniset ${SWIFT_CONFIG_PROXY_SERVER} filter:crossdomain use "egg:swift#crossdomain"
@@ -452,9 +458,7 @@
         cat <<EOF >>${SWIFT_CONFIG_PROXY_SERVER}
 [filter:s3token]
 paste.filter_factory = keystonemiddleware.s3_token:filter_factory
-auth_port = ${KEYSTONE_AUTH_PORT}
-auth_host = ${KEYSTONE_AUTH_HOST}
-auth_protocol = ${KEYSTONE_AUTH_PROTOCOL}
+auth_uri = ${KEYSTONE_AUTH_URI}
 cafile = ${SSL_BUNDLE_FILE}
 admin_user = swift
 admin_tenant_name = ${SERVICE_PROJECT_NAME}
@@ -495,21 +499,21 @@
         iniset ${swift_node_config} DEFAULT bind_ip ${SWIFT_SERVICE_LISTEN_ADDRESS}
     done
 
-    # Set new accounts in tempauth to match keystone tenant/user (to make testing easier)
-    iniset ${SWIFT_CONFIG_PROXY_SERVER} filter:tempauth user_swifttenanttest1_swiftusertest1 "testing .admin"
-    iniset ${SWIFT_CONFIG_PROXY_SERVER} filter:tempauth user_swifttenanttest2_swiftusertest2 "testing2 .admin"
-    iniset ${SWIFT_CONFIG_PROXY_SERVER} filter:tempauth user_swifttenanttest1_swiftusertest3 "testing3 .admin"
+    # Set new accounts in tempauth to match keystone project/user (to make testing easier)
+    iniset ${SWIFT_CONFIG_PROXY_SERVER} filter:tempauth user_swiftprojecttest1_swiftusertest1 "testing .admin"
+    iniset ${SWIFT_CONFIG_PROXY_SERVER} filter:tempauth user_swiftprojecttest2_swiftusertest2 "testing2 .admin"
+    iniset ${SWIFT_CONFIG_PROXY_SERVER} filter:tempauth user_swiftprojecttest1_swiftusertest3 "testing3 .admin"
 
     testfile=${SWIFT_CONF_DIR}/test.conf
     cp ${SWIFT_DIR}/test/sample.conf ${testfile}
 
     # Set accounts for functional tests
-    iniset ${testfile} func_test account swifttenanttest1
+    iniset ${testfile} func_test account swiftprojecttest1
     iniset ${testfile} func_test username swiftusertest1
     iniset ${testfile} func_test username3 swiftusertest3
-    iniset ${testfile} func_test account2 swifttenanttest2
+    iniset ${testfile} func_test account2 swiftprojecttest2
     iniset ${testfile} func_test username2 swiftusertest2
-    iniset ${testfile} func_test account4 swifttenanttest4
+    iniset ${testfile} func_test account4 swiftprojecttest4
     iniset ${testfile} func_test username4 swiftusertest4
     iniset ${testfile} func_test password4 testing4
     iniset ${testfile} func_test domain4 swift_test
@@ -603,13 +607,13 @@
 # since we want to make it compatible with tempauth which use
 # underscores for separators.
 
-# Tenant             User               Roles          Domain
-# ------------------------------------------------------------------
-# service            swift              service        default
-# swifttenanttest1   swiftusertest1     admin          default
-# swifttenanttest1   swiftusertest3     anotherrole    default
-# swifttenanttest2   swiftusertest2     admin          default
-# swifttenanttest4   swiftusertest4     admin          swift_test
+# Project             User               Roles          Domain
+# -------------------------------------------------------------------
+# service             swift              service        default
+# swiftprojecttest1   swiftusertest1     admin          default
+# swiftprojecttest1   swiftusertest3     anotherrole    default
+# swiftprojecttest2   swiftusertest2     admin          default
+# swiftprojecttest4   swiftusertest4     admin          swift_test
 
 function create_swift_accounts {
     # Defines specific passwords used by ``tools/create_userrc.sh``
@@ -635,43 +639,43 @@
         "$SWIFT_SERVICE_PROTOCOL://$SERVICE_HOST:$SWIFT_DEFAULT_BIND_PORT" \
         "$SWIFT_SERVICE_PROTOCOL://$SERVICE_HOST:$SWIFT_DEFAULT_BIND_PORT/v1/AUTH_\$(project_id)s"
 
-    local swift_tenant_test1
-    swift_tenant_test1=$(get_or_create_project swifttenanttest1 default)
-    die_if_not_set $LINENO swift_tenant_test1 "Failure creating swift_tenant_test1"
+    local swift_project_test1
+    swift_project_test1=$(get_or_create_project swiftprojecttest1 default)
+    die_if_not_set $LINENO swift_project_test1 "Failure creating swift_project_test1"
     SWIFT_USER_TEST1=$(get_or_create_user swiftusertest1 $swiftusertest1_password \
                         "default" "test@example.com")
     die_if_not_set $LINENO SWIFT_USER_TEST1 "Failure creating SWIFT_USER_TEST1"
-    get_or_add_user_project_role admin $SWIFT_USER_TEST1 $swift_tenant_test1
+    get_or_add_user_project_role admin $SWIFT_USER_TEST1 $swift_project_test1
 
     local swift_user_test3
     swift_user_test3=$(get_or_create_user swiftusertest3 $swiftusertest3_password \
                                 "default" "test3@example.com")
     die_if_not_set $LINENO swift_user_test3 "Failure creating swift_user_test3"
-    get_or_add_user_project_role $another_role $swift_user_test3 $swift_tenant_test1
+    get_or_add_user_project_role $another_role $swift_user_test3 $swift_project_test1
 
-    local swift_tenant_test2
-    swift_tenant_test2=$(get_or_create_project swifttenanttest2 default)
-    die_if_not_set $LINENO swift_tenant_test2 "Failure creating swift_tenant_test2"
+    local swift_project_test2
+    swift_project_test2=$(get_or_create_project swiftprojecttest2 default)
+    die_if_not_set $LINENO swift_project_test2 "Failure creating swift_project_test2"
 
     local swift_user_test2
     swift_user_test2=$(get_or_create_user swiftusertest2 $swiftusertest2_password \
                                 "default" "test2@example.com")
     die_if_not_set $LINENO swift_user_test2 "Failure creating swift_user_test2"
-    get_or_add_user_project_role admin $swift_user_test2 $swift_tenant_test2
+    get_or_add_user_project_role admin $swift_user_test2 $swift_project_test2
 
     local swift_domain
     swift_domain=$(get_or_create_domain swift_test 'Used for swift functional testing')
     die_if_not_set $LINENO swift_domain "Failure creating swift_test domain"
 
-    local swift_tenant_test4
-    swift_tenant_test4=$(get_or_create_project swifttenanttest4 $swift_domain)
-    die_if_not_set $LINENO swift_tenant_test4 "Failure creating swift_tenant_test4"
+    local swift_project_test4
+    swift_project_test4=$(get_or_create_project swiftprojecttest4 $swift_domain)
+    die_if_not_set $LINENO swift_project_test4 "Failure creating swift_project_test4"
 
     local swift_user_test4
     swift_user_test4=$(get_or_create_user swiftusertest4 $swiftusertest4_password \
                                 $swift_domain "test4@example.com")
     die_if_not_set $LINENO swift_user_test4 "Failure creating swift_user_test4"
-    get_or_add_user_project_role admin $swift_user_test4 $swift_tenant_test4
+    get_or_add_user_project_role admin $swift_user_test4 $swift_project_test4
 }
 
 # init_swift() - Initialize rings
@@ -693,14 +697,35 @@
         swift-ring-builder container.builder create ${SWIFT_PARTITION_POWER_SIZE} ${SWIFT_REPLICAS} 1
         swift-ring-builder account.builder create ${SWIFT_PARTITION_POWER_SIZE} ${SWIFT_REPLICAS} 1
 
-        for node_number in ${SWIFT_REPLICAS_SEQ}; do
-            swift-ring-builder object.builder add z${node_number}-${SWIFT_SERVICE_LOCAL_HOST}:$(( OBJECT_PORT_BASE + 10 * (node_number - 1) ))/sdb1 1
-            swift-ring-builder container.builder add z${node_number}-${SWIFT_SERVICE_LOCAL_HOST}:$(( CONTAINER_PORT_BASE + 10 * (node_number - 1) ))/sdb1 1
-            swift-ring-builder account.builder add z${node_number}-${SWIFT_SERVICE_LOCAL_HOST}:$(( ACCOUNT_PORT_BASE + 10 * (node_number - 1) ))/sdb1 1
-        done
-        swift-ring-builder object.builder rebalance
-        swift-ring-builder container.builder rebalance
-        swift-ring-builder account.builder rebalance
+        # The ring will be created on each node, and because the order of
+        # nodes is identical we can use a seed for rebalancing, making it
+        # possible to get a ring on each node that uses the same partition
+        # assignment.
+        if [[ -n $SWIFT_STORAGE_IPS ]]; then
+            local node_number
+            node_number=1
+
+            for node in ${SWIFT_STORAGE_IPS}; do
+                swift-ring-builder object.builder add z${node_number}-${node}:${OBJECT_PORT_BASE}/sdb1 1
+                swift-ring-builder container.builder add z${node_number}-${node}:${CONTAINER_PORT_BASE}/sdb1 1
+                swift-ring-builder account.builder add z${node_number}-${node}:${ACCOUNT_PORT_BASE}/sdb1 1
+                let "node_number=node_number+1"
+            done
+
+        else
+
+            for node_number in ${SWIFT_REPLICAS_SEQ}; do
+                swift-ring-builder object.builder add z${node_number}-${SWIFT_SERVICE_LOCAL_HOST}:$(( OBJECT_PORT_BASE + 10 * (node_number - 1) ))/sdb1 1
+                swift-ring-builder container.builder add z${node_number}-${SWIFT_SERVICE_LOCAL_HOST}:$(( CONTAINER_PORT_BASE + 10 * (node_number - 1) ))/sdb1 1
+                swift-ring-builder account.builder add z${node_number}-${SWIFT_SERVICE_LOCAL_HOST}:$(( ACCOUNT_PORT_BASE + 10 * (node_number - 1) ))/sdb1 1
+            done
+        fi
+
+        # We use a seed for rebalancing. Doing this allows us to create
+        # identical rings on multiple nodes if SWIFT_STORAGE_IPS is the same
+        swift-ring-builder object.builder rebalance 42
+        swift-ring-builder container.builder rebalance 42
+        swift-ring-builder account.builder rebalance 42
     } && popd >/dev/null
 
     # Create cache dir
@@ -820,7 +845,9 @@
     # note we are using swift credentials!
     OS_USERNAME=swift \
     OS_PASSWORD=$SERVICE_PASSWORD \
+    OS_USER_DOMAIN_NAME=$SERVICE_DOMAIN_NAME \
     OS_PROJECT_NAME=$SERVICE_PROJECT_NAME \
+    OS_PROJECT_DOMAIN_NAME=$SERVICE_DOMAIN_NAME \
     openstack object store account \
         set --property "Temp-URL-Key=$SWIFT_TEMPURL_KEY"
 }
diff --git a/lib/tempest b/lib/tempest
index 621bd62..6bfa889 100644
--- a/lib/tempest
+++ b/lib/tempest
@@ -16,7 +16,6 @@
 #   - ``BASE_SQL_CONN`` ``lib/database`` declares
 #   - ``PUBLIC_NETWORK_NAME``
 #   - ``Q_ROUTER_NAME``
-#   - ``Q_L3_ENABLED``
 #   - ``VIRT_DRIVER``
 #   - ``LIBVIRT_TYPE``
 #   - ``KEYSTONE_SERVICE_PROTOCOL``, ``KEYSTONE_SERVICE_HOST`` from lib/keystone
@@ -45,8 +44,6 @@
 # --------
 
 # Set up default directories
-GITDIR["tempest-lib"]=$DEST/tempest-lib
-
 TEMPEST_DIR=$DEST/tempest
 TEMPEST_CONFIG_DIR=${TEMPEST_CONFIG_DIR:-$TEMPEST_DIR/etc}
 TEMPEST_CONFIG=$TEMPEST_CONFIG_DIR/tempest.conf
@@ -66,6 +63,10 @@
 # have tempest installed in DevStack by default.
 INSTALL_TEMPEST=${INSTALL_TEMPEST:-"True"}
 
+# This variable is passed directly to pip install inside the common tox venv
+# that is created
+TEMPEST_PLUGINS=${TEMPEST_PLUGINS:-0}
+
 # Cinder/Volume variables
 TEMPEST_VOLUME_DRIVER=${TEMPEST_VOLUME_DRIVER:-default}
 TEMPEST_DEFAULT_VOLUME_VENDOR="Open Source"
@@ -182,8 +183,6 @@
     local admin_username=${ADMIN_USERNAME:-admin}
     local admin_project_name=${ADMIN_TENANT_NAME:-admin}
     local admin_domain_name=${ADMIN_DOMAIN_NAME:-Default}
-    local tempest_username=${TEMPEST_USERNAME:-demo}
-    local tempest_project_name=${TEMPEST_TENANT_NAME:-demo}
     local alt_username=${ALT_USERNAME:-alt_demo}
     local alt_project_name=${ALT_TENANT_NAME:-alt_demo}
     local admin_project_id
@@ -239,7 +238,9 @@
 
     ssh_connect_method=${TEMPEST_SSH_CONNECT_METHOD:-$ssh_connect_method}
 
-    if [ "$Q_L3_ENABLED" = "True" ]; then
+    # the public network (for floating ip access) is only available
+    # if the extension is enabled.
+    if is_networking_extension_supported 'external-net'; then
         public_network_id=$(neutron net-list | grep $PUBLIC_NETWORK_NAME | \
             awk '{print $2}')
     fi
@@ -260,6 +261,8 @@
     # Identity
     iniset $TEMPEST_CONFIG identity uri "$KEYSTONE_SERVICE_PROTOCOL://$KEYSTONE_SERVICE_HOST:5000/v2.0/"
     iniset $TEMPEST_CONFIG identity uri_v3 "$KEYSTONE_SERVICE_URI_V3"
+    # Use domain scoped tokens for admin v3 tests, v3 dynamic credentials of v3 account generation
+    iniset $TEMPEST_CONFIG identity admin_domain_scope True
     if [[ "$TEMPEST_HAS_ADMIN" == "True" ]]; then
         iniset $TEMPEST_CONFIG auth admin_username $admin_username
         iniset $TEMPEST_CONFIG auth admin_password "$password"
@@ -280,6 +283,10 @@
         iniset $TEMPEST_CONFIG identity ca_certificates_file $SSL_BUNDLE_FILE
     fi
 
+    # Identity Features
+    # TODO(rodrigods): Remove the reseller flag when Kilo and Liberty are end of life.
+    iniset $TEMPEST_CONFIG identity-feature-enabled reseller True
+
     # Image
     # We want to be able to override this variable in the gate to avoid
     # doing an external HTTP fetch for this test.
@@ -288,10 +295,14 @@
     fi
     if [ "$VIRT_DRIVER" = "xenserver" ]; then
         iniset $TEMPEST_CONFIG image disk_formats "ami,ari,aki,vhd,raw,iso"
+        iniset $TEMPEST_CONFIG scenario img_disk_format vhd
     fi
 
     # Image Features
     iniset $TEMPEST_CONFIG image-feature-enabled deactivate_image True
+    if [ "$GLANCE_V1_ENABLED" != "True" ]; then
+        iniset $TEMPEST_CONFIG image-feature-enabled api_v1 False
+    fi
 
     # Compute
     iniset $TEMPEST_CONFIG compute ssh_user ${DEFAULT_INSTANCE_USER:-cirros} # DEPRECATED
@@ -331,29 +342,22 @@
         tempest_compute_max_microversion=None
     fi
     if [ "$tempest_compute_min_microversion" == "None" ]; then
-        inicomment $TEMPEST_CONFIG compute-feature-enabled min_microversion
+        inicomment $TEMPEST_CONFIG compute min_microversion
     else
-        iniset $TEMPEST_CONFIG compute-feature-enabled min_microversion $tempest_compute_min_microversion
+        iniset $TEMPEST_CONFIG compute min_microversion $tempest_compute_min_microversion
     fi
     if [ "$tempest_compute_max_microversion" == "None" ]; then
-        inicomment $TEMPEST_CONFIG compute-feature-enabled max_microversion
+        inicomment $TEMPEST_CONFIG compute max_microversion
     else
-        iniset $TEMPEST_CONFIG compute-feature-enabled max_microversion $tempest_compute_max_microversion
+        iniset $TEMPEST_CONFIG compute max_microversion $tempest_compute_max_microversion
     fi
 
+    iniset $TEMPEST_CONFIG compute-feature-enabled personality ${ENABLE_FILE_INJECTION:-False}
     iniset $TEMPEST_CONFIG compute-feature-enabled resize True
     iniset $TEMPEST_CONFIG compute-feature-enabled live_migration ${LIVE_MIGRATION_AVAILABLE:-False}
     iniset $TEMPEST_CONFIG compute-feature-enabled change_password False
     iniset $TEMPEST_CONFIG compute-feature-enabled block_migration_for_live_migration ${USE_BLOCK_MIGRATION_FOR_LIVE_MIGRATION:-False}
-    # TODO(mriedem): Remove the preserve_ports flag when Juno is end of life.
-    iniset $TEMPEST_CONFIG compute-feature-enabled preserve_ports True
-    # TODO(gilliard): Remove the live_migrate_paused_instances flag when Juno is end of life.
-    iniset $TEMPEST_CONFIG compute-feature-enabled live_migrate_paused_instances True
     iniset $TEMPEST_CONFIG compute-feature-enabled attach_encrypted_volume ${ATTACH_ENCRYPTED_VOLUME_AVAILABLE:-True}
-    # TODO(mriedem): Remove this when kilo-eol happens since the
-    # neutron.allow_duplicate_networks option was removed from nova in Liberty
-    # and is now the default behavior.
-    iniset $TEMPEST_CONFIG compute-feature-enabled allow_duplicate_networks ${NOVA_ALLOW_DUPLICATE_NETWORKS:-True}
     if is_service_enabled n-cell; then
         # Cells doesn't support shelving/unshelving
         iniset $TEMPEST_CONFIG compute-feature-enabled shelve False
@@ -374,7 +378,7 @@
 
     # Network
     iniset $TEMPEST_CONFIG network api_version 2.0
-    iniset $TEMPEST_CONFIG network tenant_networks_reachable false
+    iniset $TEMPEST_CONFIG network project_networks_reachable false
     iniset $TEMPEST_CONFIG network public_network_id "$public_network_id"
     iniset $TEMPEST_CONFIG network public_router_id "$public_router_id"
     iniset $TEMPEST_CONFIG network default_network "$FIXED_RANGE"
@@ -383,6 +387,11 @@
 
     # Orchestration Tests
     if is_service_enabled heat; then
+        # Though this is not needed by heat, some tempest tests explicitly
+        # try to set this role. Removing them from the tempest tests breaks
+        # some non-devstack CIs.
+        get_or_create_role "heat_stack_owner"
+
         if [[ ! -z "$HEAT_CFN_IMAGE_URL" ]]; then
             iniset $TEMPEST_CONFIG orchestration image_ref $(basename "${HEAT_CFN_IMAGE_URL%.*}")
         fi
@@ -396,7 +405,7 @@
             iniset $TEMPEST_CONFIG orchestration instance_type "m1.heat"
         fi
         iniset $TEMPEST_CONFIG orchestration build_timeout 900
-        iniset $TEMPEST_CONFIG orchestration stack_owner_role "_member_"
+        iniset $TEMPEST_CONFIG orchestration stack_owner_role "heat_stack_owner"
     fi
 
     # Scenario
@@ -407,9 +416,6 @@
     iniset $TEMPEST_CONFIG scenario aki_img_file "cirros-${CIRROS_VERSION}-${CIRROS_ARCH}-vmlinuz"
     iniset $TEMPEST_CONFIG scenario img_file "cirros-${CIRROS_VERSION}-${CIRROS_ARCH}-disk.img"
 
-    # Large Ops Number
-    iniset $TEMPEST_CONFIG scenario large_ops_number ${TEMPEST_LARGE_OPS_NUMBER:-0}
-
     # Telemetry
     iniset $TEMPEST_CONFIG telemetry-feature-enabled events "True"
 
@@ -421,10 +427,25 @@
     iniset $TEMPEST_CONFIG validation network_for_ssh $PRIVATE_NETWORK_NAME
 
     # Volume
-    # TODO(obutenko): Remove the incremental_backup_force flag when Kilo and Juno is end of life.
-    iniset $TEMPEST_CONFIG volume-feature-enabled incremental_backup_force True
+    # TODO(obutenko): Remove snapshot_backup when liberty-eol happens.
+    iniset $TEMPEST_CONFIG volume-feature-enabled snapshot_backup True
     # TODO(ynesenenko): Remove the volume_services flag when Liberty and Kilo will correct work with host info.
     iniset $TEMPEST_CONFIG volume-feature-enabled volume_services True
+    # TODO(ameade): Remove the api_v3 flag when Mitaka and Liberty are end of life.
+    iniset $TEMPEST_CONFIG volume-feature-enabled api_v3 True
+    local tempest_volume_min_microversion=${TEMPEST_VOLUME_MIN_MICROVERSION:-None}
+    local tempest_volume_max_microversion=${TEMPEST_VOLUME_MAX_MICROVERSION:-"latest"}
+    if [ "$tempest_volume_min_microversion" == "None" ]; then
+        inicomment $TEMPEST_CONFIG volume min_microversion
+    else
+        iniset $TEMPEST_CONFIG volume min_microversion $tempest_volume_min_microversion
+    fi
+
+    if [ "$tempest_volume_max_microversion" == "None" ]; then
+        inicomment $TEMPEST_CONFIG volume max_microversion
+    else
+        iniset $TEMPEST_CONFIG volume max_microversion $tempest_volume_max_microversion
+    fi
 
     if ! is_service_enabled c-bak; then
         iniset $TEMPEST_CONFIG volume-feature-enabled backup False
@@ -515,17 +536,17 @@
     tmp_cfg_file=$(mktemp)
     cd $TEMPEST_DIR
     if [[ "$OFFLINE" != "True" ]]; then
-        tox -revenv --notest
+        tox -revenv-tempest --notest
     fi
-    tox -evenv -- pip install -c $REQUIREMENTS_DIR/upper-constraints.txt -r requirements.txt
+    tox -evenv-tempest -- pip install -c $REQUIREMENTS_DIR/upper-constraints.txt -r requirements.txt
 
     # Auth:
     iniset $TEMPEST_CONFIG auth tempest_roles "Member"
     if [[ $TEMPEST_USE_TEST_ACCOUNTS == "True" ]]; then
         if [[ $TEMPEST_HAS_ADMIN == "True" ]]; then
-            tox -evenv -- tempest-account-generator -c $TEMPEST_CONFIG --os-username $admin_username --os-password "$password" --os-tenant-name $admin_project_name -r $TEMPEST_CONCURRENCY --with-admin etc/accounts.yaml
+            tox -evenv-tempest -- tempest-account-generator -c $TEMPEST_CONFIG --os-username $admin_username --os-password "$password" --os-tenant-name $admin_project_name -r $TEMPEST_CONCURRENCY --with-admin etc/accounts.yaml
         else
-            tox -evenv -- tempest-account-generator -c $TEMPEST_CONFIG --os-username $admin_username --os-password "$password" --os-tenant-name $admin_project_name -r $TEMPEST_CONCURRENCY etc/accounts.yaml
+            tox -evenv-tempest -- tempest-account-generator -c $TEMPEST_CONFIG --os-username $admin_username --os-password "$password" --os-tenant-name $admin_project_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"
@@ -581,20 +602,6 @@
     IFS=$ifs
 }
 
-
-# install_tempest_lib() - Collect source, prepare, and install ``tempest-lib``
-function install_tempest_lib {
-    if use_library_from_git "tempest-lib"; then
-        git_clone_by_name "tempest-lib"
-        setup_dev_lib "tempest-lib"
-        # NOTE(mtreinish) For testing ``tempest-lib`` from git with Tempest we need to
-        # put the git version of ``tempest-lib`` in the Tempest job's tox venv
-        export PIP_VIRTUAL_ENV=${PROJECT_VENV["tempest"]}
-        setup_dev_lib "tempest-lib"
-        unset PIP_VIRTUAL_ENV
-    fi
-}
-
 # install_tempest() - Collect source and prepare
 function install_tempest {
     git_clone $TEMPEST_REPO $TEMPEST_DIR $TEMPEST_BRANCH
@@ -604,9 +611,19 @@
     # NOTE(mtreinish) Respect constraints in the tempest full venv, things that
     # are using a tox job other than full will not be respecting constraints but
     # running pip install -U on tempest requirements
-    $TEMPEST_DIR/.tox/full/bin/pip install -c $REQUIREMENTS_DIR/upper-constraints.txt -r requirements.txt
-    PROJECT_VENV["tempest"]=${TEMPEST_DIR}/.tox/full
-    install_tempest_lib
+    $TEMPEST_DIR/.tox/tempest/bin/pip install -c $REQUIREMENTS_DIR/upper-constraints.txt -r requirements.txt
+    PROJECT_VENV["tempest"]=${TEMPEST_DIR}/.tox/tempest
+    popd
+}
+
+# install_tempest_plugins() - Install any specified plugins into the tempest venv
+function install_tempest_plugins {
+    pushd $TEMPEST_DIR
+    if [[ $TEMPEST_PLUGINS != 0 ]] ; then
+        tox -evenv-tempest -- pip install $TEMPEST_PLUGINS
+        echo "Checking installed Tempest plugins:"
+        tox -evenv-tempest -- tempest list-plugins
+    fi
     popd
 }
 
diff --git a/lib/template b/lib/template
index 08d10bb..b92fb40 100644
--- a/lib/template
+++ b/lib/template
@@ -35,8 +35,8 @@
 XXX_CONF_DIR=/etc/XXXX
 
 
-# Entry Points
-# ------------
+# Functions
+# ---------
 
 # Test if any XXXX services are enabled
 # is_XXXX_enabled
@@ -62,6 +62,11 @@
     :
 }
 
+# create_XXXX_accounts() - Create required service accounts
+function create_XXXX_accounts {
+    :
+}
+
 # init_XXXX() - Initialize databases, etc.
 function init_XXXX {
     # clean up from previous (possibly aborted) runs
diff --git a/openrc b/openrc
index db2e97d..8d8ae8b 100644
--- a/openrc
+++ b/openrc
@@ -90,6 +90,13 @@
 #
 export OS_AUTH_URL=$KEYSTONE_AUTH_PROTOCOL://$KEYSTONE_AUTH_HOST:5000/v${OS_IDENTITY_API_VERSION}
 
+# Currently, in order to use openstackclient with Identity API v3,
+# we need to set the domain which the user and project belong to.
+if [ "$OS_IDENTITY_API_VERSION" = "3" ]; then
+    export OS_USER_DOMAIN_ID=${OS_USER_DOMAIN_ID:-"default"}
+    export OS_PROJECT_DOMAIN_ID=${OS_PROJECT_DOMAIN_ID:-"default"}
+fi
+
 # Set OS_CACERT to a default CA certificate chain if it exists.
 if [[ ! -v OS_CACERT ]] ; then
     DEFAULT_OS_CACERT=$INT_CA_DIR/ca-chain.pem
diff --git a/pkg/elasticsearch.sh b/pkg/elasticsearch.sh
index 9c4f6f7..856eaff 100755
--- a/pkg/elasticsearch.sh
+++ b/pkg/elasticsearch.sh
@@ -10,7 +10,7 @@
 
 # Package source and version, all pkg files are expected to have
 # something like this, as well as a way to override them.
-ELASTICSEARCH_VERSION=${ELASTICSEARCH_VERSION:-1.4.2}
+ELASTICSEARCH_VERSION=${ELASTICSEARCH_VERSION:-1.7.5}
 ELASTICSEARCH_BASEURL=${ELASTICSEARCH_BASEURL:-https://download.elasticsearch.org/elasticsearch/elasticsearch}
 
 # Elastic search actual implementation
diff --git a/samples/local.conf b/samples/local.conf
index 06ac185..6d5351f 100644
--- a/samples/local.conf
+++ b/samples/local.conf
@@ -10,7 +10,7 @@
 
 # This is a collection of some of the settings we have found to be useful
 # in our DevStack development environments. Additional settings are described
-# in http://devstack.org/local.conf.html
+# in http://docs.openstack.org/developer/devstack/configuration.html#local-conf
 # These should be considered as samples and are unsupported DevStack code.
 
 # The ``localrc`` section replaces the old ``localrc`` configuration file.
diff --git a/stack.sh b/stack.sh
index 739d939..823b63b 100755
--- a/stack.sh
+++ b/stack.sh
@@ -185,7 +185,7 @@
 
 # Warn users who aren't on an explicitly supported distro, but allow them to
 # override check and attempt installation with ``FORCE=yes ./stack``
-if [[ ! ${DISTRO} =~ (trusty|wily|xenial|7.0|wheezy|sid|testing|jessie|f22|f23|rhel7|kvmibm1) ]]; then
+if [[ ! ${DISTRO} =~ (trusty|wily|xenial|7.0|wheezy|sid|testing|jessie|f23|f24|rhel7|kvmibm1) ]]; then
     echo "WARNING: this script has not been tested on $DISTRO"
     if [[ "$FORCE" != "yes" ]]; then
         die $LINENO "If you wish to run this script anyway run with FORCE=yes"
@@ -240,7 +240,6 @@
 # see them by forcing ``PATH``
 echo "Defaults:$STACK_USER secure_path=/sbin:/usr/sbin:/usr/bin:/bin:/usr/local/sbin:/usr/local/bin" >> $TEMPFILE
 echo "Defaults:$STACK_USER !requiretty" >> $TEMPFILE
-echo "Defaults env_keep += PS4" >> $TEMPFILE
 chmod 0440 $TEMPFILE
 sudo chown root:root $TEMPFILE
 sudo mv $TEMPFILE /etc/sudoers.d/50_stack_sh
@@ -336,6 +335,13 @@
 # to speed things up
 SKIP_EPEL_INSTALL=$(trueorfalse False SKIP_EPEL_INSTALL)
 
+# If we have /etc/nodepool/provider assume we're on a OpenStack CI
+# node, where EPEL is already pointing at our internal mirror and RDO
+# is pre-installed.
+if [[ -f /etc/nodepool/provider ]]; then
+    SKIP_EPEL_INSTALL=True
+fi
+
 if is_fedora && [[ $DISTRO == "rhel7" ]] && \
         [[ ${SKIP_EPEL_INSTALL} != True ]]; then
     _install_epel_and_rdo
@@ -559,10 +565,12 @@
 source $TOP_DIR/lib/cinder
 source $TOP_DIR/lib/swift
 source $TOP_DIR/lib/heat
+source $TOP_DIR/lib/neutron
 source $TOP_DIR/lib/neutron-legacy
 source $TOP_DIR/lib/ldap
 source $TOP_DIR/lib/dstat
 source $TOP_DIR/lib/dlm
+source $TOP_DIR/lib/os_brick
 
 # Extras Source
 # --------------
@@ -789,6 +797,11 @@
     install_heatclient
 fi
 
+# Install shared libraries
+if is_service_enabled cinder nova; then
+    install_os_brick
+fi
+
 # Install middleware
 install_keystonemiddleware
 
@@ -830,7 +843,6 @@
 if is_service_enabled neutron; then
     # Network service
     stack_install_service neutron
-    install_neutron_third_party
 fi
 
 if is_service_enabled nova; then
@@ -1020,7 +1032,7 @@
 export OS_PASSWORD=$ADMIN_PASSWORD
 export OS_PROJECT_NAME=admin
 export OS_PROJECT_DOMAIN_ID=default
-export OS_REGION_NAME=$REGION_NAME
+export OS_REGION_NAME=$KEYSTONE_REGION_NAME
 
 EOF
 
@@ -1075,20 +1087,11 @@
 
     configure_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
+    if is_service_enabled $DATABASE_BACKENDS && is_service_enabled neutron; then
         init_neutron
     fi
 fi
 
-# Some Neutron plugins require network controllers which are not
-# a part of the OpenStack project. Configure and start them.
-if is_service_enabled neutron; then
-    configure_neutron_third_party
-    init_neutron_third_party
-    start_neutron_third_party
-fi
-
-
 # Nova
 # ----
 
@@ -1142,7 +1145,7 @@
 
     # Additional Nova configuration that is dependent on other services
     if is_service_enabled neutron; then
-        create_nova_conf_neutron
+        configure_neutron_nova
     elif is_service_enabled n-net; then
         create_nova_conf_nova_network
     fi
@@ -1208,9 +1211,9 @@
     done
 fi
 
-# Create a randomized default value for the keymgr's fixed_key
+# Create a randomized default value for the key manager's fixed_key
 if is_service_enabled nova; then
-    iniset $NOVA_CONF keymgr fixed_key $(generate_hex_string 32)
+    iniset $NOVA_CONF key_manager fixed_key $(generate_hex_string 32)
 fi
 
 # Launch the nova-api and wait for it to answer before continuing
@@ -1219,10 +1222,12 @@
     start_nova_api
 fi
 
-if is_service_enabled q-svc; then
+if is_service_enabled neutron-api; then
+    echo_summary "Starting Neutron"
+    start_neutron_api
+elif is_service_enabled q-svc; then
     echo_summary "Starting Neutron"
     start_neutron_service_and_check
-    check_neutron_third_party_integration
 elif is_service_enabled $DATABASE_BACKENDS && is_service_enabled n-net; then
     NM_CONF=${NOVA_CONF}
     if is_service_enabled n-cell; then
@@ -1240,14 +1245,14 @@
 fi
 
 if is_service_enabled neutron; then
-    start_neutron_agents
+    start_neutron
 fi
 # Once neutron agents are started setup initial network elements
 if is_service_enabled q-svc && [[ "$NEUTRON_CREATE_INITIAL_NETWORKS" == "True" ]]; then
     echo_summary "Creating initial neutron network elements"
     create_neutron_initial_network
-    setup_neutron_debug
 fi
+
 if is_service_enabled nova; then
     echo_summary "Starting Nova"
     start_nova
@@ -1367,6 +1372,12 @@
     fi
 fi
 
+# Run test-config
+# ---------------
+
+# Phase: test-config
+run_phase stack test-config
+
 
 # Fin
 # ===
diff --git a/stackrc b/stackrc
index 5dd837b..4fefe8d 100644
--- a/stackrc
+++ b/stackrc
@@ -42,6 +42,12 @@
 # Specify region name Region
 REGION_NAME=${REGION_NAME:-RegionOne}
 
+# Specify name of region where identity service endpoint is registered.
+# When deploying multiple DevStack instances in different regions with shared
+# Keystone, set KEYSTONE_REGION_NAME to the region where Keystone is running
+# for DevStack instances which do not host Keystone.
+KEYSTONE_REGION_NAME=${KEYSTONE_REGION_NAME:-$REGION_NAME}
+
 # Specify which services to launch.  These generally correspond to
 # screen tabs. To change the default list, use the ``enable_service`` and
 # ``disable_service`` functions in ``local.conf``.
@@ -64,11 +70,13 @@
     # Keystone - nothing works without keystone
     ENABLED_SERVICES=key
     # Nova - services to support libvirt based openstack clouds
-    ENABLED_SERVICES+=,n-api,n-cpu,n-net,n-cond,n-sch,n-novnc,n-cauth
+    ENABLED_SERVICES+=,n-api,n-cpu,n-cond,n-sch,n-novnc,n-cauth
     # Glance services needed for Nova
     ENABLED_SERVICES+=,g-api,g-reg
     # Cinder
     ENABLED_SERVICES+=,c-sch,c-api,c-vol
+    # Neutron
+    ENABLED_SERVICES+=,q-svc,q-dhcp,q-meta,q-agt,q-l3
     # Dashboard
     ENABLED_SERVICES+=,horizon
     # Additional services
@@ -129,12 +137,29 @@
     source $RC_DIR/.localrc.auto
 fi
 
+# Default for log coloring is based on interactive-or-not.
+# Baseline assumption is that non-interactive invocations are for CI,
+# where logs are to be presented as browsable text files; hence color
+# codes should be omitted.
+# Simply override LOG_COLOR if your environment is different.
+if [ -t 1 ]; then
+    _LOG_COLOR_DEFAULT=True
+else
+    _LOG_COLOR_DEFAULT=False
+fi
+
 # Use color for logging output (only available if syslog is not used)
-LOG_COLOR=$(trueorfalse True LOG_COLOR)
+LOG_COLOR=$(trueorfalse $_LOG_COLOR_DEFAULT LOG_COLOR)
 
 # Make tracing more educational
 if [[ "$LOG_COLOR" == "True" ]]; then
-    export PS4='+\[$(tput setaf 242)\]$(short_source)\[$(tput sgr0)\] '
+    # tput requires TERM or -T.  If neither is present, use vt100, a
+    # no-frills least common denominator supported everywhere.
+    TPUT_T=
+    if ! [ $TERM ]; then
+        TPUT_T='-T vt100'
+    fi
+    export PS4='+\[$(tput '$TPUT_T' setaf 242)\]$(short_source)\[$(tput '$TPUT_T' sgr0)\] '
 else
     export PS4='+ $(short_source):   '
 fi
@@ -202,6 +227,9 @@
 # ex: LIBS_FROM_GIT=python-keystoneclient,oslo.config
 #
 # Will install those 2 libraries from git, the rest from pypi.
+#
+# Setting the variable to 'ALL' will activate the download for all
+# libraries.
 
 
 ##############
@@ -238,9 +266,9 @@
 NEUTRON_FWAAS_REPO=${NEUTRON_FWAAS_REPO:-${GIT_BASE}/openstack/neutron-fwaas.git}
 NEUTRON_FWAAS_BRANCH=${NEUTRON_FWAAS_BRANCH:-master}
 
-# neutron vpnaas service
-NEUTRON_VPNAAS_REPO=${NEUTRON_VPNAAS_REPO:-${GIT_BASE}/openstack/neutron-vpnaas.git}
-NEUTRON_VPNAAS_BRANCH=${NEUTRON_VPNAAS_BRANCH:-master}
+# neutron lbaas service
+NEUTRON_LBAAS_REPO=${NEUTRON_LBAAS_REPO:-${GIT_BASE}/openstack/neutron-lbaas.git}
+NEUTRON_LBAAS_BRANCH=${NEUTRON_LBAAS_BRANCH:-master}
 
 # compute service
 NOVA_REPO=${NOVA_REPO:-${GIT_BASE}/openstack/nova.git}
@@ -264,10 +292,6 @@
 TEMPEST_REPO=${TEMPEST_REPO:-${GIT_BASE}/openstack/tempest.git}
 TEMPEST_BRANCH=${TEMPEST_BRANCH:-master}
 
-# TODO(sdague): this should end up as a library component like below
-GITREPO["tempest-lib"]=${TEMPEST_LIB_REPO:-${GIT_BASE}/openstack/tempest-lib.git}
-GITBRANCH["tempest-lib"]=${TEMPEST_LIB_BRANCH:-master}
-
 
 ##############
 #
@@ -280,6 +304,10 @@
 GITREPO["python-cinderclient"]=${CINDERCLIENT_REPO:-${GIT_BASE}/openstack/python-cinderclient.git}
 GITBRANCH["python-cinderclient"]=${CINDERCLIENT_BRANCH:-master}
 
+# os-brick client for local volume attachement
+GITREPO["python-brick-cinderclient-ext"]=${BRICK_CINDERCLIENT_REPO:-${GIT_BASE}/openstack/python-brick-cinderclient-ext.git}
+GITBRANCH["python-brick-cinderclient-ext"]=${BRICK_CINDERCLIENT_BRANCH:-master}
+
 # python glance client library
 GITREPO["python-glanceclient"]=${GLANCECLIENT_REPO:-${GIT_BASE}/openstack/python-glanceclient.git}
 GITBRANCH["python-glanceclient"]=${GLANCECLIENT_BRANCH:-master}
@@ -684,6 +712,8 @@
 PRIVATE_NETWORK_NAME=${PRIVATE_NETWORK_NAME:-"private"}
 PUBLIC_NETWORK_NAME=${PUBLIC_NETWORK_NAME:-"public"}
 
+PUBLIC_INTERFACE=${PUBLIC_INTERFACE:-""}
+
 # Set default screen name
 SCREEN_NAME=${SCREEN_NAME:-stack}
 
diff --git a/tests/test_libs_from_pypi.sh b/tests/test_libs_from_pypi.sh
index f01db6d..bb58088 100755
--- a/tests/test_libs_from_pypi.sh
+++ b/tests/test_libs_from_pypi.sh
@@ -31,7 +31,7 @@
 
 ALL_LIBS="python-novaclient oslo.config pbr oslo.context"
 ALL_LIBS+=" python-keystoneclient taskflow oslo.middleware pycadf"
-ALL_LIBS+=" python-glanceclient python-ironicclient tempest-lib"
+ALL_LIBS+=" python-glanceclient python-ironicclient"
 ALL_LIBS+=" oslo.messaging oslo.log cliff python-heatclient stevedore"
 ALL_LIBS+=" python-cinderclient glance_store oslo.concurrency oslo.db"
 ALL_LIBS+=" oslo.versionedobjects oslo.vmware keystonemiddleware"
@@ -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 os-vif"
+ALL_LIBS+=" diskimage-builder os-vif python-brick-cinderclient-ext"
 
 # Generate the above list with
 # echo ${!GITREPO[@]}
diff --git a/tests/test_localconf.sh b/tests/test_localconf.sh
new file mode 100755
index 0000000..d8075df
--- /dev/null
+++ b/tests/test_localconf.sh
@@ -0,0 +1,475 @@
+#!/usr/bin/env bash
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# permissions and limitations under the License.
+
+# Tests for DevStack INI functions
+
+TOP=$(cd $(dirname "$0")/.. && pwd)
+
+# Import config functions
+source $TOP/inc/ini-config
+
+source $TOP/tests/unittest.sh
+
+echo "Testing INI local.conf functions"
+
+# test that can determine if file has section in specified meta-section
+
+function test_localconf_has_section {
+    local file_localconf
+    local file_conf1
+    local file_conf2
+    file_localconf=`mktemp`
+    file_conf1=`mktemp`
+    file_conf2=`mktemp`
+
+    cat <<- EOF > $file_localconf
+[[local|localrc]]
+LOCALRC_VAR1=localrc_val1
+LOCALRC_VAR2=localrc_val2
+LOCALRC_VAR3=localrc_val3
+
+[[post-config|$file_conf1]]
+[conf1_t1]
+conf1_t1_opt1=conf1_t1_val1
+conf1_t1_opt2=conf1_t1_val2
+conf1_t1_opt3=conf1_t1_val3
+[conf1_t2]
+conf1_t2_opt1=conf1_t2_val1
+conf1_t2_opt2=conf1_t2_val2
+conf1_t2_opt3=conf1_t2_val3
+[conf1_t3]
+conf1_t3_opt1=conf1_t3_val1
+conf1_t3_opt2=conf1_t3_val2
+conf1_t3_opt3=conf1_t3_val3
+
+[[post-extra|$file_conf2]]
+[conf2_t1]
+conf2_t1_opt1=conf2_t1_val1
+conf2_t1_opt2=conf2_t1_val2
+conf2_t1_opt3=conf2_t1_val3
+EOF
+
+    localconf_has_section $file_localconf post-config $file_conf1 conf1_t1
+    assert_equal $? 0
+    localconf_has_section $file_localconf post-config $file_conf1 conf1_t2
+    assert_equal $? 0
+    localconf_has_section $file_localconf post-config $file_conf1 conf1_t3
+    assert_equal $? 0
+    localconf_has_section $file_localconf post-extra $file_conf2 conf2_t1
+    assert_equal $? 0
+    localconf_has_section $file_localconf post-config $file_conf1 conf1_t4
+    assert_equal $? 1
+    localconf_has_section $file_localconf post-install $file_conf1 conf1_t1
+    assert_equal $? 1
+    localconf_has_section $file_localconf local localrc conf1_t2
+    assert_equal $? 1
+    rm -f $file_localconf $file_conf1 $file_conf2
+}
+
+# test that can determine if file has option in specified meta-section and section
+function test_localconf_has_option {
+    local file_localconf
+    local file_conf1
+    local file_conf2
+    file_localconf=`mktemp`
+    file_conf1=`mktemp`
+    file_conf2=`mktemp`
+    cat <<- EOF > $file_localconf
+[[post-config|$file_conf1]]
+[conf1_t1]
+conf1_t1_opt1 = conf1_t1_val1
+conf1_t1_opt2 = conf1_t1_val2
+conf1_t1_opt3 = conf1_t1_val3
+[conf1_t2]
+conf1_t2_opt1=conf1_t2_val1
+conf1_t2_opt2=conf1_t2_val2
+conf1_t2_opt3=conf1_t2_val3
+[conf1_t3]
+conf1_t3_opt1=conf1_t3_val1
+conf1_t3_opt2=conf1_t3_val2
+conf1_t3_opt3=conf1_t3_val3
+
+[[local|localrc]]
+LOCALRC_VAR1=localrc_val1
+LOCALRC_VAR2=localrc_val2
+LOCALRC_VAR3=localrc_val3
+
+[[post-extra|$file_conf2]]
+[conf2_t1]
+conf2_t1_opt1=conf2_t1_val1
+conf2_t1_opt2=conf2_t1_val2
+conf2_t1_opt3=conf2_t1_val3
+EOF
+
+    localconf_has_option $file_localconf local localrc "" LOCALRC_VAR1
+    assert_equal $? 0
+    localconf_has_option $file_localconf local localrc "" LOCALRC_VAR2
+    assert_equal $? 0
+    localconf_has_option $file_localconf local localrc "" LOCALRC_VAR3
+    assert_equal $? 0
+    localconf_has_option $file_localconf post-config $file_conf1 conf1_t1 conf1_t1_opt1
+    assert_equal $? 0
+    localconf_has_option $file_localconf post-config $file_conf1 conf1_t2 conf1_t2_opt2
+    assert_equal $? 0
+    localconf_has_option $file_localconf post-config $file_conf1 conf1_t3 conf1_t3_opt3
+    assert_equal $? 0
+    localconf_has_option $file_localconf post-extra $file_conf2 conf2_t1 conf2_t1_opt2
+    assert_equal $? 0
+    localconf_has_option $file_localconf post-config $file_conf1 conf1_t1_opt4
+    assert_equal $? 1
+    localconf_has_option $file_localconf post-install $file_conf1 conf1_t1_opt1
+    assert_equal $? 1
+    localconf_has_option $file_localconf local localrc conf1_t2 conf1_t2_opt1
+    assert_equal $? 1
+    rm -f $file_localconf $file_conf1 $file_conf2
+}
+
+# test that update option in specified meta-section and section
+function test_localconf_update_option {
+    local file_localconf
+    local file_localconf_expected
+    local file_conf1
+    local file_conf2
+    file_localconf=`mktemp`
+    file_localconf_expected=`mktemp`
+    file_conf1=`mktemp`
+    file_conf2=`mktemp`
+    cat <<- EOF > $file_localconf
+[[local|localrc]]
+LOCALRC_VAR1 = localrc_val1
+LOCALRC_VAR2 = localrc_val2
+LOCALRC_VAR3 = localrc_val3
+
+[[post-config|$file_conf1]]
+[conf1_t1]
+conf1_t1_opt1=conf1_t1_val1
+conf1_t1_opt2=conf1_t1_val2
+conf1_t1_opt3=conf1_t1_val3
+[conf1_t2]
+conf1_t2_opt1=conf1_t2_val1
+conf1_t2_opt2=conf1_t2_val2
+conf1_t2_opt3=conf1_t2_val3
+[conf1_t3]
+conf1_t3_opt1=conf1_t3_val1
+conf1_t3_opt2=conf1_t3_val2
+conf1_t3_opt3=conf1_t3_val3
+
+[[post-extra|$file_conf2]]
+[conf2_t1]
+conf2_t1_opt1=conf2_t1_val1
+conf2_t1_opt2=conf2_t1_val2
+conf2_t1_opt3=conf2_t1_val3
+EOF
+    cat <<- EOF > $file_localconf_expected
+[[local|localrc]]
+LOCALRC_VAR1 = localrc_val1
+LOCALRC_VAR2 = localrc_val2_update
+LOCALRC_VAR3 = localrc_val3
+
+[[post-config|$file_conf1]]
+[conf1_t1]
+conf1_t1_opt1=conf1_t1_val1_update
+conf1_t1_opt2=conf1_t1_val2
+conf1_t1_opt3=conf1_t1_val3
+[conf1_t2]
+conf1_t2_opt1=conf1_t2_val1
+conf1_t2_opt2=conf1_t2_val2_update
+conf1_t2_opt3=conf1_t2_val3
+[conf1_t3]
+conf1_t3_opt1=conf1_t3_val1
+conf1_t3_opt2=conf1_t3_val2
+conf1_t3_opt3=conf1_t3_val3_update
+
+[[post-extra|$file_conf2]]
+[conf2_t1]
+conf2_t1_opt1=conf2_t1_val1
+conf2_t1_opt2=conf2_t1_val2
+conf2_t1_opt3=conf2_t1_val3_update
+EOF
+
+    localconf_update_option "$SUDO" $file_localconf local localrc "" LOCALRC_VAR2 localrc_val2_update
+    localconf_update_option "$SUDO" $file_localconf post-config $file_conf1 conf1_t1 conf1_t1_opt1 conf1_t1_val1_update
+    localconf_update_option "$SUDO" $file_localconf post-config $file_conf1 conf1_t2 conf1_t2_opt2 conf1_t2_val2_update
+    localconf_update_option "$SUDO" $file_localconf post-config $file_conf1 conf1_t3 conf1_t3_opt3 conf1_t3_val3_update
+    localconf_update_option "$SUDO" $file_localconf post-extra $file_conf2 conf2_t1 conf2_t1_opt3 conf2_t1_val3_update
+    result=`cat $file_localconf`
+    result_expected=`cat $file_localconf_expected`
+    assert_equal "$result" "$result_expected"
+    localconf_update_option "$SUDO" $file_localconf post-config $file_conf1 conf1_t2 conf1_t3_opt1 conf1_t3_val1_update
+    localconf_update_option "$SUDO" $file_localconf post-extra $file_conf2 conf2_t1 conf2_t1_opt4 conf2_t1_val4_update
+    localconf_update_option "$SUDO" $file_localconf post-install $file_conf2 conf2_t1 conf2_t1_opt1 conf2_t1_val1_update
+    localconf_update_option "$SUDO" $file_localconf local localrc "" LOCALRC_VAR4 localrc_val4_update
+    result=`cat $file_localconf`
+    result_expected=`cat $file_localconf_expected`
+    assert_equal "$result" "$result_expected"
+    rm -f $file_localconf $file_localconf_expected $file_conf1 $file_conf2
+}
+
+# test that add option in specified meta-section and section
+function test_localconf_add_option {
+    local file_localconf
+    local file_localconf_expected
+    local file_conf1
+    local file_conf2
+    file_localconf=`mktemp`
+    file_localconf_expected=`mktemp`
+    file_conf1=`mktemp`
+    file_conf2=`mktemp`
+    cat <<- EOF > $file_localconf
+[[post-config|$file_conf1]]
+[conf1_t1]
+conf1_t1_opt1=conf1_t1_val1
+conf1_t1_opt2=conf1_t1_val2
+conf1_t1_opt3=conf1_t1_val3
+[conf1_t2]
+conf1_t2_opt1=conf1_t2_val1
+conf1_t2_opt2=conf1_t2_val2
+conf1_t2_opt3=conf1_t2_val3
+[conf1_t3]
+conf1_t3_opt1=conf1_t3_val1
+conf1_t3_opt2=conf1_t3_val2
+conf1_t3_opt3=conf1_t3_val3
+
+[[local|localrc]]
+LOCALRC_VAR1=localrc_val1
+LOCALRC_VAR2=localrc_val2
+LOCALRC_VAR3=localrc_val3
+
+[[post-extra|$file_conf2]]
+[conf2_t1]
+conf2_t1_opt1 = conf2_t1_val1
+conf2_t1_opt2 = conf2_t1_val2
+conf2_t1_opt3 = conf2_t1_val3
+EOF
+    cat <<- EOF > $file_localconf_expected
+[[post-config|$file_conf1]]
+[conf1_t1]
+conf1_t1_opt4 = conf1_t1_val4
+conf1_t1_opt1=conf1_t1_val1
+conf1_t1_opt2=conf1_t1_val2
+conf1_t1_opt3=conf1_t1_val3
+[conf1_t2]
+conf1_t2_opt4 = conf1_t2_val4
+conf1_t2_opt1=conf1_t2_val1
+conf1_t2_opt2=conf1_t2_val2
+conf1_t2_opt3=conf1_t2_val3
+[conf1_t3]
+conf1_t3_opt4 = conf1_t3_val4
+conf1_t3_opt1=conf1_t3_val1
+conf1_t3_opt2=conf1_t3_val2
+conf1_t3_opt3=conf1_t3_val3
+
+[[local|localrc]]
+LOCALRC_VAR4 = localrc_val4
+LOCALRC_VAR1=localrc_val1
+LOCALRC_VAR2=localrc_val2
+LOCALRC_VAR3=localrc_val3
+
+[[post-extra|$file_conf2]]
+[conf2_t1]
+conf2_t1_opt4 = conf2_t1_val4
+conf2_t1_opt1 = conf2_t1_val1
+conf2_t1_opt2 = conf2_t1_val2
+conf2_t1_opt3 = conf2_t1_val3
+EOF
+
+    localconf_add_option "$SUDO" $file_localconf local localrc "" LOCALRC_VAR4 localrc_val4
+    localconf_add_option "$SUDO" $file_localconf post-config $file_conf1 conf1_t1 conf1_t1_opt4 conf1_t1_val4
+    localconf_add_option "$SUDO" $file_localconf post-config $file_conf1 conf1_t2 conf1_t2_opt4 conf1_t2_val4
+    localconf_add_option "$SUDO" $file_localconf post-config $file_conf1 conf1_t3 conf1_t3_opt4 conf1_t3_val4
+    localconf_add_option "$SUDO" $file_localconf post-extra $file_conf2 conf2_t1 conf2_t1_opt4 conf2_t1_val4
+    result=`cat $file_localconf`
+    result_expected=`cat $file_localconf_expected`
+    assert_equal "$result" "$result_expected"
+    localconf_add_option "$SUDO" $file_localconf local localrc.conf "" LOCALRC_VAR4 localrc_val4_update
+    localconf_add_option "$SUDO" $file_localconf post-config $file_conf1 conf1_t4 conf1_t4_opt1 conf1_t4_val1
+    localconf_add_option "$SUDO" $file_localconf post-extra $file_conf2 conf2_t2 conf2_t2_opt4 conf2_t2_val4
+    localconf_add_option "$SUDO" $file_localconf post-install $file_conf2 conf2_t1 conf2_t1_opt4 conf2_t2_val4
+    result=`cat $file_localconf`
+    result_expected=`cat $file_localconf_expected`
+    assert_equal "$result" "$result_expected"
+    rm -f $file_localconf $file_localconf_expected $file_conf1 $file_conf2
+}
+
+# test that add section and option in specified meta-section
+function test_localconf_add_section_and_option {
+    local file_localconf
+    local file_localconf_expected
+    local file_conf1
+    local file_conf2
+    file_localconf=`mktemp`
+    file_localconf_expected=`mktemp`
+    file_conf1=`mktemp`
+    file_conf2=`mktemp`
+    cat <<- EOF > $file_localconf
+[[post-config|$file_conf1]]
+[conf1_t1]
+conf1_t1_opt1=conf1_t1_val1
+conf1_t1_opt2=conf1_t1_val2
+conf1_t1_opt3=conf1_t1_val3
+[conf1_t2]
+conf1_t2_opt1=conf1_t2_val1
+conf1_t2_opt2=conf1_t2_val2
+conf1_t2_opt3=conf1_t2_val3
+[conf1_t3]
+conf1_t3_opt1=conf1_t3_val1
+conf1_t3_opt2=conf1_t3_val2
+conf1_t3_opt3=conf1_t3_val3
+
+[[local|localrc]]
+LOCALRC_VAR1=localrc_val1
+LOCALRC_VAR2=localrc_val2
+LOCALRC_VAR3=localrc_val3
+
+[[post-extra|$file_conf2]]
+[conf2_t1]
+conf2_t1_opt1=conf2_t1_val1
+conf2_t1_opt2=conf2_t1_val2
+conf2_t1_opt3=conf2_t1_val3
+EOF
+    cat <<- EOF > $file_localconf_expected
+[[post-config|$file_conf1]]
+[conf1_t4]
+conf1_t4_opt1 = conf1_t4_val1
+[conf1_t1]
+conf1_t1_opt1=conf1_t1_val1
+conf1_t1_opt2=conf1_t1_val2
+conf1_t1_opt3=conf1_t1_val3
+[conf1_t2]
+conf1_t2_opt1=conf1_t2_val1
+conf1_t2_opt2=conf1_t2_val2
+conf1_t2_opt3=conf1_t2_val3
+[conf1_t3]
+conf1_t3_opt1=conf1_t3_val1
+conf1_t3_opt2=conf1_t3_val2
+conf1_t3_opt3=conf1_t3_val3
+
+[[local|localrc]]
+LOCALRC_VAR1=localrc_val1
+LOCALRC_VAR2=localrc_val2
+LOCALRC_VAR3=localrc_val3
+
+[[post-extra|$file_conf2]]
+[conf2_t2]
+conf2_t2_opt1 = conf2_t2_val1
+[conf2_t1]
+conf2_t1_opt1=conf2_t1_val1
+conf2_t1_opt2=conf2_t1_val2
+conf2_t1_opt3=conf2_t1_val3
+EOF
+
+    localconf_add_section_and_option "$SUDO" $file_localconf post-config $file_conf1 conf1_t4 conf1_t4_opt1 conf1_t4_val1
+    localconf_add_section_and_option "$SUDO" $file_localconf post-extra $file_conf2 conf2_t2 conf2_t2_opt1 conf2_t2_val1
+    result=`cat $file_localconf`
+    result_expected=`cat $file_localconf_expected`
+    assert_equal "$result" "$result_expected"
+    localconf_add_section_and_option "$SUDO" $file_localconf post-install $file_conf2 conf2_t2 conf2_t2_opt1 conf2_t2_val1
+    result=`cat $file_localconf`
+    result_expected=`cat $file_localconf_expected`
+    assert_equal "$result" "$result_expected"
+    rm -f $file_localconf $file_localconf_expected $file_conf1 $file_conf2
+}
+
+# test that add section and option in specified meta-section
+function test_localconf_set {
+    local file_localconf
+    local file_localconf_expected
+    local file_conf1
+    local file_conf2
+    file_localconf=`mktemp`
+    file_localconf_expected=`mktemp`
+    file_conf1=`mktemp`
+    file_conf2=`mktemp`
+    cat <<- EOF > $file_localconf
+[[local|localrc]]
+LOCALRC_VAR1=localrc_val1
+LOCALRC_VAR2=localrc_val2
+LOCALRC_VAR3=localrc_val3
+
+[[post-config|$file_conf1]]
+[conf1_t1]
+conf1_t1_opt1=conf1_t1_val1
+conf1_t1_opt2=conf1_t1_val2
+conf1_t1_opt3=conf1_t1_val3
+[conf1_t2]
+conf1_t2_opt1=conf1_t2_val1
+conf1_t2_opt2=conf1_t2_val2
+conf1_t2_opt3=conf1_t2_val3
+[conf1_t3]
+conf1_t3_opt1=conf1_t3_val1
+conf1_t3_opt2=conf1_t3_val2
+conf1_t3_opt3=conf1_t3_val3
+
+[[post-extra|$file_conf2]]
+[conf2_t1]
+conf2_t1_opt1=conf2_t1_val1
+conf2_t1_opt2=conf2_t1_val2
+conf2_t1_opt3=conf2_t1_val3
+EOF
+    cat <<- EOF > $file_localconf_expected
+[[local|localrc]]
+LOCALRC_VAR1=localrc_val1
+LOCALRC_VAR2=localrc_val2_update
+LOCALRC_VAR3=localrc_val3
+
+[[post-config|$file_conf1]]
+[conf1_t4]
+conf1_t4_opt1 = conf1_t4_val1
+[conf1_t1]
+conf1_t1_opt1=conf1_t1_val1
+conf1_t1_opt2=conf1_t1_val2
+conf1_t1_opt3=conf1_t1_val3
+[conf1_t2]
+conf1_t2_opt1=conf1_t2_val1
+conf1_t2_opt2=conf1_t2_val2
+conf1_t2_opt3=conf1_t2_val3
+[conf1_t3]
+conf1_t3_opt1=conf1_t3_val1
+conf1_t3_opt2=conf1_t3_val2
+conf1_t3_opt3=conf1_t3_val3
+
+[[post-extra|$file_conf2]]
+[conf2_t1]
+conf2_t1_opt4 = conf2_t1_val4
+conf2_t1_opt1=conf2_t1_val1
+conf2_t1_opt2=conf2_t1_val2
+conf2_t1_opt3=conf2_t1_val3
+
+[[post-install|/etc/neutron/plugin/ml2/ml2_conf.ini]]
+[ml2]
+ml2_opt1 = ml2_val1
+EOF
+
+    if [[ -n "$SUDO" ]]; then
+        SUDO_ARG="-sudo"
+    else
+        SUDO_ARG=""
+    fi
+    localconf_set $SUDO_ARG $file_localconf post-install /etc/neutron/plugin/ml2/ml2_conf.ini ml2 ml2_opt1 ml2_val1
+    localconf_set $SUDO_ARG $file_localconf local localrc "" LOCALRC_VAR2 localrc_val2_update
+    localconf_set $SUDO_ARG $file_localconf post-config $file_conf1 conf1_t4 conf1_t4_opt1 conf1_t4_val1
+    localconf_set $SUDO_ARG $file_localconf post-extra $file_conf2 conf2_t1 conf2_t1_opt4 conf2_t1_val4
+    result=`cat $file_localconf`
+    result_expected=`cat $file_localconf_expected`
+    assert_equal "$result" "$result_expected"
+    rm -f $file_localconf $file_localconf_expected $file_conf1 $file_conf2
+}
+
+
+test_localconf_has_section
+test_localconf_has_option
+test_localconf_update_option
+test_localconf_add_option
+test_localconf_add_section_and_option
+test_localconf_set
diff --git a/tools/build_docs.sh b/tools/build_docs.sh
deleted file mode 100755
index 7dc492e..0000000
--- a/tools/build_docs.sh
+++ /dev/null
@@ -1,100 +0,0 @@
-#!/usr/bin/env bash
-
-# **build_docs.sh** - Build the docs for DevStack
-#
-# - Install shocco if not found on ``PATH`` and ``INSTALL_SHOCCO`` is set
-# - Clone ``MASTER_REPO`` branch ``MASTER_BRANCH``
-# - Re-creates ``doc/build/html`` directory from existing repo + new generated script docs
-
-# Usage:
-## build_docs.sh [-o <out-dir>]
-## -o <out-dir>     Write the static HTML output to <out-dir>
-##                  (Note that <out-dir> will be deleted and re-created to ensure it is clean)
-
-# Defaults
-# --------
-
-HTML_BUILD=doc/build/html
-
-# Keep track of the DevStack directory
-TOP_DIR=$(cd $(dirname "$0")/.. && pwd)
-
-# Uses this shocco branch: https://github.com/dtroyer/shocco/tree/rst_support
-SHOCCO=${SHOCCO:-shocco}
-if ! which shocco; then
-    if [[ ! -x $TOP_DIR/shocco/shocco ]]; then
-        if [[ -z "$INSTALL_SHOCCO" ]]; then
-            echo "shocco not found in \$PATH, please set environment variable SHOCCO"
-            exit 1
-        fi
-        echo "Installing local copy of shocco"
-        if ! which pygmentize; then
-            sudo pip install Pygments
-        fi
-        if ! which rst2html.py; then
-            sudo pip install docutils
-        fi
-        git clone -b rst_support https://github.com/dtroyer/shocco shocco
-        cd shocco
-        ./configure
-        make || exit
-        cd ..
-    fi
-    SHOCCO=$TOP_DIR/shocco/shocco
-fi
-
-# Process command-line args
-while getopts o: c; do
-    case $c in
-        o)  HTML_BUILD=$OPTARG
-            ;;
-    esac
-done
-shift `expr $OPTIND - 1`
-
-
-# Processing
-# ----------
-
-# Ensure build dir exists
-mkdir -p $HTML_BUILD
-
-# Get fully qualified dirs
-FQ_HTML_BUILD=$(cd $HTML_BUILD && pwd)
-
-# Insert automated bits
-GLOG=$(mktemp gitlogXXXX)
-echo "<ul>" >$GLOG
-git log \
-    --pretty=format:'            <li>%s - <em>Commit <a href="https://review.openstack.org/#q,%h,n,z">%h</a> %cd</em></li>' \
-    --date=short \
-    --since '6 months ago' | grep -v Merge >>$GLOG
-echo "</ul>" >>$GLOG
-sed -i~ -e $"/^.*%GIT_LOG%.*$/r $GLOG" -e $"/^.*%GIT_LOG%.*$/s/^.*%GIT_LOG%.*$//" $FQ_HTML_BUILD/changes.html
-rm -f $GLOG
-
-# Build list of scripts to process
-FILES=""
-for f in $(find . \( -name .git -o -name .tox \) -prune -o \( -type f -name \*.sh -not -path \*shocco/\* -print \)); do
-    echo $f
-    FILES+="$f "
-    mkdir -p $FQ_HTML_BUILD/`dirname $f`;
-    $SHOCCO $f > $FQ_HTML_BUILD/$f.html
-done
-for f in $(find functions functions-common inc lib pkg samples -type f -name \* ! -name *.md ! -name *.conf); do
-    echo $f
-    FILES+="$f "
-    mkdir -p $FQ_HTML_BUILD/`dirname $f`;
-    $SHOCCO $f > $FQ_HTML_BUILD/$f.html
-done
-echo "$FILES" >doc/files
-
-# Clean up or report the temp workspace
-if [[ -n REPO && -n $PUSH_REPO ]]; then
-    echo rm -rf $TMP_ROOT
-else
-    if [[ -z "$TMP_ROOT" ]]; then
-        TMP_ROOT="$(pwd)"
-    fi
-    echo "Built docs in $HTML_BUILD"
-fi
diff --git a/tools/cpu_map_update.py b/tools/cpu_map_update.py
deleted file mode 100755
index 92b7b8f..0000000
--- a/tools/cpu_map_update.py
+++ /dev/null
@@ -1,88 +0,0 @@
-#!/usr/bin/env python
-#
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-# This small script updates the libvirt CPU map to add a gate64 cpu model
-# that can be used to enable a common 64bit capable feature set across
-# devstack nodes so that features like nova live migration work.
-
-import sys
-import xml.etree.ElementTree as ET
-from xml.dom import minidom
-
-
-def update_cpu_map(tree):
-    root = tree.getroot()
-    cpus = root#.find("cpus")
-    x86 = None
-    for arch in cpus.findall("arch"):
-        if arch.get("name") == "x86":
-            x86 = arch
-            break
-    if x86 is not None:
-        # Create a gate64 cpu model that is core2duo less monitor, pse36,
-        # vme, and ssse3.
-        gate64 = ET.SubElement(x86, "model")
-        gate64.set("name", "gate64")
-        ET.SubElement(gate64, "vendor").set("name", "Intel")
-        ET.SubElement(gate64, "feature").set("name", "fpu")
-        ET.SubElement(gate64, "feature").set("name", "de")
-        ET.SubElement(gate64, "feature").set("name", "pse")
-        ET.SubElement(gate64, "feature").set("name", "tsc")
-        ET.SubElement(gate64, "feature").set("name", "msr")
-        ET.SubElement(gate64, "feature").set("name", "pae")
-        ET.SubElement(gate64, "feature").set("name", "mce")
-        ET.SubElement(gate64, "feature").set("name", "cx8")
-        ET.SubElement(gate64, "feature").set("name", "apic")
-        ET.SubElement(gate64, "feature").set("name", "sep")
-        ET.SubElement(gate64, "feature").set("name", "pge")
-        ET.SubElement(gate64, "feature").set("name", "cmov")
-        ET.SubElement(gate64, "feature").set("name", "pat")
-        ET.SubElement(gate64, "feature").set("name", "mmx")
-        ET.SubElement(gate64, "feature").set("name", "fxsr")
-        ET.SubElement(gate64, "feature").set("name", "sse")
-        ET.SubElement(gate64, "feature").set("name", "sse2")
-        ET.SubElement(gate64, "feature").set("name", "mtrr")
-        ET.SubElement(gate64, "feature").set("name", "mca")
-        ET.SubElement(gate64, "feature").set("name", "clflush")
-        ET.SubElement(gate64, "feature").set("name", "pni")
-        ET.SubElement(gate64, "feature").set("name", "nx")
-        ET.SubElement(gate64, "feature").set("name", "syscall")
-        ET.SubElement(gate64, "feature").set("name", "lm")
-
-
-def format_xml(root):
-    # Adapted from http://pymotw.com/2/xml/etree/ElementTree/create.html
-    # thank you dhellmann
-    rough_string = ET.tostring(root, encoding="UTF-8")
-    dom_parsed = minidom.parseString(rough_string)
-    return dom_parsed.toprettyxml("  ", encoding="UTF-8")
-
-
-def main():
-    if len(sys.argv) != 2:
-        raise Exception("Must pass path to cpu_map.xml to update")
-    cpu_map = sys.argv[1]
-    tree = ET.parse(cpu_map)
-    for model in tree.getroot().iter("model"):
-        if model.get("name") == "gate64":
-            # gate64 model is already present
-            return
-    update_cpu_map(tree)
-    pretty_xml = format_xml(tree.getroot())
-    with open(cpu_map, 'w') as f:
-        f.write(pretty_xml)
-
-
-if __name__ == "__main__":
-    main()
diff --git a/tools/create_userrc.sh b/tools/create_userrc.sh
index a7278e4..b6db5d1 100755
--- a/tools/create_userrc.sh
+++ b/tools/create_userrc.sh
@@ -22,6 +22,9 @@
     file=${file#$RC_DIR/}
     printf "%-40s " "$file:${called[1]}:${called[0]}"
 }
+# PS4 is exported to child shells and uses the 'short_source' function, so
+# export it so child shells have access to the 'short_source' function also.
+export -f short_source
 
 set -o xtrace
 
diff --git a/tools/fixup_stuff.sh b/tools/fixup_stuff.sh
index 193a1f7..4dec95e 100755
--- a/tools/fixup_stuff.sh
+++ b/tools/fixup_stuff.sh
@@ -162,7 +162,11 @@
 fi
 
 # The version of pip(1.5.4) supported by python-virtualenv(1.11.4) has
-# connection issues under proxy, hence uninstalling python-virtualenv package
-# and installing the latest version using pip.
-uninstall_package python-virtualenv
-pip_install -U virtualenv
+# connection issues under proxy so re-install the latest version using
+# pip. To avoid having pip's virtualenv overwritten by the distro's
+# package (e.g. due to installing a distro package with a dependency
+# on python-virtualenv), first install the distro python-virtualenv
+# to satisfy any dependencies then use pip to overwrite it.
+
+install_package python-virtualenv
+pip_install -U --force-reinstall virtualenv
diff --git a/tools/generate-devstack-plugins-list.py b/tools/generate-devstack-plugins-list.py
index 089a6ef..bbad1bf 100644
--- a/tools/generate-devstack-plugins-list.py
+++ b/tools/generate-devstack-plugins-list.py
@@ -44,16 +44,10 @@
     # stackforge, etc)
     return proj.startswith('openstack/')
 
-# Rather than returning a 404 for a nonexistent file, cgit delivers a
-# 0-byte response to a GET request.  It also does not provide a
-# Content-Length in a HEAD response, so the way we tell if a file exists
-# is to check the length of the entire GET response body.
+# Check if this project has a plugin file
 def has_devstack_plugin(proj):
     r = requests.get("https://git.openstack.org/cgit/%s/plain/devstack/plugin.sh" % proj)
-    if len(r.text) > 0:
-        return True
-    else:
-        return False
+    return r.status_code == 200
 
 logging.debug("Getting project list from %s" % url)
 r = requests.get(url)
diff --git a/tools/install_pip.sh b/tools/install_pip.sh
index dfa4f42..1267699 100755
--- a/tools/install_pip.sh
+++ b/tools/install_pip.sh
@@ -116,7 +116,7 @@
 
 # Eradicate any and all system packages
 
-# Python in f23 and f22 depends on the python-pip package so removing it
+# Python in fedora depends on the python-pip package so removing it
 # results in a nonfunctional system. pip on fedora installs to /usr so pip
 # can safely override the system pip for all versions of fedora
 if ! is_fedora ; then
diff --git a/tools/worlddump.py b/tools/worlddump.py
index 19a69e8..e1ef544 100755
--- a/tools/worlddump.py
+++ b/tools/worlddump.py
@@ -27,6 +27,16 @@
 import sys
 
 
+GMR_PROCESSES = (
+    'nova-compute',
+    'neutron-dhcp-agent',
+    'neutron-l3-agent',
+    'neutron-linuxbridge-agent',
+    'neutron-metadata-agent',
+    'neutron-openvswitch-agent',
+)
+
+
 def get_options():
     parser = argparse.ArgumentParser(
         description='Dump world state for debugging')
@@ -77,6 +87,13 @@
     print()
 
 
+def _bridge_list():
+    process = subprocess.Popen(['sudo', 'ovs-vsctl', 'list-br'],
+                               stdout=subprocess.PIPE)
+    stdout, _ = process.communicate()
+    return stdout.split()
+
+
 # This method gets a max openflow version supported by openvswitch.
 # For example 'ovs-ofctl --version' displays the following:
 #
@@ -158,14 +175,11 @@
     if not _find_cmd('ovs-vsctl'):
         return
 
-    # NOTE(ihrachys): worlddump is used outside of devstack context (f.e. in
-    # grenade), so there is no single place to determine the bridge names from.
-    # Hardcode for now.
-    bridges = ('br-int', 'br-tun', 'br-ex')
+    bridges = _bridge_list()
     ofctl_cmds = ('show', 'dump-ports-desc', 'dump-ports', 'dump-flows')
     ofp_max = _get_ofp_version()
     vers = 'OpenFlow10'
-    for i in range(ofp_max + 1):
+    for i in range(1, ofp_max + 1):
         vers += ',OpenFlow1' + str(i)
     _dump_cmd("sudo ovs-vsctl show")
     for ofctl_cmd in ofctl_cmds:
@@ -188,17 +202,18 @@
             _dump_cmd("sudo cat %s" % fullpath)
 
 
-def guru_meditation_report():
-    _header("nova-compute Guru Meditation Report")
+def guru_meditation_reports():
+    for service in GMR_PROCESSES:
+        _header("%s Guru Meditation Report" % service)
 
-    try:
-        subprocess.check_call(["pgrep","nova-compute"])
-    except subprocess.CalledProcessError:
-        print("Skipping as nova-compute does not appear to be running")
-        return
+        try:
+            subprocess.check_call(['pgrep', '-f', service])
+        except subprocess.CalledProcessError:
+            print("Skipping as %s does not appear to be running" % service)
+            continue
 
-    _dump_cmd("kill -s USR2 `pgrep nova-compute`")
-    print("guru meditation report in nova-compute log")
+        _dump_cmd("killall -e -USR2 %s" % service)
+        print("guru meditation report in %s log" % service)
 
 
 def main():
@@ -215,7 +230,7 @@
         iptables_dump()
         ebtables_dump()
         compute_consoles()
-        guru_meditation_report()
+        guru_meditation_reports()
 
 
 if __name__ == '__main__':
diff --git a/tools/xen/README.md b/tools/xen/README.md
index 21090e5..7062ecb 100644
--- a/tools/xen/README.md
+++ b/tools/xen/README.md
@@ -170,3 +170,9 @@
     xe vm-import filename="$mountdir/$TEMPLATE_FILENAME"
     umount "$mountdir"
     rm -rf "$mountdir"
+
+### Migrate OpenStack DomU to another host
+
+Given you need to migrate your DomU with OpenStack installed to another host,
+you need to set `XEN_INTEGRATION_BRIDGE` in localrc if neutron network is used.
+It is the bridge for `XEN_INT_BRIDGE_OR_NET_NAME` network created in Dom0
diff --git a/tools/xen/install_os_domU.sh b/tools/xen/install_os_domU.sh
index 46ff0b6..66b9eda 100755
--- a/tools/xen/install_os_domU.sh
+++ b/tools/xen/install_os_domU.sh
@@ -183,10 +183,8 @@
         # Copy the tools DEB to the XS web server
         XS_TOOLS_URL="https://github.com/downloads/citrix-openstack/warehouse/xe-guest-utilities_5.6.100-651_amd64.deb"
         ISO_DIR="/opt/xensource/packages/iso"
-        XS_TOOLS_FILE_NAME="xs-tools.deb"
-        XS_TOOLS_PATH="/root/$XS_TOOLS_FILE_NAME"
         if [ -e "$ISO_DIR" ]; then
-            TOOLS_ISO=$(ls -1 $ISO_DIR/xs-tools-*.iso | head -1)
+            TOOLS_ISO=$(ls -1 $ISO_DIR/*-tools-*.iso | head -1)
             TMP_DIR=/tmp/temp.$RANDOM
             mkdir -p $TMP_DIR
             mount -o loop $TOOLS_ISO $TMP_DIR
@@ -249,7 +247,7 @@
 fi
 
 if [ -n "${EXIT_AFTER_JEOS_INSTALLATION:-}" ]; then
-    echo "User requested to quit after JEOS instalation"
+    echo "User requested to quit after JEOS installation"
     exit 0
 fi
 
@@ -299,10 +297,10 @@
 # kernel parameter for DomU
 attach_network "$XEN_INT_BRIDGE_OR_NET_NAME"
 
-XEN_INTEGRATION_BRIDGE=$(bridge_for "$XEN_INT_BRIDGE_OR_NET_NAME")
+XEN_INTEGRATION_BRIDGE_DEFAULT=$(bridge_for "$XEN_INT_BRIDGE_OR_NET_NAME")
 append_kernel_cmdline \
     "$GUEST_NAME" \
-    "xen_integration_bridge=${XEN_INTEGRATION_BRIDGE}"
+    "xen_integration_bridge=${XEN_INTEGRATION_BRIDGE_DEFAULT}"
 
 FLAT_NETWORK_BRIDGE="${FLAT_NETWORK_BRIDGE:-$(bridge_for "$VM_BRIDGE_OR_NET_NAME")}"
 append_kernel_cmdline "$GUEST_NAME" "flat_network_bridge=${FLAT_NETWORK_BRIDGE}"
diff --git a/tox.ini b/tox.ini
index 4ec2939..55a06d0 100644
--- a/tox.ini
+++ b/tox.ini
@@ -12,12 +12,11 @@
 # against devstack, just set BASHATE_INSTALL_PATH=/path/... to your
 # modified bashate tree
 deps =
-   {env:BASHATE_INSTALL_PATH:bashate==0.5.0}
+   {env:BASHATE_INSTALL_PATH:bashate==0.5.1}
 whitelist_externals = bash
 commands = bash -c "find {toxinidir}             \
          -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 \*~                          \
@@ -48,7 +47,15 @@
 whitelist_externals = bash
 setenv =
   TOP_DIR={toxinidir}
-  INSTALL_SHOCCO=true
-commands = 
-	python setup.py build_sphinx
-	bash tools/build_docs.sh
+commands =
+  python setup.py build_sphinx
+
+[testenv:venv]
+deps =
+   pbr>=0.6,!=0.7,<1.0
+   sphinx>=1.1.2,<1.2
+   oslosphinx
+   blockdiag
+   sphinxcontrib-blockdiag
+   sphinxcontrib-nwdiag
+commands = {posargs}
diff --git a/unstack.sh b/unstack.sh
index 83703ec..ece69ac 100755
--- a/unstack.sh
+++ b/unstack.sh
@@ -66,6 +66,7 @@
 source $TOP_DIR/lib/cinder
 source $TOP_DIR/lib/swift
 source $TOP_DIR/lib/heat
+source $TOP_DIR/lib/neutron
 source $TOP_DIR/lib/neutron-legacy
 source $TOP_DIR/lib/ldap
 source $TOP_DIR/lib/dstat
@@ -167,7 +168,6 @@
 
 if is_service_enabled neutron; then
     stop_neutron
-    stop_neutron_third_party
     cleanup_neutron
 fi