Merge "Set cinder's my_ip based on SERVICE_IP_VERSION value"
diff --git a/.zuul.yaml b/.zuul.yaml
index 2dd0b9f..9853798 100644
--- a/.zuul.yaml
+++ b/.zuul.yaml
@@ -39,10 +39,10 @@
           - controller
 
 - nodeset:
-    name: devstack-single-node-opensuse-150
+    name: devstack-single-node-opensuse-15
     nodes:
       - name: controller
-        label: opensuse-150
+        label: opensuse-15
     groups:
       - name: tempest
         nodes:
@@ -382,8 +382,6 @@
         SWIFT_HASH: 1234123412341234
         DEBUG_LIBVIRT_COREDUMPS: true
         NOVA_VNC_ENABLED: true
-        VNCSERVER_LISTEN: 0.0.0.0
-        VNCSERVER_PROXYCLIENT_ADDRESS: $HOST_IP
       devstack_local_conf:
         post-config:
           $NEUTRON_CONF:
@@ -479,8 +477,6 @@
           GLANCE_HOSTPORT: "{{ hostvars['controller']['nodepool']['private_ipv4'] }}:9292"
           Q_HOST: "{{ hostvars['controller']['nodepool']['private_ipv4'] }}"
           NOVA_VNC_ENABLED: true
-          VNCSERVER_LISTEN: 0.0.0.0
-          VNCSERVER_PROXYCLIENT_ADDRESS: $HOST_IP
 
 - job:
     name: devstack-ipv6
@@ -532,10 +528,10 @@
     voting: false
 
 - job:
-    name: devstack-platform-opensuse-150
+    name: devstack-platform-opensuse-15
     parent: tempest-full-py3
-    description: openSUSE 15.0 platform test
-    nodeset: devstack-single-node-opensuse-150
+    description: openSUSE 15.x platform test
+    nodeset: devstack-single-node-opensuse-15
     voting: false
 
 - job:
@@ -624,10 +620,9 @@
       jobs:
         - devstack
         - devstack-xenial
-        - devstack-ipv6:
-            voting: false
+        - devstack-ipv6
         - devstack-platform-centos-7
-        - devstack-platform-opensuse-150
+        - devstack-platform-opensuse-15
         - devstack-platform-fedora-latest
         - devstack-platform-xenial
         - devstack-multinode
@@ -662,10 +657,15 @@
             irrelevant-files:
               - ^.*\.rst$
               - ^doc/.*$
+        - tempest-ipv6-only:
+            irrelevant-files:
+              - ^.*\.rst$
+              - ^doc/.*$
     gate:
       jobs:
         - devstack
         - devstack-xenial
+        - devstack-ipv6
         - devstack-multinode
         - devstack-multinode-xenial
         - devstack-unit-tests
@@ -686,6 +686,10 @@
             irrelevant-files:
               - ^.*\.rst$
               - ^doc/.*$
+        - tempest-ipv6-only:
+            irrelevant-files:
+              - ^.*\.rst$
+              - ^doc/.*$
     # Please add a note on each job and conditions for the job not
     # being experimental any more, so we can keep this list somewhat
     # pruned.
diff --git a/HACKING.rst b/HACKING.rst
index f695106..f0bb269 100644
--- a/HACKING.rst
+++ b/HACKING.rst
@@ -189,7 +189,7 @@
 list below is not complete for what bashate checks, nor is it all checked
 by bashate.  So many lines of code, so little time.
 
-.. _bashate: https://pypi.python.org/pypi/bashate
+.. _bashate: https://pypi.org/project/bashate/
 
 Whitespace Rules
 ----------------
diff --git a/doc/requirements.txt b/doc/requirements.txt
index f65e9df..fffb83d 100644
--- a/doc/requirements.txt
+++ b/doc/requirements.txt
@@ -3,7 +3,7 @@
 Pygments
 docutils
 sphinx>=1.6.2
-openstackdocstheme>=1.11.0
+openstackdocstheme>=1.20.0
 nwdiag
 blockdiag
 sphinxcontrib-blockdiag
diff --git a/doc/source/conf.py b/doc/source/conf.py
index e9708fa..9059f8c 100644
--- a/doc/source/conf.py
+++ b/doc/source/conf.py
@@ -11,9 +11,6 @@
 # All configuration values have a default; values that are commented out
 # serve to show the default.
 
-import sys
-import os
-
 # If extensions (or modules to document with autodoc) are in another directory,
 # add these directories to sys.path here. If the directory is relative to the
 # documentation root, use os.path.abspath to make it absolute, like shown here.
@@ -26,13 +23,16 @@
 
 # Add any Sphinx extension module names here, as strings. They can be extensions
 # coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
-extensions = [ 'sphinx.ext.autodoc', 'zuul_sphinx', 'openstackdocstheme', 'sphinxcontrib.blockdiag', 'sphinxcontrib.nwdiag' ]
+extensions = [ 'sphinx.ext.autodoc',
+               'zuul_sphinx',
+               'openstackdocstheme',
+               'sphinxcontrib.blockdiag',
+               'sphinxcontrib.nwdiag' ]
 
 # openstackdocstheme options
 repository_name = 'openstack-dev/devstack'
 bug_project = 'devstack'
 bug_tag = ''
-html_last_updated_fmt = '%Y-%m-%d %H:%M'
 
 todo_include_todos = True
 
@@ -119,11 +119,6 @@
 # pixels large.
 #html_favicon = None
 
-# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
-# using the given strftime format.
-git_cmd = "git log --pretty=format:'%ad, commit %h' --date=local -n1"
-html_last_updated_fmt = os.popen(git_cmd).read()
-
 # If true, SmartyPants will be used to convert quotes and dashes to
 # typographically correct entities.
 #html_use_smartypants = True
@@ -167,17 +162,6 @@
 
 # -- Options for LaTeX output --------------------------------------------------
 
