Merge "Revert "install LIBS_FROM_GIT using python 2 and 3 where appropriate""
diff --git a/.zuul.yaml b/.zuul.yaml
index 1b43611..f7594d4 100644
--- a/.zuul.yaml
+++ b/.zuul.yaml
@@ -52,7 +52,7 @@
     name: devstack-single-node-fedora-latest
     nodes:
       - name: controller
-        label: fedora-28
+        label: fedora-29
     groups:
       - name: tempest
         nodes:
@@ -233,6 +233,7 @@
         '{{ devstack_log_dir }}/devstacklog.txt': logs
         '{{ devstack_log_dir }}/devstacklog.txt.summary': logs
         '{{ devstack_log_dir }}/tcpdump.pcap': logs
+        '{{ devstack_log_dir }}/worlddump-latest.txt': logs
         '{{ devstack_full_log}}': logs
         '{{ stage_dir }}/verify_tempest_conf.log': logs
         '{{ stage_dir }}/apache': logs
diff --git a/doc/source/conf.py b/doc/source/conf.py
index 9059f8c..56043ba 100644
--- a/doc/source/conf.py
+++ b/doc/source/conf.py
@@ -165,7 +165,7 @@
 # Grouping the document tree into LaTeX files. List of tuples
 # (source start file, target name, title, author, documentclass [howto/manual]).
 latex_documents = [
-  ('index', 'DevStack-doc.tex', u'DevStack Docs',
+  ('index', 'doc-devstack.tex', u'DevStack Docs',
    u'OpenStack DevStack Team', 'manual'),
 ]
 
diff --git a/doc/source/index.rst b/doc/source/index.rst
index 8f95858..6694022 100644
--- a/doc/source/index.rst
+++ b/doc/source/index.rst
@@ -11,9 +11,8 @@
    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
-==========
+DevStack
+========
 
 .. image:: assets/images/logo-blue.png
 
@@ -32,7 +31,7 @@
    are dedicated to this purpose.
 
 Quick Start
-===========
++++++++++++
 
 Install Linux
 -------------
@@ -153,7 +152,7 @@
 <hacking>`.
 
 Contents
---------
+++++++++
 
 .. toctree::
    :glob:
diff --git a/files/rpms/cinder b/files/rpms/cinder
index 058c235..e6b33dc 100644
--- a/files/rpms/cinder
+++ b/files/rpms/cinder
@@ -1,5 +1,5 @@
 iscsi-initiator-utils
 lvm2
 qemu-img
-scsi-target-utils # not:rhel7,f25,f26,f27,f28 NOPRIME
-targetcli # dist:rhel7,f25,f26,f27,f28 NOPRIME
+scsi-target-utils # not:rhel7,f25,f26,f27,f28,f29 NOPRIME
+targetcli # dist:rhel7,f25,f26,f27,f28,f29 NOPRIME
diff --git a/files/rpms/dstat b/files/rpms/dstat
index 0d9da44..b058c27 100644
--- a/files/rpms/dstat
+++ b/files/rpms/dstat
@@ -1,2 +1,3 @@
-dstat
+dstat # not:f29
+pcp-system-tools # dist:f29
 python-psutil
diff --git a/files/rpms/general b/files/rpms/general
index c7863e4..5bf1e9a 100644
--- a/files/rpms/general
+++ b/files/rpms/general
@@ -9,9 +9,9 @@
 graphviz # needed only for docs
 httpd
 httpd-devel
-iptables-services  # NOPRIME f25,f26,f27,f28
+iptables-services  # NOPRIME f25,f26,f27,f28,f29
 java-1.7.0-openjdk-headless  # NOPRIME rhel7
-java-1.8.0-openjdk-headless  # NOPRIME f25,f26,f27,f28
+java-1.8.0-openjdk-headless  # NOPRIME f25,f26,f27,f28,f29
 libffi-devel
 libjpeg-turbo-devel # Pillow 3.0.0
 libxml2-devel # lxml
diff --git a/files/rpms/nova b/files/rpms/nova
index f69fc37..639d793 100644
--- a/files/rpms/nova
+++ b/files/rpms/nova
@@ -7,7 +7,7 @@
 genisoimage # required for config_drive
 iptables
 iputils
-kernel-modules # dist:f25,f26,f27,f28
+kernel-modules # dist:f25,f26,f27,f28,f29
 kpartx
 libxml2-python
 m2crypto
diff --git a/files/rpms/swift b/files/rpms/swift
index f2f5de6..be524d1 100644
--- a/files/rpms/swift
+++ b/files/rpms/swift
@@ -2,7 +2,7 @@
 liberasurecode-devel
 memcached
 pyxattr
-rsync-daemon # dist:f25,f26,f27,f28
+rsync-daemon # dist:f25,f26,f27,f28,f29
 sqlite
 xfsprogs
 xinetd
diff --git a/functions-common b/functions-common
index e234523..a13d611 100644
--- a/functions-common
+++ b/functions-common
@@ -2354,6 +2354,10 @@
 }
 
 function oscwrap {
+    local xtrace
+    xtrace=$(set +o | grep xtrace)
+    set +o xtrace
+
     local out
     local rc
     local start
@@ -2368,6 +2372,7 @@
     echo $((end - start)) >> $OSCWRAP_TIMER_FILE
 
     echo "$out"
+    $xtrace
     return $rc
 }
 
diff --git a/lib/horizon b/lib/horizon
index 293a627..b2bf7bc 100644
--- a/lib/horizon
+++ b/lib/horizon
@@ -43,8 +43,8 @@
     local value=$4
 
     if [ -z "$section" ]; then
-        sed -e "/^$option/d" -i $local_settings
-        echo -e "\n$option=$value" >> $file
+        sed -e "/^$option/d" -i $file
+        echo "$option = $value" >> $file
     elif grep -q "^$section" $file; then
         local line
         line=$(sed -ne "/^$section/,/^}/ { /^ *'$option':/ p; }" $file)
@@ -84,6 +84,9 @@
     local local_settings=$HORIZON_DIR/openstack_dashboard/local/local_settings.py
     cp $HORIZON_SETTINGS $local_settings
 
+    # Ensure local_setting.py file ends with EOL (newline)
+    echo >> $local_settings
+
     _horizon_config_set $local_settings "" WEBROOT \"$HORIZON_APACHE_ROOT/\"
 
     _horizon_config_set $local_settings "" COMPRESS_OFFLINE True
@@ -91,7 +94,6 @@
 
     _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_URI}/v3\""
 
     # note(trebskit): if HOST_IP points at non-localhost ip address, horizon cannot be accessed
diff --git a/lib/neutron_plugins/services/l3 b/lib/neutron_plugins/services/l3
index ec289f6..69536bb 100644
--- a/lib/neutron_plugins/services/l3
+++ b/lib/neutron_plugins/services/l3
@@ -395,8 +395,6 @@
 
     # 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
         # if the Linux host considers itself to be a router then it will
         # ignore all router advertisements
         # Ensure IPv6 RAs are accepted on interfaces with a default route.
@@ -409,6 +407,8 @@
             # device name would be reinterpreted as a slash, causing an error.
             sudo sysctl -w net/ipv6/conf/$d/accept_ra=2
         done
+        # 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=$(openstack --os-cloud devstack-admin --os-region "$REGION_NAME" port list -c 'Fixed IP Addresses' | grep $ipv6_pub_subnet_id | awk -F'ip_address' '{ print $2 }' | cut -f2 -d\' | tr '\n' ' ')
diff --git a/lib/nova b/lib/nova
index 22f0706..c41f881 100644
--- a/lib/nova
+++ b/lib/nova
@@ -296,6 +296,16 @@
             fi
         fi
 
+        if is_fedora && [[ $DISTRO =~ f[0-9][0-9] ]]; then
+            # There is an iscsi-initiator bug where it inserts
+            # different whitespace that causes a bunch of output
+            # matching to fail.  We have not been able to get
+            # fixed, yet :/  Exists in fedora 29 & 30 at least
+            #  https://bugzilla.redhat.com/show_bug.cgi?id=1676365
+            sudo dnf copr enable -y iwienand/iscsi-initiator-utils
+            sudo dnf update -y
+        fi
+
         if [[ ${ISCSID_DEBUG} == "True" ]]; then
             # Install an override that starts iscsid with debugging
             # enabled.
diff --git a/lib/nova_plugins/functions-libvirt b/lib/nova_plugins/functions-libvirt
index 4639869..914ee7b 100644
--- a/lib/nova_plugins/functions-libvirt
+++ b/lib/nova_plugins/functions-libvirt
@@ -150,21 +150,19 @@
     fi
 
     if is_nova_console_proxy_compute_tls_enabled ; then
-        if is_service_enabled n-novnc ; then
-            echo "vnc_tls = 1" | sudo tee -a $QEMU_CONF
-            echo "vnc_tls_x509_verify = 1" | sudo tee -a $QEMU_CONF
+        echo "vnc_tls = 1" | sudo tee -a $QEMU_CONF
+        echo "vnc_tls_x509_verify = 1" | sudo tee -a $QEMU_CONF
 
-            sudo mkdir -p /etc/pki/libvirt-vnc
-            deploy_int_CA /etc/pki/libvirt-vnc/ca-cert.pem
-            deploy_int_cert /etc/pki/libvirt-vnc/server-cert.pem /etc/pki/libvirt-vnc/server-key.pem
-            # OpenSSL 1.1.0 generates the key file with permissions: 600, by
-            # default and the deploy_int* methods use 'sudo cp' to copy the
-            # files, making them owned by root:root.
-            # Change ownership of everything under /etc/pki/libvirt-vnc to
-            # libvirt-qemu:libvirt-qemu so that libvirt-qemu can read the key
-            # file.
-            sudo chown -R libvirt-qemu:libvirt-qemu /etc/pki/libvirt-vnc
-        fi
+        sudo mkdir -p /etc/pki/libvirt-vnc
+        deploy_int_CA /etc/pki/libvirt-vnc/ca-cert.pem
+        deploy_int_cert /etc/pki/libvirt-vnc/server-cert.pem /etc/pki/libvirt-vnc/server-key.pem
+        # OpenSSL 1.1.0 generates the key file with permissions: 600, by
+        # default and the deploy_int* methods use 'sudo cp' to copy the
+        # files, making them owned by root:root.
+        # Change ownership of everything under /etc/pki/libvirt-vnc to
+        # libvirt-qemu:libvirt-qemu so that libvirt-qemu can read the key
+        # file.
+        sudo chown -R libvirt-qemu:libvirt-qemu /etc/pki/libvirt-vnc
     fi
 
     # Service needs to be started on redhat/fedora -- do a restart for
diff --git a/lib/rpc_backend b/lib/rpc_backend
index 1c7c82f..743b4ae 100644
--- a/lib/rpc_backend
+++ b/lib/rpc_backend
@@ -66,7 +66,12 @@
             sudo systemctl restart epmd.socket epmd.service
         fi
         if is_fedora || is_suse; then
-            sudo systemctl enable rabbitmq-server
+            # NOTE(jangutter): If rabbitmq is not running (as in a fresh
+            # install) then rabbit_setuser triggers epmd@0.0.0.0.socket with
+            # socket activation. This fails the first time and does not get
+            # cleared. It is benign, but the workaround is to start rabbitmq a
+            # bit earlier for RPM based distros.
+            sudo systemctl --now enable rabbitmq-server
         fi
     fi
 }
diff --git a/playbooks/pre.yaml b/playbooks/pre.yaml
index 4689a63..60f365a 100644
--- a/playbooks/pre.yaml
+++ b/playbooks/pre.yaml
@@ -1,5 +1,12 @@
 - hosts: all
   pre_tasks:
+    - name: Fix the permissions of the zuul home directory
+      # Make sure that the zuul home can be traversed,
+      # so that all users can access the sources placed there.
+      # Some distributions create it with 700 by default.
+      file:
+        path: "{{ ansible_user_dir }}"
+        mode: a+x
     - name: Gather minimum local MTU
       set_fact:
         local_mtu: >
diff --git a/samples/local.sh b/samples/local.sh
index 9cd0bdc..a1c5c81 100755
--- a/samples/local.sh
+++ b/samples/local.sh
@@ -41,6 +41,13 @@
         fi
     done
 
+    # Update security default group
+    # -----------------------------
+
+    # Add tcp/22 and icmp to default security group
+    default=$(openstack security group list -f value -c ID)
+    openstack security group rule create $default --protocol tcp --dst-port 22
+    openstack security group rule create $default --protocol icmp
 
     # Create A Flavor
     # ---------------
@@ -57,12 +64,4 @@
         openstack flavor create $MI_NAME --id 6 --ram 128 --disk 0 --vcpus 1
     fi
 
-
-    # Other Uses
-    # ----------
-
-    # Add tcp/22 and icmp to default security group
-    openstack security group rule create --project $OS_PROJECT_NAME default --protocol tcp --ingress --dst-port 22
-    openstack security group rule create --project $OS_PROJECT_NAME default --protocol icmp
-
 fi
diff --git a/stack.sh b/stack.sh
index 9982c35..b7b37e2 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|artful|bionic|stretch|jessie|f28|f29|opensuse-15.0|opensuse-15.1|opensuse-tumbleweed|rhel7) ]]; then
+if [[ ! ${DISTRO} =~ (xenial|artful|bionic|stretch|jessie|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"
@@ -796,9 +796,6 @@
     PYPI_ALTERNATIVE_URL=${PYPI_ALTERNATIVE_URL:-""} $TOP_DIR/tools/install_pip.sh
 fi
 
-# Install subunit for the subunit output stream
-pip_install -U os-testr
-
 TRACK_DEPENDS=${TRACK_DEPENDS:-False}
 
 # Install Python packages into a virtualenv so that we can track them
@@ -816,6 +813,9 @@
 source $TOP_DIR/tools/fixup_stuff.sh
 fixup_all
 
+# Install subunit for the subunit output stream
+pip_install -U os-testr
+
 if [[ "$USE_SYSTEMD" == "True" ]]; then
     pip_install_gr systemd-python
     # the default rate limit of 1000 messages / 30 seconds is not
@@ -1472,7 +1472,10 @@
 # ===============
 
 # Prepare bash completion for OSC
-openstack complete | sudo tee /etc/bash_completion.d/osc.bash_completion > /dev/null
+# Note we use "command" to avoid the timing wrapper
+# which isn't relevant here and floods logs
+command openstack complete \
+    | sudo tee /etc/bash_completion.d/osc.bash_completion > /dev/null
 
 # If cinder is configured, set global_filter for PV devices
 if is_service_enabled cinder; then
diff --git a/stackrc b/stackrc
index 10117f2..3fcdadf 100644
--- a/stackrc
+++ b/stackrc
@@ -258,7 +258,7 @@
 # Setting the variable to 'ALL' will activate the download for all
 # libraries.
 
-DEVSTACK_SERIES="train"
+DEVSTACK_SERIES="ussuri"
 
 ##############
 #
@@ -499,7 +499,7 @@
 
 # pbr drives the setuptools configs
 GITREPO["pbr"]=${PBR_REPO:-${GIT_BASE}/openstack/pbr.git}
-GITBRANCH["pbr"]=${PBR_BRANCH:-$TARGET_BRANCH}
+GITBRANCH["pbr"]=${PBR_BRANCH:-$BRANCHLESS_TARGET_BRANCH}
 
 
 ##################
@@ -554,7 +554,7 @@
 
 # diskimage-builder tool
 GITREPO["diskimage-builder"]=${DIB_REPO:-${GIT_BASE}/openstack/diskimage-builder.git}
-GITBRANCH["diskimage-builder"]=${DIB_BRANCH:-$TARGET_BRANCH}
+GITBRANCH["diskimage-builder"]=${DIB_BRANCH:-$BRANCHLESS_TARGET_BRANCH}
 GITDIR["diskimage-builder"]=$DEST/diskimage-builder
 
 # neutron-lib library containing neutron stable non-REST interfaces
diff --git a/tools/fixup_stuff.sh b/tools/fixup_stuff.sh
index 037928f..d298937 100755
--- a/tools/fixup_stuff.sh
+++ b/tools/fixup_stuff.sh
@@ -230,12 +230,24 @@
         return
     fi
 
-    # Disable apparmor profiles in openSUSE distros
-    # to avoid issues with haproxy and dnsmasq
-    if [ -x /usr/sbin/aa-enabled ] && sudo /usr/sbin/aa-enabled -q; then
-        sudo systemctl disable apparmor
+    # Deactivate and disable apparmor profiles in openSUSE and SLE
+    # distros to avoid issues with haproxy and dnsmasq.  In newer
+    # releases, systemctl stop apparmor is actually a no-op, so we
+    # have to use aa-teardown to make sure we've deactivated the
+    # profiles:
+    #
+    # https://www.suse.com/releasenotes/x86_64/SUSE-SLES/15/#fate-325343
+    # https://gitlab.com/apparmor/apparmor/merge_requests/81
+    # https://build.opensuse.org/package/view_file/openSUSE:Leap:15.2/apparmor/apparmor.service?expand=1
+    if sudo systemctl is-active -q apparmor; then
+        sudo systemctl stop apparmor
+    fi
+    if [ -x /usr/sbin/aa-teardown ]; then
         sudo /usr/sbin/aa-teardown
     fi
+    if sudo systemctl is-enabled -q apparmor; then
+        sudo systemctl disable apparmor
+    fi
 
     # Since pip10, pip will refuse to uninstall files from packages
     # that were created with distutils (rather than more modern
@@ -244,6 +256,7 @@
     # overwriting works.  So this hacks around those packages that
     # have been dragged in by some other system dependency
     sudo rm -rf /usr/lib/python3.6/site-packages/ply-*.egg-info
+    sudo rm -rf /usr/lib/python3.6/site-packages/six-*.egg-info
 }
 
 # The version of pip(1.5.4) supported by python-virtualenv(1.11.4) has
diff --git a/tools/generate-devstack-plugins-list.py b/tools/generate-devstack-plugins-list.py
index 11062ea..d39b801 100644
--- a/tools/generate-devstack-plugins-list.py
+++ b/tools/generate-devstack-plugins-list.py
@@ -28,6 +28,9 @@
 import json
 import requests
 
+from requests.adapters import HTTPAdapter
+from requests.packages.urllib3.util.retry import Retry
+
 logging.basicConfig(level=logging.DEBUG)
 
 url = 'https://review.opendev.org/projects/'
@@ -63,6 +66,12 @@
 logging.debug("Found %d projects" % len(projects))
 
 s = requests.Session()
+# sometimes gitea gives us a 500 error; retry sanely
+#  https://stackoverflow.com/a/35636367
+retries = Retry(total=3, backoff_factor=1,
+                status_forcelist=[ 500 ])
+s.mount('https://', HTTPAdapter(max_retries=retries))
+
 found_plugins = filter(functools.partial(has_devstack_plugin, s), projects)
 
 for project in found_plugins:
diff --git a/tools/worlddump.py b/tools/worlddump.py
index 88af19d..d1453ca 100755
--- a/tools/worlddump.py
+++ b/tools/worlddump.py
@@ -25,6 +25,7 @@
 import fnmatch
 import os
 import os.path
+import shutil
 import subprocess
 import sys
 
@@ -248,6 +249,14 @@
         compute_consoles()
         guru_meditation_reports()
         var_core()
+    # Singular name for ease of log retrieval
+    copyname = os.path.join(opts.dir, 'worlddump')
+    if opts.name:
+        copyname += '-' + opts.name
+    copyname += '-latest.txt'
+    # We make a full copy to deal with jobs that may or may not
+    # gzip logs breaking symlinks.
+    shutil.copyfile(fname, copyname)
 
 
 if __name__ == '__main__':
diff --git a/tox.ini b/tox.ini
index d81107f..26baa2a 100644
--- a/tox.ini
+++ b/tox.ini
@@ -43,6 +43,14 @@
 commands =
   sphinx-build -W -b html -d doc/build/doctrees doc/source doc/build/html
 
+[testenv:pdf-docs]
+basepython = python3
+deps = {[testenv:docs]deps}
+whitelist_externals =
+   make
+commands =
+   sphinx-build -W -b latex doc/source doc/build/pdf
+   make -C doc/build/pdf
 
 [testenv:venv]
 basepython = python3