Merge "Skip test_show_host volume test"
diff --git a/.zuul.yaml b/.zuul.yaml
new file mode 100644
index 0000000..313ce49
--- /dev/null
+++ b/.zuul.yaml
@@ -0,0 +1,80 @@
+- job:
+    name: patrole-dsvm-base
+    parent: legacy-dsvm-base
+    timeout: 7800
+    irrelevant-files:
+      - ^(test-|)requirements.txt$
+      - ^.*\.rst$
+      - ^doc/.*
+      - ^patrole/patrole_tempest_plugin/tests/unit/.*$
+      - ^releasenotes/.*
+      - ^setup.cfg$
+    required-projects:
+      - openstack-infra/devstack-gate
+      - openstack/patrole
+      - openstack/tempest
+
+- job:
+    name: patrole-dsvm-base-multinode
+    parent: legacy-dsvm-base-multinode
+    timeout: 7800
+    irrelevant-files:
+      - ^(test-|)requirements.txt$
+      - ^.*\.rst$
+      - ^doc/.*
+      - ^patrole/patrole_tempest_plugin/tests/unit/.*$
+      - ^releasenotes/.*
+      - ^setup.cfg$
+    required-projects:
+      - openstack-infra/devstack-gate
+      - openstack/patrole
+      - openstack/tempest
+
+- job:
+    name: tempest-dsvm-patrole-admin
+    parent: patrole-dsvm-base
+    run: playbooks/legacy/tempest-dsvm-patrole-admin/run.yaml
+    post-run: playbooks/legacy/tempest-dsvm-patrole-admin/post.yaml
+
+- job:
+    name: tempest-dsvm-patrole-member
+    parent: patrole-dsvm-base
+    run: playbooks/legacy/tempest-dsvm-patrole-member/run.yaml
+    post-run: playbooks/legacy/tempest-dsvm-patrole-member/post.yaml
+
+- job:
+    name: tempest-dsvm-patrole-multinode-admin
+    parent: patrole-dsvm-base-multinode
+    run: playbooks/legacy/tempest-dsvm-patrole-multinode-admin/run.yaml
+    post-run: playbooks/legacy/tempest-dsvm-patrole-multinode-admin/post.yaml
+    voting: false
+    nodeset: legacy-ubuntu-xenial-2-node
+
+- job:
+    name: tempest-dsvm-patrole-multinode-member
+    parent: patrole-dsvm-base-multinode
+    run: playbooks/legacy/tempest-dsvm-patrole-multinode-member/run.yaml
+    post-run: playbooks/legacy/tempest-dsvm-patrole-multinode-member/post.yaml
+    voting: false
+    nodeset: legacy-ubuntu-xenial-2-node
+
+- job:
+    name: tempest-dsvm-patrole-py35-member
+    parent: patrole-dsvm-base
+    run: playbooks/legacy/tempest-dsvm-patrole-py35-member/run.yaml
+    post-run: playbooks/legacy/tempest-dsvm-patrole-py35-member/post.yaml
+
+- project:
+    name: openstack/patrole
+    check:
+      jobs:
+        - tempest-dsvm-patrole-admin
+        - tempest-dsvm-patrole-member
+        - tempest-dsvm-patrole-py35-member
+        - tempest-dsvm-patrole-multinode-admin
+        - tempest-dsvm-patrole-multinode-member
+    gate:
+      jobs:
+        - tempest-dsvm-patrole-admin
+        - tempest-dsvm-patrole-member
+        - tempest-dsvm-patrole-py35-member
diff --git a/devstack/plugin.sh b/devstack/plugin.sh
index 1066136..1f666f2 100644
--- a/devstack/plugin.sh
+++ b/devstack/plugin.sh
@@ -20,7 +20,6 @@
 
         iniset $TEMPEST_CONFIG rbac enable_rbac True
         iniset $TEMPEST_CONFIG rbac rbac_test_role $RBAC_TEST_ROLE
-        iniset $TEMPEST_CONFIG rbac strict_policy_check False
     fi
 }
 
diff --git a/patrole_tempest_plugin/config.py b/patrole_tempest_plugin/config.py
index d309d60..7966247 100644
--- a/patrole_tempest_plugin/config.py
+++ b/patrole_tempest_plugin/config.py
@@ -30,8 +30,12 @@
                 deprecated_group='rbac',
                 help="Enables RBAC tests."),
     cfg.BoolOpt('strict_policy_check',
-                default=False,
+                default=True,
                 deprecated_group='rbac',
+                deprecated_for_removal=True,
+                deprecated_reason="""This option allows for the possibility
+of false positives. As a testing framework, Patrole should fail any test that
+passes in an invalid policy.""",
                 help="""If true, throws RbacParsingException for policies which
 don't exist or are not included in the service's policy file. If false, throws
 skipException."""),