-latex_elements = {
-# The paper size ('letterpaper' or 'a4paper').
-#'papersize': 'letterpaper',
-
-# The font size ('10pt', '11pt' or '12pt').
-#'pointsize': '10pt',
-
-# Additional stuff for the LaTeX preamble.
-#'preamble': '',
-}
-
 # Grouping the document tree into LaTeX files. List of tuples
 # (source start file, target name, title, author, documentclass [howto/manual]).
 latex_documents = [
diff --git a/doc/source/configuration.rst b/doc/source/configuration.rst
index 0105d5e..45f4ffe 100644
--- a/doc/source/configuration.rst
+++ b/doc/source/configuration.rst
@@ -259,6 +259,8 @@
 Logging
 -------
 
+.. _enable_logging:
+
 Enable Logging
 ~~~~~~~~~~~~~~
 
@@ -495,7 +497,7 @@
 default flavors instead.
 
 KVM on Power with QEMU 2.4 requires 512 MB to load the firmware -
-`QEMU 2.4 - PowerPC <http://wiki.qemu.org/ChangeLog/2.4>`__ so users
+`QEMU 2.4 - PowerPC <https://wiki.qemu.org/ChangeLog/2.4>`__ so users
 running instances on ppc64/ppc64le can choose one of the default
 created flavors as follows:
 
diff --git a/doc/source/guides/devstack-with-lbaas-v2.rst b/doc/source/guides/devstack-with-lbaas-v2.rst
index 07a9bb3..669a70d 100644
--- a/doc/source/guides/devstack-with-lbaas-v2.rst
+++ b/doc/source/guides/devstack-with-lbaas-v2.rst
@@ -6,7 +6,7 @@
 
 This guide will show you how to create a devstack with `Octavia API`_ enabled.
 
-.. _Octavia API: https://developer.openstack.org/api-ref/load-balancer/v2/index.html
+.. _Octavia API: https://docs.openstack.org/api-ref/load-balancer/v2/index.html
 
 Phase 1: Create DevStack + 2 nova instances
 --------------------------------------------
@@ -39,7 +39,7 @@
     # If you are enabling horizon, include the octavia dashboard
     # enable_plugin octavia-dashboard https://opendev.org/openstack/octavia-dashboard.git
     # If you are enabling barbican for TLS offload in Octavia, include it here.
-    # enable_plugin barbican https://github.com/openstack/barbican.git
+    # enable_plugin barbican https://opendev.org/openstack/barbican
 
     # If you have python3 available:
     # USE_PYTHON3=True
diff --git a/doc/source/guides/nova.rst b/doc/source/guides/nova.rst
index 2271e23..5b42797 100644
--- a/doc/source/guides/nova.rst
+++ b/doc/source/guides/nova.rst
@@ -10,7 +10,7 @@
 ================
 
 In Juno, nova implemented a `spec
-<http://specs.openstack.org/openstack/nova-specs/specs/juno/implemented/serial-ports.html>`_
+<https://specs.openstack.org/openstack/nova-specs/specs/juno/implemented/serial-ports.html>`_
 to allow read/write access to the serial console of an instance via
 `nova-serialproxy
 <https://docs.openstack.org/nova/latest/cli/nova-serialproxy.html>`_.
@@ -63,7 +63,7 @@
 Enabling the service is enough to be functional for a single machine DevStack.
 
 These config options are defined in `nova.conf.serial_console
-<https://github.com/openstack/nova/blob/master/nova/conf/serial_console.py>`_.
+<https://opendev.org/openstack/nova/src/master/nova/conf/serial_console.py>`_.
 
 For more information on OpenStack configuration see the `OpenStack
 Compute Service Configuration Reference
diff --git a/doc/source/guides/single-vm.rst b/doc/source/guides/single-vm.rst
index 8ebf2a6..7dac18b 100644
--- a/doc/source/guides/single-vm.rst
+++ b/doc/source/guides/single-vm.rst
@@ -78,7 +78,7 @@
 to create a non-root user and run the ``start.sh`` script as that user.
 
 If you are using cloud-init and you have not
-`enabled custom logging <../configuration.html#enable-logging>`_ of the stack
+:ref:`enabled custom logging <enable_logging>` of the stack
 output, then the stack output can be found in
 ``/var/log/cloud-init-output.log`` by default.
 
diff --git a/doc/source/plugin-registry.rst b/doc/source/plugin-registry.rst
index 1c1c5a5..5cbe4ed 100644
--- a/doc/source/plugin-registry.rst
+++ b/doc/source/plugin-registry.rst
@@ -186,7 +186,6 @@
 x/networking-vsphere                     `https://opendev.org/x/networking-vsphere <https://opendev.org/x/networking-vsphere>`__
 x/neutron-classifier                     `https://opendev.org/x/neutron-classifier <https://opendev.org/x/neutron-classifier>`__
 x/nova-dpm                               `https://opendev.org/x/nova-dpm <https://opendev.org/x/nova-dpm>`__
-x/nova-lxd                               `https://opendev.org/x/nova-lxd <https://opendev.org/x/nova-lxd>`__
 x/nova-mksproxy                          `https://opendev.org/x/nova-mksproxy <https://opendev.org/x/nova-mksproxy>`__
 x/oaktree                                `https://opendev.org/x/oaktree <https://opendev.org/x/oaktree>`__
 x/omni                                   `https://opendev.org/x/omni <https://opendev.org/x/omni>`__
diff --git a/doc/source/plugins.rst b/doc/source/plugins.rst
index 2484569..a18a786 100644
--- a/doc/source/plugins.rst
+++ b/doc/source/plugins.rst
@@ -332,6 +332,6 @@
 ========
 
 For additional inspiration on devstack plugins you can check out the
-`Plugin Registry <plugin-registry.html>`_.
+:doc:`Plugin Registry <plugin-registry>`.
 
 .. _service types authority: https://specs.openstack.org/openstack/service-types-authority/
diff --git a/doc/source/systemd.rst b/doc/source/systemd.rst
index 1bc9911..15b3f75 100644
--- a/doc/source/systemd.rst
+++ b/doc/source/systemd.rst
@@ -194,7 +194,7 @@
 
 See the `remote-pdb`_ home page for more options.
 
-.. _`remote-pdb`: https://pypi.python.org/pypi/remote-pdb
+.. _`remote-pdb`: https://pypi.org/project/remote-pdb/
 
 Known Issues
 ============
diff --git a/doc/source/zuul_ci_jobs_migration.rst b/doc/source/zuul_ci_jobs_migration.rst
index dbb7989..17e7e16 100644
--- a/doc/source/zuul_ci_jobs_migration.rst
+++ b/doc/source/zuul_ci_jobs_migration.rst
@@ -180,123 +180,147 @@
 devstack-gate defined a default value. In ansible jobs the default is either the
 value defined in the parent job, or the default from DevStack, if any.
 
-==============================================  ============= ==================
-DevStack gate flag                              Repo          New implementation
-==============================================  ============= ==================
-OVERRIDE_ZUUL_BRANCH                            zuul          override-checkout:
-                                                              [branch]
-                                                              in the job definition.
-DEVSTACK_GATE_NET_OVERLAY                       zuul-jobs     A bridge called
-                                                              br-infra is set up for
-                                                              all jobs that inherit
-                                                              from multinode with
-                                                              a dedicated `bridge role <https://docs.openstack.org/infra/zuul-jobs/roles.html#role-multi-node-bridge>`_.
-DEVSTACK_GATE_FEATURE_MATRIX                    devstack-gate ``test_matrix_features``
-                                                              variable of the
-                                                              test-matrix role in
-                                                              devstack-gate. This
-                                                              is a temporary
-                                                              solution, feature
-                                                              matrix will go away.
-                                                              In the future services
-                                                              will be defined in
-                                                              jobs only.
-DEVSTACK_CINDER_VOLUME_CLEAR                    devstack      *CINDER_VOLUME_CLEAR: true/false*
-                                                              in devstack_localrc
-                                                              in the job vars.
-DEVSTACK_GATE_NEUTRON                           devstack      True by default. To
-                                                              disable, disable all
-                                                              neutron services in
-                                                              devstack_services in
-                                                              the job definition.
-DEVSTACK_GATE_CONFIGDRIVE                       devstack      *FORCE_CONFIG_DRIVE: true/false*
-                                                              in devstack_localrc
-                                                              in the job vars.
-DEVSTACK_GATE_INSTALL_TESTONLY                  devstack      *INSTALL_TESTONLY_PACKAGES: true/false*
-                                                              in devstack_localrc
-                                                              in the job vars.
-DEVSTACK_GATE_VIRT_DRIVER                       devstack      *VIRT_DRIVER: [virt driver]*
-                                                              in devstack_localrc
-                                                              in the job vars.
-DEVSTACK_GATE_LIBVIRT_TYPE                      devstack      *LIBVIRT_TYPE: [libvirt type]*
-                                                              in devstack_localrc
-                                                              in the job vars.
-DEVSTACK_GATE_TEMPEST                           devstack      Defined by the job
-                                                tempest       that is used. The
-                                                              ``devstack`` job only
-                                                              runs devstack.
-                                                              The ``devstack-tempest``
-                                                              one triggers a Tempest
-                                                              run as well.
-DEVSTACK_GATE_TEMPEST_FULL                      tempest       *tox_envlist: full*
-                                                              in the job vars.
-DEVSTACK_GATE_TEMPEST_ALL                       tempest       *tox_envlist: all*
-                                                              in the job vars.
-DEVSTACK_GATE_TEMPEST_ALL_PLUGINS               tempest       *tox_envlist: all-plugin*
-                                                              in the job vars.
-DEVSTACK_GATE_TEMPEST_SCENARIOS                 tempest       *tox_envlist: scenario*
-                                                              in the job vars.
-TEMPEST_CONCURRENCY                             tempest       *tempest_concurrency: [value]*
-                                                              in the job vars. This
-                                                              is available only on
-                                                              jobs that inherit from
-                                                              ``devstack-tempest``
-                                                              down.
-DEVSTACK_GATE_TEMPEST_NOTESTS                   tempest       *tox_envlist: venv-tempest*
-                                                              in the job vars. This
-                                                              will create Tempest
-                                                              virtual environment
-                                                              but run no tests.
-DEVSTACK_GATE_SMOKE_SERIAL                      tempest       *tox_envlist: smoke-serial*
-                                                              in the job vars.
-DEVSTACK_GATE_TEMPEST_DISABLE_TENANT_ISOLATION  tempest       *tox_envlist: full-serial*
-                                                              in the job vars.
-                                                              *TEMPEST_ALLOW_TENANT_ISOLATION: false*
-                                                              in devstack_localrc in
-                                                              the job vars.
-==============================================  ============= ==================
+.. list-table:: **DevStack Gate Flags**
+   :widths: 20 10 60
+   :header-rows: 1
+
+   * - DevStack gate flag
+     - Repo
+     - New implementation
+   * - OVERRIDE_ZUUL_BRANCH
+     - zuul
+     - override-checkout: [branch] in the job definition.
+   * - DEVSTACK_GATE_NET_OVERLAY
+     - zuul-jobs
+     - A bridge called br-infra is set up for all jobs that inherit
+       from multinode with a dedicated `bridge role
+       <https://zuul-ci.org/docs/zuul-jobs/general-roles.html#role-multi-node-bridge>`_.
+   * - DEVSTACK_GATE_FEATURE_MATRIX
+     - devstack-gate
+     - ``test_matrix_features`` variable of the test-matrix role in
+       devstack-gate. This is a temporary solution, feature matrix
+       will go away. In the future services will be defined in jobs
+       only.
+   * - DEVSTACK_CINDER_VOLUME_CLEAR
+     - devstack
+     - *CINDER_VOLUME_CLEAR: true/false* in devstack_localrc in the
+       job vars.
+   * - DEVSTACK_GATE_NEUTRON
+     - devstack
+     - True by default. To disable, disable all neutron services in
+       devstack_services in the job definition.
+   * - DEVSTACK_GATE_CONFIGDRIVE
+     - devstack
+     - *FORCE_CONFIG_DRIVE: true/false* in devstack_localrc in the job
+       vars.
+   * - DEVSTACK_GATE_INSTALL_TESTONLY
+     - devstack
+     - *INSTALL_TESTONLY_PACKAGES: true/false* in devstack_localrc in
+       the job vars.
+   * - DEVSTACK_GATE_VIRT_DRIVER
+     - devstack
+     - *VIRT_DRIVER: [virt driver]* in devstack_localrc in the job
+       vars.
+   * - DEVSTACK_GATE_LIBVIRT_TYPE
+     - devstack
+     - *LIBVIRT_TYPE: [libvirt type]* in devstack_localrc in the job
+       vars.
+   * - DEVSTACK_GATE_TEMPEST
+     - devstack and tempest
+     - Defined by the job that is used. The ``devstack`` job only runs
+       devstack. The ``devstack-tempest`` one triggers a Tempest run
+       as well.
+   * - DEVSTACK_GATE_TEMPEST_FULL
+     - tempest
+     - *tox_envlist: full* in the job vars.
+   * - DEVSTACK_GATE_TEMPEST_ALL
+     - tempest
+     - *tox_envlist: all* in the job vars.
+   * - DEVSTACK_GATE_TEMPEST_ALL_PLUGINS
+     - tempest
+     - *tox_envlist: all-plugin* in the job vars.
+   * - DEVSTACK_GATE_TEMPEST_SCENARIOS
+     - tempest
+     - *tox_envlist: scenario* in the job vars.
+   * - TEMPEST_CONCURRENCY
+     - tempest
+     - *tempest_concurrency: [value]* in the job vars. This is
+       available only on jobs that inherit from ``devstack-tempest``
+       down.
+   * - DEVSTACK_GATE_TEMPEST_NOTESTS
+     - tempest
+     - *tox_envlist: venv-tempest* in the job vars. This will create
+       Tempest virtual environment but run no tests.
+   * - DEVSTACK_GATE_SMOKE_SERIAL
+     - tempest
+     - *tox_envlist: smoke-serial* in the job vars.
+   * - DEVSTACK_GATE_TEMPEST_DISABLE_TENANT_ISOLATION
+     - tempest
+     - *tox_envlist: full-serial* in the job vars.
+       *TEMPEST_ALLOW_TENANT_ISOLATION: false* in devstack_localrc in
+       the job vars.
+
 
 The following flags have not been migrated yet or are legacy and won't be
 migrated at all.
 
-=====================================  ======  ==========================
-DevStack gate flag                     Status  Details
-=====================================  ======  ==========================
-DEVSTACK_GATE_TOPOLOGY                 WIP     The topology depends on the base
-                                               job that is used and more
-                                               specifically on the nodeset
-                                               attached to it. The new job
-                                               format allows project to define
-                                               the variables to be passed to
-                                               every node/node-group that exists
-                                               in the topology. Named topologies
-                                               that include the nodeset and the
-                                               matching variables can be defined
-                                               in the form of base jobs.
-DEVSTACK_GATE_GRENADE                  TBD     Grenade Zuul V3 jobs will be
-                                               hosted in the grenade repo.
-GRENADE_BASE_BRANCH                    TBD     Grenade Zuul V3 jobs will be
-                                               hosted in the grenade repo.
-DEVSTACK_GATE_NEUTRON_DVR              TBD     Depends on multinode support.
-DEVSTACK_GATE_EXERCISES                TBD     Can be done on request.
-DEVSTACK_GATE_IRONIC                   TBD     This will probably be implemented
-                                               on ironic side.
-DEVSTACK_GATE_IRONIC_DRIVER            TBD     This will probably be implemented
-                                               on ironic side.
-DEVSTACK_GATE_IRONIC_BUILD_RAMDISK     TBD     This will probably be implemented
-                                               on ironic side.
-DEVSTACK_GATE_POSTGRES                 Legacy  This flag exists in d-g but the
-                                               only thing that it does is
-                                               capture postgres logs. This is
-                                               already supported by the roles in
-                                               post, so the flag is useless in
-                                               the new jobs. postgres itself can
-                                               be enabled via the
-                                               devstack_service job variable.
-DEVSTACK_GATE_ZEROMQ                   Legacy  This has no effect in d-g.
-DEVSTACK_GATE_MQ_DRIVER                Legacy  This has no effect in d-g.
-DEVSTACK_GATE_TEMPEST_STRESS_ARGS      Legacy  Stress is not in Tempest anymore.
-DEVSTACK_GATE_TEMPEST_HEAT_SLOW        Legacy  This is not used anywhere.
-DEVSTACK_GATE_CELLS                    Legacy  This has no effect in d-g.
-DEVSTACK_GATE_NOVA_API_METADATA_SPLIT  Legacy  This has no effect in d-g.
-=====================================  ======  ==========================
+.. list-table:: **Not Migrated DevStack Gate Flags**
+   :widths: 20 10 60
+   :header-rows: 1
+
+   * - DevStack gate flag
+     - Status
+     - Details
+   * - DEVSTACK_GATE_TOPOLOGY
+     - WIP
+     - The topology depends on the base job that is used and more
+       specifically on the nodeset attached to it. The new job format
+       allows project to define the variables to be passed to every
+       node/node-group that exists in the topology. Named topologies
+       that include the nodeset and the matching variables can be
+       defined in the form of base jobs.
+   * - DEVSTACK_GATE_GRENADE
+     - TBD
+     - Grenade Zuul V3 jobs will be hosted in the grenade repo.
+   * - GRENADE_BASE_BRANCH
+     - TBD
+     - Grenade Zuul V3 jobs will be hosted in the grenade repo.
+   * - DEVSTACK_GATE_NEUTRON_DVR
+     - TBD
+     - Depends on multinode support.
+   * - DEVSTACK_GATE_EXERCISES
+     - TBD
+     - Can be done on request.
+   * - DEVSTACK_GATE_IRONIC
+     - TBD
+     - This will probably be implemented on ironic side.
+   * - DEVSTACK_GATE_IRONIC_DRIVER
+     - TBD
+     - This will probably be implemented on ironic side.
+   * - DEVSTACK_GATE_IRONIC_BUILD_RAMDISK
+     - TBD
+     - This will probably be implemented on ironic side.
+   * - DEVSTACK_GATE_POSTGRES
+     - Legacy
+     - This flag exists in d-g but the only thing that it does is
+       capture postgres logs. This is already supported by the roles
+       in post, so the flag is useless in the new jobs. postgres
+       itself can be enabled via the devstack_service job variable.
+   * - DEVSTACK_GATE_ZEROMQ
+     - Legacy
+     - This has no effect in d-g.
+   * - DEVSTACK_GATE_MQ_DRIVER
+     - Legacy
+     - This has no effect in d-g.
+   * - DEVSTACK_GATE_TEMPEST_STRESS_ARGS
+     - Legacy
+     - Stress is not in Tempest anymore.
+   * - DEVSTACK_GATE_TEMPEST_HEAT_SLOW
+     - Legacy
+     - This is not used anywhere.
+   * - DEVSTACK_GATE_CELLS
+     - Legacy
+     - This has no effect in d-g.
+   * - DEVSTACK_GATE_NOVA_API_METADATA_SPLIT
+     - Legacy
+     - This has no effect in d-g.
diff --git a/functions b/functions
index 9303567..f33fd25 100644
--- a/functions
+++ b/functions
@@ -18,6 +18,7 @@
 FUNC_DIR=$(cd $(dirname "${BASH_SOURCE:-$0}") && pwd)
 source ${FUNC_DIR}/functions-common
 source ${FUNC_DIR}/inc/ini-config
+source ${FUNC_DIR}/inc/meta-config
 source ${FUNC_DIR}/inc/python
 source ${FUNC_DIR}/inc/rootwrap
 
diff --git a/lib/keystone b/lib/keystone
index 5bd552f..9ceb829 100644
--- a/lib/keystone
+++ b/lib/keystone
@@ -131,6 +131,9 @@
 # however may not be suitable for real production.
 KEYSTONE_PASSWORD_HASH_ROUNDS=${KEYSTONE_PASSWORD_HASH_ROUNDS:-4}
 
+# Cache settings
+KEYSTONE_ENABLE_CACHE=${KEYSTONE_ENABLE_CACHE:-True}
+
 # Functions
 # ---------
 
@@ -213,9 +216,9 @@
     iniset $KEYSTONE_CONF resource driver "$KEYSTONE_RESOURCE_BACKEND"
 
     # Enable caching
-    iniset $KEYSTONE_CONF cache enabled "True"
-    iniset $KEYSTONE_CONF cache backend "dogpile.cache.memcached"
-    iniset $KEYSTONE_CONF cache memcache_servers localhost:11211
+    iniset $KEYSTONE_CONF cache enabled $KEYSTONE_ENABLE_CACHE
+    iniset $KEYSTONE_CONF cache backend $CACHE_BACKEND
+    iniset $KEYSTONE_CONF cache memcache_servers $MEMCACHE_SERVERS
 
     iniset_rpc_backend keystone $KEYSTONE_CONF oslo_messaging_notifications
 
diff --git a/lib/neutron b/lib/neutron
index e1fd10c..9c05c85 100644
--- a/lib/neutron
+++ b/lib/neutron
@@ -54,6 +54,7 @@
 NEUTRON_CONF_DIR=/etc/neutron
 NEUTRON_CONF=$NEUTRON_CONF_DIR/neutron.conf
 NEUTRON_META_CONF=$NEUTRON_CONF_DIR/metadata_agent.ini
+NEUTRON_META_DATA_HOST=${NEUTRON_META_DATA_HOST:-$(ipv6_unquote $SERVICE_HOST)}
 
 NEUTRON_DHCP_CONF=$NEUTRON_CONF_DIR/dhcp_agent.ini
 NEUTRON_L3_CONF=$NEUTRON_CONF_DIR/l3_agent.ini
@@ -98,6 +99,17 @@
 PUBLIC_BRIDGE=${PUBLIC_BRIDGE:-br-ex}
 PUBLIC_BRIDGE_MTU=${PUBLIC_BRIDGE_MTU:-1500}
 
+# Network type - default vxlan, however enables vlan based jobs to override
+# using the legacy environment variable as well as a new variable in greater
+# alignment with the naming scheme of this plugin.
+NEUTRON_TENANT_NETWORK_TYPE=${NEUTRON_TENANT_NETWORK_TYPE:-vxlan}
+
+NEUTRON_TENANT_VLAN_RANGE=${NEUTRON_TENANT_VLAN_RANGE:-${TENANT_VLAN_RANGE:-100:150}}
+
+# Physical network for VLAN network usage.
+NEUTRON_PHYSICAL_NETWORK=${NEUTRON_PHYSICAL_NETWORK:-}
+
+
 # Additional neutron api config files
 declare -a -g _NEUTRON_SERVER_EXTRA_CONF_FILES_ABS
 
@@ -201,9 +213,8 @@
         configure_keystone_authtoken_middleware $NEUTRON_CONF neutron
         configure_keystone_authtoken_middleware $NEUTRON_CONF nova nova
 
-        # Configure VXLAN
-        # TODO(sc68cal) not hardcode?
-        iniset $NEUTRON_CORE_PLUGIN_CONF ml2 tenant_network_types vxlan
+        # Configure tenant network type
+        iniset $NEUTRON_CORE_PLUGIN_CONF ml2 tenant_network_types $NEUTRON_TENANT_NETWORK_TYPE
 
         local mech_drivers="openvswitch"
         if [[ "$NEUTRON_DISTRIBUTED_ROUTING" = "True" ]]; then
@@ -215,6 +226,9 @@
 
         iniset $NEUTRON_CORE_PLUGIN_CONF ml2_type_vxlan vni_ranges 1001:2000
         iniset $NEUTRON_CORE_PLUGIN_CONF ml2_type_flat flat_networks public
+        if [[ "$NEUTRON_TENANT_NETWORK_TYPE" =~ "vlan" ]] && [[ "$NEUTRON_PHYSICAL_NETWORK" != "" ]]; then
+            iniset $NEUTRON_CORE_PLUGIN_CONF ml2_type_vlan network_vlan_ranges ${NEUTRON_PHYSICAL_NETWORK}:${NEUTRON_TENANT_VLAN_RANGE}
+        fi
         if [[ "$NEUTRON_PORT_SECURITY" = "True" ]]; then
             neutron_ml2_extension_driver_add port_security
         fi
@@ -237,6 +251,7 @@
             if [[ "$NEUTRON_DISTRIBUTED_ROUTING" = "True" ]]; then
                 iniset $NEUTRON_CORE_PLUGIN_CONF agent l2_population True
                 iniset $NEUTRON_CORE_PLUGIN_CONF agent enable_distributed_routing True
+                iniset $NEUTRON_CORE_PLUGIN_CONF agent arp_responder True
             fi
         fi
 
@@ -283,7 +298,7 @@
         cp $NEUTRON_DIR/etc/metadata_agent.ini.sample $NEUTRON_META_CONF
 
         iniset $NEUTRON_META_CONF DEFAULT debug $ENABLE_DEBUG_LOG_LEVEL
-        iniset $NEUTRON_META_CONF DEFAULT nova_metadata_host $SERVICE_HOST
+        iniset $NEUTRON_META_CONF DEFAULT nova_metadata_host $NEUTRON_META_DATA_HOST
         iniset $NEUTRON_META_CONF DEFAULT metadata_workers $API_WORKERS
         # TODO(ihrachys) do we really need to set rootwrap for metadata agent?
         configure_root_helper_options $NEUTRON_META_CONF
diff --git a/lib/neutron_plugins/ml2 b/lib/neutron_plugins/ml2
index 127d46b..497b6c6 100644
--- a/lib/neutron_plugins/ml2
+++ b/lib/neutron_plugins/ml2
@@ -147,6 +147,7 @@
         populate_ml2_config /$Q_PLUGIN_CONF_FILE agent l2_population=True
         populate_ml2_config /$Q_PLUGIN_CONF_FILE agent tunnel_types=vxlan
         populate_ml2_config /$Q_PLUGIN_CONF_FILE agent enable_distributed_routing=True
+        populate_ml2_config /$Q_PLUGIN_CONF_FILE agent arp_responder=True
     fi
 }
 
