Merge "Save rc from stack.sh in run-devstack role"
diff --git a/.zuul.yaml b/.zuul.yaml
index 1a81ef1..5fda6b1 100644
--- a/.zuul.yaml
+++ b/.zuul.yaml
@@ -29,6 +29,16 @@
           - controller
 
 - nodeset:
+    name: devstack-single-node-opensuse-tumbleweed
+    nodes:
+      - name: controller
+        label: opensuse-tumbleweed
+    groups:
+      - name: tempest
+        nodes:
+          - controller
+
+- nodeset:
     name: devstack-single-node-fedora-27
     nodes:
       - name: controller
@@ -354,11 +364,18 @@
 - job:
     name: devstack-platform-opensuse-423
     parent: tempest-full
-    description: OpenSuSE 43.2 platform test
+    description: openSUSE 43.2 platform test
     nodeset: devstack-single-node-opensuse-423
     voting: false
 
 - job:
+    name: devstack-platform-opensuse-tumbleweed
+    parent: tempest-full
+    description: openSUSE Tumbleweed platform test
+    nodeset: devstack-single-node-opensuse-tumbleweed
+    voting: false
+
+- job:
     name: devstack-platform-fedora-27
     parent: tempest-full
     description: Fedora 27 platform test
@@ -434,6 +451,7 @@
         - devstack
         - devstack-platform-centos-7
         - devstack-platform-opensuse-423
+        - devstack-platform-opensuse-tumbleweed
         - devstack-platform-fedora-27
         - devstack-multinode
         - devstack-unit-tests
diff --git a/clean.sh b/clean.sh
index 2333596..a29ebd9 100755
--- a/clean.sh
+++ b/clean.sh
@@ -122,9 +122,6 @@
 if [[ -n "$LOGDIR" ]] && [[ -d "$LOGDIR" ]]; then
     sudo rm -rf $LOGDIR
 fi
-if [[ -n "$SCREEN_LOGDIR" ]] && [[ -d "$SCREEN_LOGDIR" ]]; then
-    sudo rm -rf $SCREEN_LOGDIR
-fi
 
 # Clean out the sytemd user unit files if systemd was used.
 if [[ "$USE_SYSTEMD" = "True" ]]; then
diff --git a/doc/source/plugin-registry.rst b/doc/source/plugin-registry.rst
index 591e226..04b7698 100644
--- a/doc/source/plugin-registry.rst
+++ b/doc/source/plugin-registry.rst
@@ -31,12 +31,12 @@
 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>`__
+castellan-ui                           `git://git.openstack.org/openstack/castellan-ui <https://git.openstack.org/cgit/openstack/castellan-ui>`__
 ceilometer                             `git://git.openstack.org/openstack/ceilometer <https://git.openstack.org/cgit/openstack/ceilometer>`__
 ceilometer-powervm                     `git://git.openstack.org/openstack/ceilometer-powervm <https://git.openstack.org/cgit/openstack/ceilometer-powervm>`__
 cloudkitty                             `git://git.openstack.org/openstack/cloudkitty <https://git.openstack.org/cgit/openstack/cloudkitty>`__
 collectd-ceilometer-plugin             `git://git.openstack.org/openstack/collectd-ceilometer-plugin <https://git.openstack.org/cgit/openstack/collectd-ceilometer-plugin>`__
 congress                               `git://git.openstack.org/openstack/congress <https://git.openstack.org/cgit/openstack/congress>`__
-cue                                    `git://git.openstack.org/openstack/cue <https://git.openstack.org/cgit/openstack/cue>`__
 cyborg                                 `git://git.openstack.org/openstack/cyborg <https://git.openstack.org/cgit/openstack/cyborg>`__
 designate                              `git://git.openstack.org/openstack/designate <https://git.openstack.org/cgit/openstack/designate>`__
 devstack-plugin-additional-pkg-repos   `git://git.openstack.org/openstack/devstack-plugin-additional-pkg-repos <https://git.openstack.org/cgit/openstack/devstack-plugin-additional-pkg-repos>`__
@@ -71,7 +71,6 @@
 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>`__
 ironic-ui                              `git://git.openstack.org/openstack/ironic-ui <https://git.openstack.org/cgit/openstack/ironic-ui>`__
-k8s-cloud-provider                     `git://git.openstack.org/openstack/k8s-cloud-provider <https://git.openstack.org/cgit/openstack/k8s-cloud-provider>`__
 karbor                                 `git://git.openstack.org/openstack/karbor <https://git.openstack.org/cgit/openstack/karbor>`__
 karbor-dashboard                       `git://git.openstack.org/openstack/karbor-dashboard <https://git.openstack.org/cgit/openstack/karbor-dashboard>`__
 keystone                               `git://git.openstack.org/openstack/keystone <https://git.openstack.org/cgit/openstack/keystone>`__