diff --git a/patrole_tempest_plugin/tests/api/network/test_routers_rbac.py b/patrole_tempest_plugin/tests/api/network/test_routers_rbac.py
index c3ed9e1..fff2ada 100644
--- a/patrole_tempest_plugin/tests/api/network/test_routers_rbac.py
+++ b/patrole_tempest_plugin/tests/api/network/test_routers_rbac.py
@@ -176,6 +176,27 @@
             raise rbac_exceptions.RbacMalformedResponse(
                 attribute='distributed')
 
+    @decorators.idempotent_id('defc502c-4159-4824-b4d9-3cdcc39015b2')
+    @utils.requires_ext(extension='l3-ha', service='network')
+    @rbac_rule_validation.action(service="neutron",
+                                 rule="get_router:ha")
+    def test_show_high_availability_router(self):
+        """GET high-availability router
+
+        RBAC test for the neutron get_router:ha policy
+        """
+        router = self.routers_client.create_router(ha=True)['router']
+        self.addCleanup(self.routers_client.delete_router, router['id'])
+
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        retrieved_fields = self.routers_client.show_router(
+            router['id'], fields=['ha'])['router']
+
+        # Rather than throwing a 403, the field is not present, so raise exc.
+        if 'ha' not in retrieved_fields:
+            raise rbac_exceptions.RbacMalformedResponse(
+                attribute='ha')
+
     @rbac_rule_validation.action(
         service="neutron", rule="update_router")
     @decorators.idempotent_id('3d182f4e-0023-4218-9aa0-ea2b0ae0bd7a')
diff --git a/patrole_tempest_plugin/tests/api/volume/test_groups_rbac.py b/patrole_tempest_plugin/tests/api/volume/test_groups_rbac.py
index 7cc089a..236e927 100644
--- a/patrole_tempest_plugin/tests/api/volume/test_groups_rbac.py
+++ b/patrole_tempest_plugin/tests/api/volume/test_groups_rbac.py
@@ -146,7 +146,21 @@
         service="cinder",
         rule="group:group_types_manage")
     def test_delete_group_type(self):
-        goup_type = self.create_group_type(ignore_notfound=True)
+        group_type = self.create_group_type(ignore_notfound=True)
 
         self.rbac_utils.switch_role(self, toggle_rbac_role=True)