diff --git a/lib/nova b/lib/nova
index f423b57..22f0706 100644
--- a/lib/nova
+++ b/lib/nova
@@ -88,9 +88,9 @@
 NOVA_SERVICE_PORT=${NOVA_SERVICE_PORT:-8774}
 NOVA_SERVICE_PORT_INT=${NOVA_SERVICE_PORT_INT:-18774}
 NOVA_SERVICE_PROTOCOL=${NOVA_SERVICE_PROTOCOL:-$SERVICE_PROTOCOL}
-NOVA_SERVICE_LOCAL_HOST=${NOVA_SERVICE_LOCAL_HOST:-$SERVICE_LOCAL_HOST}
 NOVA_SERVICE_LISTEN_ADDRESS=${NOVA_SERVICE_LISTEN_ADDRESS:-$(ipv6_unquote $SERVICE_LISTEN_ADDRESS)}
 METADATA_SERVICE_PORT=${METADATA_SERVICE_PORT:-8775}
+NOVA_ENABLE_CACHE=${NOVA_ENABLE_CACHE:-True}
 
 # Option to enable/disable config drive
 # NOTE: Set ``FORCE_CONFIG_DRIVE="False"`` to turn OFF config drive
@@ -102,7 +102,7 @@
 
 # The following NOVA_FILTERS contains SameHostFilter and DifferentHostFilter with
 # the default filters.