diff --git a/functions-common b/functions-common
index df295a3..279cfcf 100644
--- a/functions-common
+++ b/functions-common
@@ -373,6 +373,9 @@
         DISTRO="f$os_RELEASE"
     elif [[ "$os_VENDOR" =~ (openSUSE) ]]; then
         DISTRO="opensuse-$os_RELEASE"
+        # Tumbleweed uses "n/a" as a codename, and the release is a datestring
+        # like 20180218, so not very useful.
+        [ "$os_CODENAME" = "n/a" ] && DISTRO="opensuse-tumbleweed"
     elif [[ "$os_VENDOR" =~ (SUSE LINUX) ]]; then
         # just use major release
         DISTRO="sle${os_RELEASE%.*}"
diff --git a/lib/rpc_backend b/lib/rpc_backend
index 44d0717..1c7c82f 100644
--- a/lib/rpc_backend
+++ b/lib/rpc_backend
@@ -52,7 +52,20 @@
     if is_service_enabled rabbit; then
         # Install rabbitmq-server
         install_package rabbitmq-server
-        if is_fedora; then
+        if is_suse; then
+            install_package rabbitmq-server-plugins
+            # the default systemd socket activation only listens on the loopback interface
+            # which causes rabbitmq to try to start its own epmd
+            sudo mkdir -p /etc/systemd/system/epmd.socket.d
+            cat <<EOF | sudo tee /etc/systemd/system/epmd.socket.d/ports.conf >/dev/null
+[Socket]
+ListenStream=
+ListenStream=[::]:4369
+EOF
+            sudo systemctl daemon-reload
+            sudo systemctl restart epmd.socket epmd.service
+        fi
+        if is_fedora || is_suse; then
             sudo systemctl enable rabbitmq-server
         fi
     fi
diff --git a/lib/swift b/lib/swift
index 1187846..6cda9c8 100644
--- a/lib/swift
+++ b/lib/swift
@@ -557,7 +557,11 @@
 
     local swift_log_dir=${SWIFT_DATA_DIR}/logs
     sudo rm -rf ${swift_log_dir}
-    sudo install -d -o ${STACK_USER} -g adm ${swift_log_dir}/hourly
+    local swift_log_group=adm
+    if is_suse; then
+        swift_log_group=root
+    fi
+    sudo install -d -o ${STACK_USER} -g ${swift_log_group} ${swift_log_dir}/hourly
 
     if [[ $SYSLOG != "False" ]]; then
         sed "s,%SWIFT_LOGDIR%,${swift_log_dir}," $FILES/swift/rsyslog.conf | sudo \
diff --git a/lib/tempest b/lib/tempest
index 3b39dae..f60b477 100644
--- a/lib/tempest
+++ b/lib/tempest
@@ -554,7 +554,10 @@
     if [[ "$OFFLINE" != "True" ]]; then
         tox -revenv-tempest --notest
     fi
-    tox -evenv-tempest -- pip install -c $REQUIREMENTS_DIR/upper-constraints.txt -r requirements.txt
+
+    # The requirements might be on a different branch, while tempest needs master requirements.
+    (cd $REQUIREMENTS_DIR && git show master:upper-constraints.txt) > u-c-m.txt
+    tox -evenv-tempest -- pip install -c u-c-m.txt -r requirements.txt
 
     # Auth:
     iniset $TEMPEST_CONFIG auth tempest_roles "Member"
diff --git a/playbooks/devstack.yaml b/playbooks/devstack.yaml
index 93d19f1..d090638 100644
--- a/playbooks/devstack.yaml
+++ b/playbooks/devstack.yaml
@@ -1,3 +1,7 @@
 - hosts: all
+  # This is the default strategy, however since orchestrate-devstack requires
+  # "linear", it is safer to enforce it in case this is running in an
+  # environment configured with a different default strategy.
+  strategy: linear
   roles:
     - orchestrate-devstack
diff --git a/roles/orchestrate-devstack/README.rst b/roles/orchestrate-devstack/README.rst
index 7803ee4..097dcea 100644
--- a/roles/orchestrate-devstack/README.rst
+++ b/roles/orchestrate-devstack/README.rst
@@ -15,6 +15,7 @@
 this role is for the controller inventory_hostname to be "controller"
 and for all sub-nodes to be defined in a group called "subnode".
 