-        self.group_types_client.delete_group_type(goup_type['id'])
+        self.group_types_client.delete_group_type(group_type['id'])
+
+    @decorators.idempotent_id('8d9e2831-24c3-47b7-a76a-2e563287f12f')
+    @rbac_rule_validation.action(
+        service="cinder",
+        rule="group:access_group_types_specs")
+    def test_show_group_type(self):
+        group_type = self.create_group_type()
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        resp_body = \
+            self.group_types_client.show_group_type(
+                group_type['id'])['group_type']
+        if 'group_specs' not in resp_body:
+            raise rbac_exceptions.RbacMalformedResponse(
+                attribute='group_specs')
diff --git a/playbooks/legacy/tempest-dsvm-patrole-admin/post.yaml b/playbooks/legacy/tempest-dsvm-patrole-admin/post.yaml
new file mode 100644
index 0000000..dac8753
--- /dev/null
+++ b/playbooks/legacy/tempest-dsvm-patrole-admin/post.yaml
@@ -0,0 +1,80 @@
+- hosts: primary
+  tasks:
+
+    - name: Copy files from {{ ansible_user_dir }}/workspace/ on node
+      synchronize:
+        src: '{{ ansible_user_dir }}/workspace/'
+        dest: '{{ zuul.executor.log_root }}'
+        mode: pull
+        copy_links: true
+        verify_host: true
+        rsync_opts:
+          - --include=**/*nose_results.html
+          - --include=*/
+          - --exclude=*
+          - --prune-empty-dirs
+
+    - name: Copy files from {{ ansible_user_dir }}/workspace/ on node
+      synchronize:
+        src: '{{ ansible_user_dir }}/workspace/'
+        dest: '{{ zuul.executor.log_root }}'
+        mode: pull
+        copy_links: true
+        verify_host: true
+        rsync_opts:
+          - --include=**/*testr_results.html.gz
+          - --include=*/
+          - --exclude=*
+          - --prune-empty-dirs
+
+    - name: Copy files from {{ ansible_user_dir }}/workspace/ on node
+      synchronize:
+        src: '{{ ansible_user_dir }}/workspace/'
+        dest: '{{ zuul.executor.log_root }}'
+        mode: pull
+        copy_links: true
+        verify_host: true
+        rsync_opts:
+          - --include=/.testrepository/tmp*
+          - --include=*/
+          - --exclude=*
+          - --prune-empty-dirs
+
+    - name: Copy files from {{ ansible_user_dir }}/workspace/ on node
+      synchronize:
+        src: '{{ ansible_user_dir }}/workspace/'
+        dest: '{{ zuul.executor.log_root }}'
+        mode: pull
+        copy_links: true
+        verify_host: true
+        rsync_opts:
+          - --include=**/*testrepository.subunit.gz
+          - --include=*/
+          - --exclude=*
+          - --prune-empty-dirs
+
+    - name: Copy files from {{ ansible_user_dir }}/workspace/ on node
+      synchronize:
+        src: '{{ ansible_user_dir }}/workspace/'
+        dest: '{{ zuul.executor.log_root }}/tox'
+        mode: pull
+        copy_links: true
+        verify_host: true
+        rsync_opts:
+          - --include=/.tox/*/log/*
+          - --include=*/
+          - --exclude=*
+          - --prune-empty-dirs
+
+    - name: Copy files from {{ ansible_user_dir }}/workspace/ on node
+      synchronize:
+        src: '{{ ansible_user_dir }}/workspace/'
+        dest: '{{ zuul.executor.log_root }}'
+        mode: pull
+        copy_links: true
+        verify_host: true
+        rsync_opts:
+          - --include=/logs/**
+          - --include=*/
+          - --exclude=*
+          - --prune-empty-dirs
diff --git a/playbooks/legacy/tempest-dsvm-patrole-admin/run.yaml b/playbooks/legacy/tempest-dsvm-patrole-admin/run.yaml
new file mode 100644
index 0000000..57f208d
--- /dev/null
+++ b/playbooks/legacy/tempest-dsvm-patrole-admin/run.yaml
@@ -0,0 +1,60 @@
+- hosts: all
+  name: Autoconverted job legacy-tempest-dsvm-patrole-admin from old job gate-tempest-dsvm-patrole-admin-ubuntu-xenial
+  tasks:
+
+    - name: Ensure legacy workspace directory
+      file:
+        path: '{{ ansible_user_dir }}/workspace'
+        state: directory
+
+    - shell:
+        cmd: |
+          set -e
+          set -x
+          cat > clonemap.yaml << EOF
+          clonemap:
+            - name: openstack-infra/devstack-gate
+              dest: devstack-gate
+          EOF
+          /usr/zuul-env/bin/zuul-cloner -m clonemap.yaml --cache-dir /opt/git \
+              git://git.openstack.org \
+              openstack-infra/devstack-gate
+        executable: /bin/bash
+        chdir: '{{ ansible_user_dir }}/workspace'
+      environment: '{{ zuul | zuul_legacy_vars }}'
+
+    - shell:
+        cmd: |
+          set -e
+          set -x
+          cat << 'EOF' >>"/tmp/dg-local.conf"
+          [[local|localrc]]
+          enable_plugin patrole git://git.openstack.org/openstack/patrole
+          TEMPEST_PLUGINS='/opt/stack/new/patrole'
+          # Needed by Patrole devstack plugin
+          RBAC_TEST_ROLE=admin
+          EOF
+        executable: /bin/bash
+        chdir: '{{ ansible_user_dir }}/workspace'
+      environment: '{{ zuul | zuul_legacy_vars }}'
+
+    - shell:
+        cmd: |
+          set -e
+          set -x
+          export PYTHONUNBUFFERED=true
+          export DEVSTACK_GATE_TEMPEST=1
+          export DEVSTACK_GATE_NEUTRON=1
+          export DEVSTACK_GATE_TEMPEST_REGEX='(?!.*\[.*\bslow\b.*\])(^patrole_tempest_plugin\.tests\.api)'
+          export DEVSTACK_GATE_TEMPEST_ALL_PLUGINS=1
+          export TEMPEST_CONCURRENCY=2
+          export PROJECTS="openstack/patrole $PROJECTS"
+          export BRANCH_OVERRIDE=default
+          if [ "$BRANCH_OVERRIDE" != "default" ] ; then
+              export OVERRIDE_ZUUL_BRANCH=$BRANCH_OVERRIDE
+          fi
+          cp devstack-gate/devstack-vm-gate-wrap.sh ./safe-devstack-vm-gate-wrap.sh
+          ./safe-devstack-vm-gate-wrap.sh
+        executable: /bin/bash
+        chdir: '{{ ansible_user_dir }}/workspace'
+      environment: '{{ zuul | zuul_legacy_vars }}'
diff --git a/playbooks/legacy/tempest-dsvm-patrole-member/post.yaml b/playbooks/legacy/tempest-dsvm-patrole-member/post.yaml
new file mode 100644
index 0000000..dac8753
--- /dev/null
+++ b/playbooks/legacy/tempest-dsvm-patrole-member/post.yaml
@@ -0,0 +1,80 @@
+- hosts: primary
+  tasks:
+
+    - name: Copy files from {{ ansible_user_dir }}/workspace/ on node
+      synchronize:
+        src: '{{ ansible_user_dir }}/workspace/'
+        dest: '{{ zuul.executor.log_root }}'
+        mode: pull
+        copy_links: true
+        verify_host: true
+        rsync_opts:
+          - --include=**/*nose_results.html
+          - --include=*/
+          - --exclude=*
+          - --prune-empty-dirs
+
+    - name: Copy files from {{ ansible_user_dir }}/workspace/ on node
+      synchronize:
+        src: '{{ ansible_user_dir }}/workspace/'
+        dest: '{{ zuul.executor.log_root }}'
+        mode: pull
+        copy_links: true
+        verify_host: true
+        rsync_opts:
+          - --include=**/*testr_results.html.gz
+          - --include=*/
+          - --exclude=*
+          - --prune-empty-dirs
+
+    - name: Copy files from {{ ansible_user_dir }}/workspace/ on node
+      synchronize:
+        src: '{{ ansible_user_dir }}/workspace/'
+        dest: '{{ zuul.executor.log_root }}'
+        mode: pull
+        copy_links: true
+        verify_host: true
+        rsync_opts:
+          - --include=/.testrepository/tmp*
+          - --include=*/
+          - --exclude=*
+          - --prune-empty-dirs
+
+    - name: Copy files from {{ ansible_user_dir }}/workspace/ on node
+      synchronize:
+        src: '{{ ansible_user_dir }}/workspace/'
+        dest: '{{ zuul.executor.log_root }}'
+        mode: pull
+        copy_links: true
+        verify_host: true
+        rsync_opts:
+          - --include=**/*testrepository.subunit.gz
+          - --include=*/
+          - --exclude=*
+          - --prune-empty-dirs
+
+    - name: Copy files from {{ ansible_user_dir }}/workspace/ on node
+      synchronize:
+        src: '{{ ansible_user_dir }}/workspace/'
+        dest: '{{ zuul.executor.log_root }}/tox'
+        mode: pull
+        copy_links: true
+        verify_host: true
+        rsync_opts:
+          - --include=/.tox/*/log/*
+          - --include=*/
+          - --exclude=*
+          - --prune-empty-dirs
+
+    - name: Copy files from {{ ansible_user_dir }}/workspace/ on node
+      synchronize:
+        src: '{{ ansible_user_dir }}/workspace/'
+        dest: '{{ zuul.executor.log_root }}'
+        mode: pull
+        copy_links: true
+        verify_host: true
+        rsync_opts:
+          - --include=/logs/**
+          - --include=*/
+          - --exclude=*
+          - --prune-empty-dirs
diff --git a/playbooks/legacy/tempest-dsvm-patrole-member/run.yaml b/playbooks/legacy/tempest-dsvm-patrole-member/run.yaml
new file mode 100644
index 0000000..b95467f
--- /dev/null
+++ b/playbooks/legacy/tempest-dsvm-patrole-member/run.yaml
@@ -0,0 +1,61 @@
+- hosts: all
+  name: Autoconverted job legacy-tempest-dsvm-patrole-member from old job gate-tempest-dsvm-patrole-member-ubuntu-xenial
+  tasks:
+
+    - name: Ensure legacy workspace directory
+      file:
+        path: '{{ ansible_user_dir }}/workspace'
+        state: directory
+
+    - shell:
+        cmd: |
+          set -e
+          set -x
+          cat > clonemap.yaml << EOF
+          clonemap:
+            - name: openstack-infra/devstack-gate
+              dest: devstack-gate
+          EOF
+          /usr/zuul-env/bin/zuul-cloner -m clonemap.yaml --cache-dir /opt/git \
+              git://git.openstack.org \
+              openstack-infra/devstack-gate
+        executable: /bin/bash
+        chdir: '{{ ansible_user_dir }}/workspace'
+      environment: '{{ zuul | zuul_legacy_vars }}'
+
+    - shell:
+        cmd: |
+          set -e
+          set -x
+          cat << 'EOF' >>"/tmp/dg-local.conf"
+          [[local|localrc]]
+          enable_plugin patrole git://git.openstack.org/openstack/patrole
+          TEMPEST_PLUGINS='/opt/stack/new/patrole'
+          # Needed by Patrole devstack plugin
+          RBAC_TEST_ROLE=member
+          EOF
+        executable: /bin/bash
+        chdir: '{{ ansible_user_dir }}/workspace'
+      environment: '{{ zuul | zuul_legacy_vars }}'
+
+    - shell:
+        cmd: |
+          set -e
+          set -x
+          export PYTHONUNBUFFERED=true
+          export DEVSTACK_GATE_TEMPEST=1
+          export DEVSTACK_GATE_NEUTRON=1
+          export DEVSTACK_GATE_TEMPEST_REGEX='(?!.*\[.*\bslow\b.*\])(^patrole_tempest_plugin\.tests\.api)'
+          export DEVSTACK_GATE_TEMPEST_ALL_PLUGINS=1
+          export TEMPEST_CONCURRENCY=2
+          export PROJECTS="openstack/patrole $PROJECTS"
+          export BRANCH_OVERRIDE=default
+          if [ "$BRANCH_OVERRIDE" != "default" ] ; then
+              export OVERRIDE_ZUUL_BRANCH=$BRANCH_OVERRIDE
+          fi
+          cp devstack-gate/devstack-vm-gate-wrap.sh ./safe-devstack-vm-gate-wrap.sh
+          ./safe-devstack-vm-gate-wrap.sh
+        executable: /bin/bash
+        chdir: '{{ ansible_user_dir }}/workspace'
+      environment: '{{ zuul | zuul_legacy_vars }}'
+
diff --git a/playbooks/legacy/tempest-dsvm-patrole-multinode-admin/post.yaml b/playbooks/legacy/tempest-dsvm-patrole-multinode-admin/post.yaml
new file mode 100644
index 0000000..dac8753
--- /dev/null
+++ b/playbooks/legacy/tempest-dsvm-patrole-multinode-admin/post.yaml
@@ -0,0 +1,80 @@
+- hosts: primary
+  tasks:
+
+    - name: Copy files from {{ ansible_user_dir }}/workspace/ on node
+      synchronize:
+        src: '{{ ansible_user_dir }}/workspace/'
+        dest: '{{ zuul.executor.log_root }}'
+        mode: pull
+        copy_links: true
+        verify_host: true
+        rsync_opts:
+          - --include=**/*nose_results.html
+          - --include=*/
+          - --exclude=*
+          - --prune-empty-dirs
+
+    - name: Copy files from {{ ansible_user_dir }}/workspace/ on node
+      synchronize:
+        src: '{{ ansible_user_dir }}/workspace/'
+        dest: '{{ zuul.executor.log_root }}'
+        mode: pull
+        copy_links: true
+        verify_host: true
+        rsync_opts:
+          - --include=**/*testr_results.html.gz
+          - --include=*/
+          - --exclude=*
+          - --prune-empty-dirs
+
+    - name: Copy files from {{ ansible_user_dir }}/workspace/ on node
+      synchronize:
+        src: '{{ ansible_user_dir }}/workspace/'
+        dest: '{{ zuul.executor.log_root }}'
+        mode: pull
+        copy_links: true
+        verify_host: true
+        rsync_opts:
+          - --include=/.testrepository/tmp*
+          - --include=*/
+          - --exclude=*
+          - --prune-empty-dirs
+
+    - name: Copy files from {{ ansible_user_dir }}/workspace/ on node
+      synchronize:
+        src: '{{ ansible_user_dir }}/workspace/'
+        dest: '{{ zuul.executor.log_root }}'
+        mode: pull
+        copy_links: true
+        verify_host: true
+        rsync_opts:
+          - --include=**/*testrepository.subunit.gz
+          - --include=*/
+          - --exclude=*
+          - --prune-empty-dirs
+
+    - name: Copy files from {{ ansible_user_dir }}/workspace/ on node
+      synchronize:
+        src: '{{ ansible_user_dir }}/workspace/'
+        dest: '{{ zuul.executor.log_root }}/tox'
+        mode: pull
+        copy_links: true
+        verify_host: true
+        rsync_opts:
+          - --include=/.tox/*/log/*
+          - --include=*/
+          - --exclude=*
+          - --prune-empty-dirs
+
+    - name: Copy files from {{ ansible_user_dir }}/workspace/ on node
+      synchronize:
+        src: '{{ ansible_user_dir }}/workspace/'
+        dest: '{{ zuul.executor.log_root }}'
+        mode: pull
+        copy_links: true
+        verify_host: true
+        rsync_opts:
+          - --include=/logs/**
+          - --include=*/
+          - --exclude=*
+          - --prune-empty-dirs
diff --git a/playbooks/legacy/tempest-dsvm-patrole-multinode-admin/run.yaml b/playbooks/legacy/tempest-dsvm-patrole-multinode-admin/run.yaml
new file mode 100644
index 0000000..bece4e2
--- /dev/null
+++ b/playbooks/legacy/tempest-dsvm-patrole-multinode-admin/run.yaml
@@ -0,0 +1,63 @@
+- hosts: primary
+  name: Autoconverted job legacy-tempest-dsvm-patrole-multinode-admin from old job
+    gate-tempest-dsvm-patrole-multinode-admin-ubuntu-xenial-nv
+  tasks:
+
+    - name: Ensure legacy workspace directory
+      file:
+        path: '{{ ansible_user_dir }}/workspace'
+        state: directory
+
+    - shell:
+        cmd: |
+          set -e
+          set -x
+          cat > clonemap.yaml << EOF
+          clonemap:
+            - name: openstack-infra/devstack-gate
+              dest: devstack-gate
+          EOF
+          /usr/zuul-env/bin/zuul-cloner -m clonemap.yaml --cache-dir /opt/git \
+              git://git.openstack.org \
+              openstack-infra/devstack-gate
+        executable: /bin/bash
+        chdir: '{{ ansible_user_dir }}/workspace'
+      environment: '{{ zuul | zuul_legacy_vars }}'
+
+    - shell:
+        cmd: |
+          set -e
+          set -x
+          cat << 'EOF' >>"/tmp/dg-local.conf"
+          [[local|localrc]]
+          enable_plugin patrole git://git.openstack.org/openstack/patrole
+          TEMPEST_PLUGINS='/opt/stack/new/patrole'
+          # Needed by Patrole devstack plugin
+          RBAC_TEST_ROLE=admin
+          EOF
+        executable: /bin/bash
+        chdir: '{{ ansible_user_dir }}/workspace'
+      environment: '{{ zuul | zuul_legacy_vars }}'
+
+    - shell:
+        cmd: |
+          set -e
+          set -x
+          export PYTHONUNBUFFERED=true
+          # Ensure that tempest set up is executed, but do not automatically
+          # execute tempest tests; they are executed in post_test_hook.
+          export DEVSTACK_GATE_TEMPEST=1
+          export DEVSTACK_GATE_NEUTRON=1
+          export DEVSTACK_GATE_TOPOLOGY="multinode"
+          export DEVSTACK_GATE_TEMPEST_REGEX='(?=.*\[.*\bslow\b.*\])(^patrole_tempest_plugin\.tests\.api)'
+          export DEVSTACK_GATE_TEMPEST_ALL_PLUGINS=1
+          export PROJECTS="openstack/patrole $PROJECTS"
+          export BRANCH_OVERRIDE=default
+          if [ "$BRANCH_OVERRIDE" != "default" ] ; then
+              export OVERRIDE_ZUUL_BRANCH=$BRANCH_OVERRIDE
+          fi
+          cp devstack-gate/devstack-vm-gate-wrap.sh ./safe-devstack-vm-gate-wrap.sh
+          ./safe-devstack-vm-gate-wrap.sh
+        executable: /bin/bash
+        chdir: '{{ ansible_user_dir }}/workspace'
+      environment: '{{ zuul | zuul_legacy_vars }}'
diff --git a/playbooks/legacy/tempest-dsvm-patrole-multinode-member/post.yaml b/playbooks/legacy/tempest-dsvm-patrole-multinode-member/post.yaml
new file mode 100644
index 0000000..dac8753
--- /dev/null
+++ b/playbooks/legacy/tempest-dsvm-patrole-multinode-member/post.yaml
@@ -0,0 +1,80 @@
+- hosts: primary
+  tasks:
+
+    - name: Copy files from {{ ansible_user_dir }}/workspace/ on node
+      synchronize:
+        src: '{{ ansible_user_dir }}/workspace/'
+        dest: '{{ zuul.executor.log_root }}'
+        mode: pull
+        copy_links: true
+        verify_host: true
+        rsync_opts:
+          - --include=**/*nose_results.html
+          - --include=*/
+          - --exclude=*
+          - --prune-empty-dirs
+
+    - name: Copy files from {{ ansible_user_dir }}/workspace/ on node
+      synchronize:
+        src: '{{ ansible_user_dir }}/workspace/'
+        dest: '{{ zuul.executor.log_root }}'
+        mode: pull
+        copy_links: true
+        verify_host: true
+        rsync_opts:
+          - --include=**/*testr_results.html.gz
+          - --include=*/
+          - --exclude=*
+          - --prune-empty-dirs
+
+    - name: Copy files from {{ ansible_user_dir }}/workspace/ on node
+      synchronize:
+        src: '{{ ansible_user_dir }}/workspace/'
+        dest: '{{ zuul.executor.log_root }}'
+        mode: pull
+        copy_links: true
+        verify_host: true
+        rsync_opts:
+          - --include=/.testrepository/tmp*
+          - --include=*/
+          - --exclude=*
+          - --prune-empty-dirs
+
+    - name: Copy files from {{ ansible_user_dir }}/workspace/ on node
+      synchronize:
+        src: '{{ ansible_user_dir }}/workspace/'
+        dest: '{{ zuul.executor.log_root }}'
+        mode: pull
+        copy_links: true
+        verify_host: true
+        rsync_opts:
+          - --include=**/*testrepository.subunit.gz
+          - --include=*/
+          - --exclude=*
+          - --prune-empty-dirs
+
+    - name: Copy files from {{ ansible_user_dir }}/workspace/ on node
+      synchronize:
+        src: '{{ ansible_user_dir }}/workspace/'
+        dest: '{{ zuul.executor.log_root }}/tox'
+        mode: pull
+        copy_links: true
+        verify_host: true
+        rsync_opts:
+          - --include=/.tox/*/log/*
+          - --include=*/
+          - --exclude=*
+          - --prune-empty-dirs
+
+    - name: Copy files from {{ ansible_user_dir }}/workspace/ on node
+      synchronize:
+        src: '{{ ansible_user_dir }}/workspace/'
+        dest: '{{ zuul.executor.log_root }}'
+        mode: pull
+        copy_links: true
+        verify_host: true
+        rsync_opts:
+          - --include=/logs/**
+          - --include=*/
+          - --exclude=*
+          - --prune-empty-dirs
diff --git a/playbooks/legacy/tempest-dsvm-patrole-multinode-member/run.yaml b/playbooks/legacy/tempest-dsvm-patrole-multinode-member/run.yaml
new file mode 100644
index 0000000..4c7b70f
--- /dev/null
+++ b/playbooks/legacy/tempest-dsvm-patrole-multinode-member/run.yaml
@@ -0,0 +1,63 @@
+- hosts: primary
+  name: Autoconverted job legacy-tempest-dsvm-patrole-multinode-member from old job
+    gate-tempest-dsvm-patrole-multinode-member-ubuntu-xenial-nv
+  tasks:
+
+    - name: Ensure legacy workspace directory
+      file:
+        path: '{{ ansible_user_dir }}/workspace'
+        state: directory
+
+    - shell:
+        cmd: |
+          set -e
+          set -x
+          cat > clonemap.yaml << EOF
+          clonemap:
+            - name: openstack-infra/devstack-gate
+              dest: devstack-gate
+          EOF
+          /usr/zuul-env/bin/zuul-cloner -m clonemap.yaml --cache-dir /opt/git \
+              git://git.openstack.org \
+              openstack-infra/devstack-gate
+        executable: /bin/bash
+        chdir: '{{ ansible_user_dir }}/workspace'
+      environment: '{{ zuul | zuul_legacy_vars }}'
+
+    - shell:
+        cmd: |
+          set -e
+          set -x
+          cat << 'EOF' >>"/tmp/dg-local.conf"
+          [[local|localrc]]
+          enable_plugin patrole git://git.openstack.org/openstack/patrole
+          TEMPEST_PLUGINS='/opt/stack/new/patrole'
+          # Needed by Patrole devstack plugin
+          RBAC_TEST_ROLE=member
+          EOF
+        executable: /bin/bash
+        chdir: '{{ ansible_user_dir }}/workspace'
+      environment: '{{ zuul | zuul_legacy_vars }}'
+
+    - shell:
+        cmd: |
+          set -e
+          set -x
+          export PYTHONUNBUFFERED=true
+          # Ensure that tempest set up is executed, but do not automatically
+          # execute tempest tests; they are executed in post_test_hook.
+          export DEVSTACK_GATE_TEMPEST=1
+          export DEVSTACK_GATE_NEUTRON=1
+          export DEVSTACK_GATE_TOPOLOGY="multinode"
+          export DEVSTACK_GATE_TEMPEST_REGEX='(?=.*\[.*\bslow\b.*\])(^patrole_tempest_plugin\.tests\.api)'
+          export DEVSTACK_GATE_TEMPEST_ALL_PLUGINS=1
+          export PROJECTS="openstack/patrole $PROJECTS"
+          export BRANCH_OVERRIDE=default
+          if [ "$BRANCH_OVERRIDE" != "default" ] ; then
+              export OVERRIDE_ZUUL_BRANCH=$BRANCH_OVERRIDE
+          fi
+          cp devstack-gate/devstack-vm-gate-wrap.sh ./safe-devstack-vm-gate-wrap.sh
+          ./safe-devstack-vm-gate-wrap.sh
+        executable: /bin/bash
+        chdir: '{{ ansible_user_dir }}/workspace'
+      environment: '{{ zuul | zuul_legacy_vars }}'
diff --git a/playbooks/legacy/tempest-dsvm-patrole-py35-member/post.yaml b/playbooks/legacy/tempest-dsvm-patrole-py35-member/post.yaml
new file mode 100644
index 0000000..dac8753
--- /dev/null
+++ b/playbooks/legacy/tempest-dsvm-patrole-py35-member/post.yaml
@@ -0,0 +1,80 @@
+- hosts: primary
+  tasks:
+
+    - name: Copy files from {{ ansible_user_dir }}/workspace/ on node
+      synchronize:
+        src: '{{ ansible_user_dir }}/workspace/'
+        dest: '{{ zuul.executor.log_root }}'
+        mode: pull
+        copy_links: true
+        verify_host: true
+        rsync_opts:
+          - --include=**/*nose_results.html
+          - --include=*/
+          - --exclude=*
+          - --prune-empty-dirs
+
+    - name: Copy files from {{ ansible_user_dir }}/workspace/ on node
+      synchronize:
+        src: '{{ ansible_user_dir }}/workspace/'
+        dest: '{{ zuul.executor.log_root }}'
+        mode: pull
+        copy_links: true
+        verify_host: true
+        rsync_opts:
+          - --include=**/*testr_results.html.gz
+          - --include=*/
+          - --exclude=*
+          - --prune-empty-dirs
+
+    - name: Copy files from {{ ansible_user_dir }}/workspace/ on node
+      synchronize:
+        src: '{{ ansible_user_dir }}/workspace/'
+        dest: '{{ zuul.executor.log_root }}'
+        mode: pull
+        copy_links: true
+        verify_host: true
+        rsync_opts:
+          - --include=/.testrepository/tmp*
+          - --include=*/
+          - --exclude=*
+          - --prune-empty-dirs
+
+    - name: Copy files from {{ ansible_user_dir }}/workspace/ on node
+      synchronize:
+        src: '{{ ansible_user_dir }}/workspace/'
+        dest: '{{ zuul.executor.log_root }}'
+        mode: pull
+        copy_links: true
+        verify_host: true
+        rsync_opts:
+          - --include=**/*testrepository.subunit.gz
+          - --include=*/
+          - --exclude=*
+          - --prune-empty-dirs
+
+    - name: Copy files from {{ ansible_user_dir }}/workspace/ on node
+      synchronize:
+        src: '{{ ansible_user_dir }}/workspace/'
+        dest: '{{ zuul.executor.log_root }}/tox'
+        mode: pull
+        copy_links: true
+        verify_host: true
+        rsync_opts:
+          - --include=/.tox/*/log/*
+          - --include=*/
+          - --exclude=*
+          - --prune-empty-dirs
+
+    - name: Copy files from {{ ansible_user_dir }}/workspace/ on node
+      synchronize:
+        src: '{{ ansible_user_dir }}/workspace/'
+        dest: '{{ zuul.executor.log_root }}'
+        mode: pull
+        copy_links: true
+        verify_host: true
+        rsync_opts:
+          - --include=/logs/**
+          - --include=*/
+          - --exclude=*
+          - --prune-empty-dirs
diff --git a/playbooks/legacy/tempest-dsvm-patrole-py35-member/run.yaml b/playbooks/legacy/tempest-dsvm-patrole-py35-member/run.yaml
new file mode 100644
index 0000000..e895702
--- /dev/null
+++ b/playbooks/legacy/tempest-dsvm-patrole-py35-member/run.yaml
@@ -0,0 +1,70 @@
+- hosts: all
+  name: Autoconverted job legacy-tempest-dsvm-patrole-py35-member from old job gate-tempest-dsvm-patrole-py35-member-ubuntu-xenial
+  tasks:
+
+    - name: Ensure legacy workspace directory
+      file:
+        path: '{{ ansible_user_dir }}/workspace'
+        state: directory
+
+    - shell:
+        cmd: |
+          set -e
+          set -x
+          cat > clonemap.yaml << EOF
+          clonemap:
+            - name: openstack-infra/devstack-gate
+              dest: devstack-gate
+          EOF
+          /usr/zuul-env/bin/zuul-cloner -m clonemap.yaml --cache-dir /opt/git \
+              git://git.openstack.org \
+              openstack-infra/devstack-gate
+        executable: /bin/bash
+        chdir: '{{ ansible_user_dir }}/workspace'
+      environment: '{{ zuul | zuul_legacy_vars }}'
+
+    - shell:
+        cmd: |
+          set -e
+          set -x
+          cat << 'EOF' >>"/tmp/dg-local.conf"
+          [[local|localrc]]
+          enable_plugin patrole git://git.openstack.org/openstack/patrole
+          TEMPEST_PLUGINS='/opt/stack/new/patrole'
+          # Needed by Patrole devstack plugin
+          RBAC_TEST_ROLE=member
+          # Swift is not ready for python3 yet
+          disable_service s-account
+          disable_service s-container
+          disable_service s-object
+          disable_service s-proxy
+          # Without Swift, c-bak cannot run (in the Gate at least)
+          disable_service c-bak
+          EOF
+        executable: /bin/bash
+        chdir: '{{ ansible_user_dir }}/workspace'
+      environment: '{{ zuul | zuul_legacy_vars }}'
+
+    - shell:
+        cmd: |
+          set -e
+          set -x
+          export PYTHONUNBUFFERED=true
+          export DEVSTACK_GATE_USE_PYTHON3=True
+          # Ensure that tempest set up is executed, but do not automatically
+          # execute tempest tests; they are executed in post_test_hook.
+          export DEVSTACK_GATE_TEMPEST=1
+          export DEVSTACK_GATE_NEUTRON=1
+          export DEVSTACK_GATE_TEMPEST_REGEX='(?!.*\[.*\bslow\b.*\])(^patrole_tempest_plugin\.tests\.api)'
+          export DEVSTACK_GATE_TEMPEST_ALL_PLUGINS=1
+          export TEMPEST_CONCURRENCY=2
+          export PROJECTS="openstack/patrole $PROJECTS"
+          export BRANCH_OVERRIDE=default
+          if [ "$BRANCH_OVERRIDE" != "default" ] ; then
+              export OVERRIDE_ZUUL_BRANCH=$BRANCH_OVERRIDE
+          fi
+          cp devstack-gate/devstack-vm-gate-wrap.sh ./safe-devstack-vm-gate-wrap.sh
+          ./safe-devstack-vm-gate-wrap.sh
+        executable: /bin/bash
+        chdir: '{{ ansible_user_dir }}/workspace'
+      environment: '{{ zuul | zuul_legacy_vars }}'
diff --git a/releasenotes/notes/deprecate-strict-policy-enforce-option-e15d2be4e753608e.yaml b/releasenotes/notes/deprecate-strict-policy-enforce-option-e15d2be4e753608e.yaml
new file mode 100644
index 0000000..4f56dd8
--- /dev/null
+++ b/releasenotes/notes/deprecate-strict-policy-enforce-option-e15d2be4e753608e.yaml
@@ -0,0 +1,10 @@
+---
+deprecations:
+  - |
+    The configuration option ``[patrole] strict_policy_check`` is deprecated
+    and will be removed in the Rocky release cycle.
+other:
+  - |
+    The default value for ``[patrole] strict_policy_check`` has been changed
+    to ``True`` because a Patrole test should always fail if the policy action
+    is invalid, to avoid false positives.