-NOVA_FILTERS="RetryFilter,AvailabilityZoneFilter,ComputeFilter,ComputeCapabilitiesFilter,ImagePropertiesFilter,ServerGroupAntiAffinityFilter,ServerGroupAffinityFilter,SameHostFilter,DifferentHostFilter"
+NOVA_FILTERS="AvailabilityZoneFilter,ComputeFilter,ComputeCapabilitiesFilter,ImagePropertiesFilter,ServerGroupAntiAffinityFilter,ServerGroupAffinityFilter,SameHostFilter,DifferentHostFilter"
 
 QEMU_CONF=/etc/libvirt/qemu.conf
 
@@ -399,7 +399,6 @@
     iniset $NOVA_CONF neutron default_floating_pool "$PUBLIC_NETWORK_NAME"
     if [[ $SERVICE_IP_VERSION == 6 ]]; then
         iniset $NOVA_CONF DEFAULT my_ip "$HOST_IPV6"
-        iniset $NOVA_CONF DEFAULT use_ipv6 "True"
     else
         iniset $NOVA_CONF DEFAULT my_ip "$HOST_IP"
     fi
@@ -416,8 +415,8 @@
         iniset $NOVA_CONF DEFAULT bindir "/usr/bin"
     fi
 
-    # only setup database connections if there are services that
-    # require them running on the host. The ensures that n-cpu doesn't
+    # only setup database connections and cache backend if there are services
+    # that require them running on the host. The ensures that n-cpu doesn't
     # leak a need to use the db in a multinode scenario.
     if is_service_enabled n-api n-cond n-sched; then
         # If we're in multi-tier cells mode, we want our control services pointing