+This role needs to be invoked from a playbook that uses a "linear" strategy.
 
 **Role Variables**
 
diff --git a/stack.sh b/stack.sh
index ba546c0..badc1a1 100755
--- a/stack.sh
+++ b/stack.sh
@@ -221,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|zesty|artful|stretch|jessie|f25|f26|f27|opensuse-42.2|opensuse-42.3|rhel7) ]]; then
+if [[ ! ${DISTRO} =~ (xenial|zesty|artful|stretch|jessie|f25|f26|f27|opensuse-42.3|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"
@@ -778,6 +778,7 @@
 
 # Do the ugly hacks for broken packages and distros
 source $TOP_DIR/tools/fixup_stuff.sh
+fixup_all
 
 if [[ "$USE_SYSTEMD" == "True" ]]; then
     pip_install_gr systemd-python
diff --git a/stackrc b/stackrc
index 5944252..e8c35f4 100644
--- a/stackrc
+++ b/stackrc
@@ -949,7 +949,6 @@
 fi
 
 # ``LOGDIR`` is always set at this point so it is not useful as a 'enable' for service logs
-# ``SCREEN_LOGDIR`` may be set, it is useful to enable the compat symlinks
 
 # System-wide ulimit file descriptors override
 ULIMIT_NOFILE=${ULIMIT_NOFILE:-2048}
diff --git a/tools/fixup_stuff.sh b/tools/fixup_stuff.sh
index f78f05f..90b2c8b 100755
--- a/tools/fixup_stuff.sh
+++ b/tools/fixup_stuff.sh
@@ -45,27 +45,29 @@
 # where Keystone will try and bind to the port and the port will already be
 # in use as an ephemeral port by another process. This places an explicit
 # exception into the Kernel for the Keystone AUTH ports.
-keystone_ports=${KEYSTONE_AUTH_PORT:-35357},${KEYSTONE_AUTH_PORT_INT:-35358}
+function fixup_keystone {
+    keystone_ports=${KEYSTONE_AUTH_PORT:-35357},${KEYSTONE_AUTH_PORT_INT:-35358}
 
-# Only do the reserved ports when available, on some system (like containers)
-# where it's not exposed we are almost pretty sure these ports would be
-# exclusive for our DevStack.
-if sysctl net.ipv4.ip_local_reserved_ports >/dev/null 2>&1; then
-    # Get any currently reserved ports, strip off leading whitespace
-    reserved_ports=$(sysctl net.ipv4.ip_local_reserved_ports | awk -F'=' '{print $2;}' | sed 's/^ //')
+    # Only do the reserved ports when available, on some system (like containers)
+    # where it's not exposed we are almost pretty sure these ports would be
+    # exclusive for our DevStack.
+    if sysctl net.ipv4.ip_local_reserved_ports >/dev/null 2>&1; then
+        # Get any currently reserved ports, strip off leading whitespace
+        reserved_ports=$(sysctl net.ipv4.ip_local_reserved_ports | awk -F'=' '{print $2;}' | sed 's/^ //')
 
-    if [[ -z "${reserved_ports}" ]]; then
-        # If there are no currently reserved ports, reserve the keystone ports
-        sudo sysctl -w net.ipv4.ip_local_reserved_ports=${keystone_ports}
+        if [[ -z "${reserved_ports}" ]]; then
+            # If there are no currently reserved ports, reserve the keystone ports
+            sudo sysctl -w net.ipv4.ip_local_reserved_ports=${keystone_ports}
+        else
+            # If there are currently reserved ports, keep those and also reserve the
+            # Keystone specific ports. Duplicate reservations are merged into a single
+            # reservation (or range) automatically by the kernel.
+            sudo sysctl -w net.ipv4.ip_local_reserved_ports=${keystone_ports},${reserved_ports}
+        fi
     else
-        # If there are currently reserved ports, keep those and also reserve the
-        # Keystone specific ports. Duplicate reservations are merged into a single
-        # reservation (or range) automatically by the kernel.
-        sudo sysctl -w net.ipv4.ip_local_reserved_ports=${keystone_ports},${reserved_ports}
+        echo_summary "WARNING: unable to reserve keystone ports"
     fi
-else
-    echo_summary "WARNING: unable to reserve keystone ports"
-fi
+}
 
 # Ubuntu Cloud Archive
 #---------------------
@@ -79,8 +81,12 @@
 # ENABLE_VOLUME_MULTIATTACH is True, we can't use the Pike UCA
 # because multiattach won't work with those package versions.
 # We can remove this check when the UCA has libvirt>=3.10.
-if [[ "${ENABLE_UBUNTU_CLOUD_ARCHIVE}" == "True" && "$DISTRO" = "xenial" && \
-        "${ENABLE_VOLUME_MULTIATTACH}" == "False" ]]; then
+function fixup_uca {
+    if [[ "${ENABLE_UBUNTU_CLOUD_ARCHIVE}" == "False" || "$DISTRO" != "xenial" || \
+            "${ENABLE_VOLUME_MULTIATTACH}" == "True" ]]; then
+        return
+    fi
+
     # This pulls in apt-add-repository
     install_package "software-properties-common"
     # Use UCA for newer libvirt. Should give us libvirt 2.5.0.
@@ -104,8 +110,7 @@
     # Force update our APT repos, since we added UCA above.
     REPOS_UPDATED=False
     apt_get_update
-fi
-
+}
 
 # Python Packages
 # ---------------
@@ -120,27 +125,32 @@
 # Pre-install affected packages so we can fix the permissions
 # These can go away once we are confident that pip 1.4.1+ is available everywhere
 
-# Fix prettytable 0.7.2 permissions
-# Don't specify --upgrade so we use the existing package if present
-pip_install 'prettytable>=0.7'
-PACKAGE_DIR=$(get_package_path prettytable)
-# Only fix version 0.7.2
-dir=$(echo $PACKAGE_DIR/prettytable-0.7.2*)
-if [[ -d $dir ]]; then
-    sudo chmod +r $dir/*
-fi
+function fixup_python_packages {
+    # Fix prettytable 0.7.2 permissions
+    # Don't specify --upgrade so we use the existing package if present
+    pip_install 'prettytable>=0.7'
+    PACKAGE_DIR=$(get_package_path prettytable)
+    # Only fix version 0.7.2
+    dir=$(echo $PACKAGE_DIR/prettytable-0.7.2*)
+    if [[ -d $dir ]]; then
+        sudo chmod +r $dir/*
+    fi
 
-# Fix httplib2 0.8 permissions
-# Don't specify --upgrade so we use the existing package if present
-pip_install httplib2
-PACKAGE_DIR=$(get_package_path httplib2)
-# Only fix version 0.8
-dir=$(echo $PACKAGE_DIR-0.8*)
-if [[ -d $dir ]]; then
-    sudo chmod +r $dir/*
-fi
+    # Fix httplib2 0.8 permissions
+    # Don't specify --upgrade so we use the existing package if present
+    pip_install httplib2
+    PACKAGE_DIR=$(get_package_path httplib2)
+    # Only fix version 0.8
+    dir=$(echo $PACKAGE_DIR-0.8*)
+    if [[ -d $dir ]]; then
+        sudo chmod +r $dir/*
+    fi
+}
 
-if is_fedora; then
+function fixup_fedora {
+    if ! is_fedora; then
+        return
+    fi
     # Disable selinux to avoid configuring to allow Apache access
     # to Horizon files (LP#1175444)
     if selinuxenabled; then
@@ -198,7 +208,7 @@
             pip_install --upgrade --force-reinstall requests
         fi
     fi
-fi
+}
 
 # The version of pip(1.5.4) supported by python-virtualenv(1.11.4) has
 # connection issues under proxy so re-install the latest version using
@@ -222,7 +232,17 @@
 #            install.d/pip-and-virtualenv-source-install/04-install-pip
 # [2] https://bugzilla.redhat.com/show_bug.cgi?id=1477823
 
-if [[ ! -f /etc/ci/mirror_info.sh ]]; then
-    install_package python-virtualenv
-    pip_install -U --force-reinstall virtualenv
-fi
+function fixup_virtualenv {
+    if [[ ! -f /etc/ci/mirror_info.sh ]]; then
+        install_package python-virtualenv
+        pip_install -U --force-reinstall virtualenv
+    fi
+}
+
+function fixup_all {
+    fixup_keystone
+    fixup_uca
+    fixup_python_packages
+    fixup_fedora
+    fixup_virtualenv
+}
diff --git a/tools/install_pip.sh b/tools/install_pip.sh
index dbe5278..1bd7392 100755
--- a/tools/install_pip.sh
+++ b/tools/install_pip.sh
@@ -129,10 +129,10 @@
 
 # Eradicate any and all system packages
 
-# Python in fedora depends on the python-pip package so removing it
+# Python in fedora/suse 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
+if ! is_fedora  && ! is_suse; then
     uninstall_package python-pip
     uninstall_package python3-pip
 fi