@@ -434,6 +433,13 @@
 
         iniset $NOVA_CONF database connection `database_connection_url $db`
         iniset $NOVA_CONF api_database connection `database_connection_url nova_api`
+
+        # Cache related settings
+        # Those settings aren't really needed in n-cpu thus it is configured
+        # only on nodes which runs controller services
+        iniset $NOVA_CONF cache enabled $NOVA_ENABLE_CACHE
+        iniset $NOVA_CONF cache backend $CACHE_BACKEND
+        iniset $NOVA_CONF cache memcache_servers $MEMCACHE_SERVERS
     fi
 
     if is_service_enabled n-api; then
@@ -578,31 +584,47 @@
 }
 
 function configure_console_compute {
+    # If we are running multiple cells (and thus multiple console proxies) on a
+    # single host, we offset the ports to avoid collisions.  We need to
+    # correspondingly configure the console proxy port for nova-compute and we
+    # can use the NOVA_CPU_CELL variable to know which cell we are for
+    # calculating the offset.
+    # Stagger the offset based on the total number of possible console proxies
+    # (novnc, xvpvnc, spice, serial) so that their ports will not collide if
+    # all are enabled.
+    local offset
+    offset=$(((NOVA_CPU_CELL - 1) * 4))
+
+    # Use the host IP instead of the service host because for multi-node, the
+    # service host will be the controller only.
+    local default_proxyclient_addr
+    default_proxyclient_addr=$(iniget $NOVA_CPU_CONF DEFAULT my_ip)
+
     # All nova-compute workers need to know the vnc configuration options
     # These settings don't hurt anything if n-xvnc and n-novnc are disabled
     if is_service_enabled n-cpu; then
         if [ "$NOVNC_FROM_PACKAGE" == "True" ]; then
             # Use the old URL when installing novnc packages.
-            NOVNCPROXY_URL=${NOVNCPROXY_URL:-"http://$SERVICE_HOST:6080/vnc_auto.html"}
+            NOVNCPROXY_URL=${NOVNCPROXY_URL:-"http://$SERVICE_HOST:$((6080 + offset))/vnc_auto.html"}
         elif vercmp ${NOVNC_BRANCH} "<" "1.0.0"; then
-             # Use the old URL when installing older novnc source.
-            NOVNCPROXY_URL=${NOVNCPROXY_URL:-"http://$SERVICE_HOST:6080/vnc_auto.html"}
+            # Use the old URL when installing older novnc source.
+            NOVNCPROXY_URL=${NOVNCPROXY_URL:-"http://$SERVICE_HOST:$((6080 + offset))/vnc_auto.html"}
         else
             # Use the new URL when building >=v1.0.0 from source.
-            NOVNCPROXY_URL=${NOVNCPROXY_URL:-"http://$SERVICE_HOST:6080/vnc_lite.html"}
+            NOVNCPROXY_URL=${NOVNCPROXY_URL:-"http://$SERVICE_HOST:$((6080 + offset))/vnc_lite.html"}
         fi
         iniset $NOVA_CPU_CONF vnc novncproxy_base_url "$NOVNCPROXY_URL"
-        XVPVNCPROXY_URL=${XVPVNCPROXY_URL:-"http://$SERVICE_HOST:6081/console"}
+        XVPVNCPROXY_URL=${XVPVNCPROXY_URL:-"http://$SERVICE_HOST:$((6081 + offset))/console"}
         iniset $NOVA_CPU_CONF vnc xvpvncproxy_base_url "$XVPVNCPROXY_URL"
-        SPICEHTML5PROXY_URL=${SPICEHTML5PROXY_URL:-"http://$SERVICE_HOST:6082/spice_auto.html"}
+        SPICEHTML5PROXY_URL=${SPICEHTML5PROXY_URL:-"http://$SERVICE_HOST:$((6082 + offset))/spice_auto.html"}
         iniset $NOVA_CPU_CONF spice html5proxy_base_url "$SPICEHTML5PROXY_URL"
     fi
 
     if is_service_enabled n-novnc || is_service_enabled n-xvnc || [ "$NOVA_VNC_ENABLED" != False ]; then
         # Address on which instance vncservers will listen on compute hosts.
         # For multi-host, this should be the management ip of the compute host.
-        VNCSERVER_LISTEN=${VNCSERVER_LISTEN=$NOVA_SERVICE_LOCAL_HOST}
-        VNCSERVER_PROXYCLIENT_ADDRESS=${VNCSERVER_PROXYCLIENT_ADDRESS=$NOVA_SERVICE_LOCAL_HOST}
+        VNCSERVER_LISTEN=${VNCSERVER_LISTEN:-$NOVA_SERVICE_LISTEN_ADDRESS}
+        VNCSERVER_PROXYCLIENT_ADDRESS=${VNCSERVER_PROXYCLIENT_ADDRESS:-$default_proxyclient_addr}
         iniset $NOVA_CPU_CONF vnc server_listen "$VNCSERVER_LISTEN"
         iniset $NOVA_CPU_CONF vnc server_proxyclient_address "$VNCSERVER_PROXYCLIENT_ADDRESS"
     else
@@ -612,8 +634,8 @@
     if is_service_enabled n-spice; then
         # Address on which instance spiceservers will listen on compute hosts.
         # For multi-host, this should be the management ip of the compute host.
-        SPICESERVER_PROXYCLIENT_ADDRESS=${SPICESERVER_PROXYCLIENT_ADDRESS=$NOVA_SERVICE_LOCAL_HOST}
-        SPICESERVER_LISTEN=${SPICESERVER_LISTEN=$NOVA_SERVICE_LOCAL_HOST}
+        SPICESERVER_PROXYCLIENT_ADDRESS=${SPICESERVER_PROXYCLIENT_ADDRESS:-$default_proxyclient_addr}
+        SPICESERVER_LISTEN=${SPICESERVER_LISTEN:-$NOVA_SERVICE_LISTEN_ADDRESS}
         iniset $NOVA_CPU_CONF spice enabled true
         iniset $NOVA_CPU_CONF spice server_listen "$SPICESERVER_LISTEN"
         iniset $NOVA_CPU_CONF spice server_proxyclient_address "$SPICESERVER_PROXYCLIENT_ADDRESS"
@@ -621,6 +643,7 @@
 
     if is_service_enabled n-sproxy; then
         iniset $NOVA_CPU_CONF serial_console enabled True
+        iniset $NOVA_CPU_CONF serial_console base_url "ws://$SERVICE_HOST:$((6083 + offset))/"
     fi
 }
 
@@ -838,7 +861,10 @@
 
     local compute_cell_conf=$NOVA_CONF
 
+    # Bug #1802143: $NOVA_CPU_CONF is constructed by first copying $NOVA_CONF...
     cp $compute_cell_conf $NOVA_CPU_CONF
+    # ...and then adding/overriding anything explicitly set in $NOVA_CPU_CONF
+    merge_config_file $TOP_DIR/local.conf post-config '$NOVA_CPU_CONF'
 
     if [[ "${CELLSV2_SETUP}" == "singleconductor" ]]; then
         # NOTE(danms): Grenade doesn't setup multi-cell rabbit, so
diff --git a/lib/nova_plugins/hypervisor-ironic b/lib/nova_plugins/hypervisor-ironic
index 1279256..adcc278 100644
--- a/lib/nova_plugins/hypervisor-ironic
+++ b/lib/nova_plugins/hypervisor-ironic
@@ -36,7 +36,9 @@
 
 # configure_nova_hypervisor - Set config files, create data dirs, etc
 function configure_nova_hypervisor {
-    configure_libvirt
+    if ! is_ironic_hardware; then
+        configure_libvirt
+    fi
     LIBVIRT_FIREWALL_DRIVER=${LIBVIRT_FIREWALL_DRIVER:-"nova.virt.firewall.NoopFirewallDriver"}
 
     iniset $NOVA_CONF DEFAULT compute_driver ironic.IronicDriver
@@ -52,8 +54,14 @@
     iniset $NOVA_CONF ironic project_name demo
     iniset $NOVA_CONF ironic region_name $REGION_NAME
 
+    # These are used with crufty legacy ironicclient
     iniset $NOVA_CONF ironic api_max_retries 300
     iniset $NOVA_CONF ironic api_retry_interval 5
+    # These are used with shiny new openstacksdk
+    iniset $NOVA_CONF ironic connect_retries 300
+    iniset $NOVA_CONF ironic connect_retry_delay 5
+    iniset $NOVA_CONF ironic status_code_retries 300
+    iniset $NOVA_CONF ironic status_code_retry_delay 5
 }
 
 # install_nova_hypervisor() - Install external components
diff --git a/lib/tempest b/lib/tempest
index 4a192a0..96c9ced 100644
--- a/lib/tempest
+++ b/lib/tempest
@@ -130,6 +130,8 @@
     local available_flavors
     local flavors_ref
     local flavor_lines
+    local flavor_ref_size
+    local flavor_ref_alt_size
     local public_network_id
     local public_router_id
     local ssh_connect_method="floating"
@@ -233,11 +235,24 @@
             fi
             flavor_ref=${flavors[0]}
             flavor_ref_alt=$flavor_ref
+            flavor_ref_size=$(openstack flavor show --format value --column disk "${flavor_ref}")
 
             # Ensure ``flavor_ref`` and ``flavor_ref_alt`` have different values.
             # Some resize instance in tempest tests depends on this.
             for f in ${flavors[@]:1}; do
                 if [[ "$f" != "$flavor_ref" ]]; then
+                    #
+                    # NOTE(sdatko): Resize is only possible when target flavor
+                    #               is not smaller than the original one. For
+                    #               Tempest tests, in case there was a bigger
+                    #               flavor selected as default, e.g. m1.small,
+                    #               we need to perform additional check.
+                    #
+                    flavor_ref_alt_size=$(openstack flavor show --format value --column disk "${f}")
+                    if [[ "${flavor_ref_alt_size}" -lt "${flavor_ref_size}" ]]; then
+                        continue
+                    fi
+
                     flavor_ref_alt=$f
                     break
                 fi
diff --git a/lib/tls b/lib/tls
index 0032449..65ffeb9 100644
--- a/lib/tls
+++ b/lib/tls
@@ -234,6 +234,9 @@
                 # see https://bugs.python.org/issue23239
                 TLS_IP="DNS:$TLS_IP,IP:$TLS_IP"
             fi
+            if [[ -n "$HOST_IPV6" ]]; then
+                TLS_IP="$TLS_IP,IP:$HOST_IPV6"
+            fi
         fi
         make_cert $INT_CA_DIR $DEVSTACK_CERT_NAME $DEVSTACK_HOSTNAME "$TLS_IP"
 
diff --git a/roles/setup-devstack-log-dir/tasks/main.yaml b/roles/setup-devstack-log-dir/tasks/main.yaml
index b9f38df..d8e8cfe 100644
--- a/roles/setup-devstack-log-dir/tasks/main.yaml
+++ b/roles/setup-devstack-log-dir/tasks/main.yaml
@@ -2,4 +2,7 @@
   file:
     path: '{{ devstack_base_dir }}/logs'
     state: directory
+    mode: 0755
+    owner: stack
+    group: stack
   become: yes
diff --git a/roles/setup-devstack-source-dirs/README.rst b/roles/setup-devstack-source-dirs/README.rst
index 49d22c3..0aa048b 100644
--- a/roles/setup-devstack-source-dirs/README.rst
+++ b/roles/setup-devstack-source-dirs/README.rst
@@ -10,7 +10,7 @@
 
    The devstack base directory.
 
- .. zuul:rolevar:: devstack_sources_branch
-    :default: None
+.. zuul:rolevar:: devstack_sources_branch
+   :default: None
 
-    The target branch to be setup (where available).
+   The target branch to be setup (where available).
diff --git a/roles/sync-devstack-data/tasks/main.yaml b/roles/sync-devstack-data/tasks/main.yaml
index e62be87..a1d37c3 100644
--- a/roles/sync-devstack-data/tasks/main.yaml
+++ b/roles/sync-devstack-data/tasks/main.yaml
@@ -46,3 +46,14 @@
     dest: "{{ devstack_data_base_dir }}/data/"
     mode: push
   when: 'inventory_hostname in groups["subnode"]|default([])'
+
+- name: Ensure the data folder and subfolders have the correct permissions
+  become: true
+  file:
+    path: "{{ devstack_data_base_dir }}/data"
+    state: directory
+    owner: stack
+    group: stack
+    mode: 0755
+    recurse: yes
+  when: 'inventory_hostname in groups["subnode"]|default([])'
diff --git a/setup.cfg b/setup.cfg
index 825d386..4e27ad8 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -11,14 +11,5 @@
     License :: OSI Approved :: Apache Software License
     Operating System :: POSIX :: Linux
 
-[build_sphinx]
-all_files = 1
-build-dir = doc/build
-source-dir = doc/source
-warning-is-error = 1
-
-[pbr]
-warnerrors = True
-
 [wheel]
 universal = 1
diff --git a/stack.sh b/stack.sh
index b8d597e..9982c35 100755
--- a/stack.sh
+++ b/stack.sh
@@ -167,9 +167,6 @@
 # Import common functions
 source $TOP_DIR/functions
 
-# Import config functions
-source $TOP_DIR/inc/meta-config
-
 # Import 'public' stack.sh functions
 source $TOP_DIR/lib/stack
 
@@ -224,7 +221,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} =~ (xenial|artful|bionic|stretch|jessie|f28|f29|opensuse-42.3|opensuse-15.0|opensuse-tumbleweed|rhel7) ]]; then
+if [[ ! ${DISTRO} =~ (xenial|artful|bionic|stretch|jessie|f28|f29|opensuse-15.0|opensuse-15.1|opensuse-tumbleweed|rhel7) ]]; 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"
@@ -247,7 +244,7 @@
 # --------------
 
 # We're not as **root** so make sure ``sudo`` is available
-is_package_installed sudo || install_package sudo
+is_package_installed sudo || is_package_installed sudo-ldap || install_package sudo
 
 # UEC images ``/etc/sudoers`` does not have a ``#includedir``, add one
 sudo grep -q "^#includedir.*/etc/sudoers.d" /etc/sudoers ||
@@ -365,9 +362,12 @@
 
 # Create the destination directory and ensure it is writable by the user
 # and read/executable by everybody for daemons (e.g. apache run for horizon)
-sudo mkdir -p $DEST
-safe_chown -R $STACK_USER $DEST
-safe_chmod 0755 $DEST
+# If directory exists do not modify the permissions.
+if [[ ! -d $DEST ]]; then
+    sudo mkdir -p $DEST
+    safe_chown -R $STACK_USER $DEST
+    safe_chmod 0755 $DEST
+fi
 
 # Destination path for devstack logs
 if [[ -n ${LOGDIR:-} ]]; then
@@ -376,9 +376,11 @@
 
 # Destination path for service data
 DATA_DIR=${DATA_DIR:-${DEST}/data}
-sudo mkdir -p $DATA_DIR
-safe_chown -R $STACK_USER $DATA_DIR
-safe_chmod 0755 $DATA_DIR
+if [[ ! -d $DATA_DIR ]]; then
+    sudo mkdir -p $DATA_DIR
+    safe_chown -R $STACK_USER $DATA_DIR
+    safe_chmod 0755 $DATA_DIR
+fi
 
 # Configure proper hostname
 # Certain services such as rabbitmq require that the local hostname resolves
diff --git a/stackrc b/stackrc
index 2661b5f..10117f2 100644
--- a/stackrc
+++ b/stackrc
@@ -131,7 +131,7 @@
 
 # Explicitly list services not to run under Python 3. See
 # disable_python3_package to edit this variable.
-export DISABLED_PYTHON3_PACKAGES="swift"
+export DISABLED_PYTHON3_PACKAGES=""
 
 # When Python 3 is supported by an application, adding the specific
 # version of Python 3 to this variable will install the app using that
@@ -770,6 +770,10 @@
 # etcd is always required, so place it into list of pre-cached downloads
 EXTRA_CACHE_URLS+=",$ETCD_DOWNLOAD_LOCATION"
 
+# Cache settings
+CACHE_BACKEND=${CACHE_BACKEND:-"dogpile.cache.memcached"}
+MEMCACHE_SERVERS=${MEMCACHE_SERVERS:-"localhost:11211"}
+
 # Detect duplicate values in IMAGE_URLS
 for image_url in ${IMAGE_URLS//,/ }; do
     if [ $(echo "$IMAGE_URLS" | grep -o -F "$image_url" | wc -l) -gt 1 ]; then
diff --git a/tools/create-stack-user.sh b/tools/create-stack-user.sh
index c0b7ac7..919cacb 100755
--- a/tools/create-stack-user.sh
+++ b/tools/create-stack-user.sh
@@ -32,7 +32,7 @@
 source $TOP_DIR/stackrc
 
 # Give the non-root user the ability to run as **root** via ``sudo``
-is_package_installed sudo || install_package sudo
+is_package_installed sudo || is_package_installed sudo-ldap || install_package sudo
 
 [[ -z "$STACK_USER" ]] && die "STACK_USER is not set. Exiting."
 
diff --git a/tools/xen/README.md b/tools/xen/README.md
index 22263bb..2873011 100644
--- a/tools/xen/README.md
+++ b/tools/xen/README.md
@@ -1,3 +1,3 @@
 Note: XenServer relative tools have been moved to `os-xenapi`_ and be maintained there.
 
-.. _os-xenapi: https://github.com/openstack/os-xenapi/
+.. _os-xenapi: https://opendev.org/x/os-xenapi/
diff --git a/tox.ini b/tox.ini
index f643fdb..d81107f 100644
--- a/tox.ini
+++ b/tox.ini
@@ -41,7 +41,8 @@
 setenv =
   TOP_DIR={toxinidir}
 commands =
-  python setup.py build_sphinx
+  sphinx-build -W -b html -d doc/build/doctrees doc/source doc/build/html
+
 
 [testenv:venv]
 basepython = python3