Merge "Fix hacking min version to 3.0.1"
diff --git a/doc/requirements.txt b/doc/requirements.txt
index 54fca18..2a94e8b 100644
--- a/doc/requirements.txt
+++ b/doc/requirements.txt
@@ -3,11 +3,11 @@
 # process, which may cause wedges in the gate later.
 
 sphinxcontrib-apidoc>=0.2.0 # BSD
-sphinx!=1.6.6,!=1.6.7,>=1.6.2,!=2.1.0;  # BSD
-openstackdocstheme>=1.18.1 # Apache-2.0
+sphinx>=2.0.0,!=2.1.0 # BSD
+openstackdocstheme>=2.2.1 # Apache-2.0
 
 # releasenotes
-reno>=2.5.0 # Apache-2.0
+reno>=3.1.0 # Apache-2.0
 
 # PDF Docs
 sphinxcontrib-svg2pdfconverter>=0.1.0 # BSD
diff --git a/doc/source/conf.py b/doc/source/conf.py
index 5bbe295..ff6a826 100755
--- a/doc/source/conf.py
+++ b/doc/source/conf.py
@@ -16,8 +16,6 @@
 import os
 import sys
 
-import openstackdocstheme
-
 sys.path.insert(0, os.path.abspath('../..'))
 sys.path.insert(0, os.path.abspath('.'))
 
@@ -49,16 +47,6 @@
 project = u'octavia-tempest-plugin'
 copyright = u'2017-2019, OpenStack Foundation'
 
-# The version info for the project you're documenting, acts as replacement for
-# |version| and |release|, also used in various other places throughout the
-# built documents.
-#
-# Version info
-from octavia_tempest_plugin.version import version_info as octavia_tempest_ver
-release = octavia_tempest_ver.release_string()
-# The short X.Y version.
-version = octavia_tempest_ver.version_string()
-
 # If true, '()' will be appended to :func: etc. cross-reference text.
 add_function_parentheses = True
 
@@ -67,14 +55,14 @@
 add_module_names = False
 
 # The name of the Pygments (syntax highlighting) style to use.
-pygments_style = 'sphinx'
+pygments_style = 'native'
 
 # A list of ignored prefixes for module index sorting.
 modindex_common_prefix = ['octavia_tempest_plugin.']
 
-repository_name = 'openstack/octavia-tempest-plugin'
-bug_project = '910'
-bug_tag = 'docs'
+openstackdocs_repo_name = 'openstack/octavia-tempest-plugin'
+openstackdocs_pdf_link = True
+openstackdocs_use_storyboard = True
 
 apidoc_output_dir = '_build/modules'
 apidoc_module_dir = '../../octavia_tempest_plugin'
@@ -90,7 +78,6 @@
 
 html_theme = 'openstackdocs'
 
-html_last_updated_fmt = '%Y-%m-%d %H:%M'
 
 # Output file base name for HTML help builder.
 htmlhelp_basename = '%sdoc' % project
diff --git a/octavia_tempest_plugin/tests/api/v2/test_amphora.py b/octavia_tempest_plugin/tests/api/v2/test_amphora.py
index 7cf77dd..d1106e6 100644
--- a/octavia_tempest_plugin/tests/api/v2/test_amphora.py
+++ b/octavia_tempest_plugin/tests/api/v2/test_amphora.py
@@ -12,6 +12,9 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+from uuid import UUID
+
+from dateutil import parser
 from tempest import config
 from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
@@ -57,6 +60,98 @@
                                 CONF.load_balancer.lb_build_interval,
                                 CONF.load_balancer.lb_build_timeout)
 
+    def _expected_amp_count(self, amp_list):
+        self.assertNotEmpty(amp_list)
+        if amp_list[0][const.ROLE] in (const.ROLE_MASTER, const.ROLE_BACKUP):
+            return 2
+        return 1
+
+    @decorators.idempotent_id('a0e9ff99-2c4f-45d5-81c9-78d3107c236f')
+    def test_amphora_list_and_show(self):
+        """Tests amphora show API.
+
+        * Show amphora details.
+        * Validate the show reflects the requested values.
+        * Validates that other accounts cannot see the amphora.
+        """
+        lb_name = data_utils.rand_name("lb_member_lb2_amphora-list")
+        lb = self.mem_lb_client.create_loadbalancer(
+            name=lb_name, provider=CONF.load_balancer.provider,
+            vip_network_id=self.lb_member_vip_net[const.ID])
+        lb_id = lb[const.ID]
+        self.addCleanup(self.mem_lb_client.cleanup_loadbalancer, lb_id)
+
+        waiters.wait_for_status(self.mem_lb_client.show_loadbalancer,
+                                lb_id,
+                                const.PROVISIONING_STATUS,
+                                const.ACTIVE,
+                                CONF.load_balancer.lb_build_interval,
+                                CONF.load_balancer.lb_build_timeout)
+
+        # Test that a user, without the load balancer member role, cannot
+        # list amphorae
+        if CONF.load_balancer.RBAC_test_type == const.ADVANCED:
+            self.assertRaises(
+                exceptions.Forbidden,
+                self.os_primary.amphora_client.list_amphorae)
+
+        # Get an actual list of the amphorae
+        amphorae = self.lb_admin_amphora_client.list_amphorae()
+
+        # There should be AT LEAST 2, there may be more depending on the
+        # configured topology
+        self.assertGreaterEqual(
+            len(amphorae), 2 * self._expected_amp_count(amphorae))
+
+        # Test filtering by loadbalancer_id
+        amphorae = self.lb_admin_amphora_client.list_amphorae(
+            query_params='{loadbalancer_id}={lb_id}'.format(
+                loadbalancer_id=const.LOADBALANCER_ID, lb_id=self.lb_id))
+        self.assertEqual(self._expected_amp_count(amphorae), len(amphorae))
+        self.assertEqual(self.lb_id, amphorae[0][const.LOADBALANCER_ID])
+
+        # Test that a different user, with load balancer member role, cannot
+        # see this amphora
+        if not CONF.load_balancer.RBAC_test_type == const.NONE:
+            member2_client = self.os_roles_lb_member2.amphora_client
+            self.assertRaises(exceptions.Forbidden,
+                              member2_client.show_amphora,
+                              amphora_id=amphorae[0][const.ID])
+
+        show_amphora_response_fields = const.SHOW_AMPHORA_RESPONSE_FIELDS
+        if self.lb_admin_amphora_client.is_version_supported(
+                self.api_version, '2.1'):
+            show_amphora_response_fields.append('created_at')
+            show_amphora_response_fields.append('updated_at')
+            show_amphora_response_fields.append('image_id')
+
+        for amp in amphorae:
+
+            # Make sure all of the fields exist on the amp list records
+            for field in show_amphora_response_fields:
+                self.assertIn(field, amp)
+
+            # Verify a few of the fields are the right type
+            if self.lb_admin_amphora_client.is_version_supported(
+                    self.api_version, '2.1'):
+                parser.parse(amp[const.CREATED_AT])
+                parser.parse(amp[const.UPDATED_AT])
+
+            UUID(amp[const.ID])
+            UUID(amp[const.HA_PORT_ID])
+            UUID(amp[const.LOADBALANCER_ID])
+            UUID(amp[const.COMPUTE_ID])
+            UUID(amp[const.VRRP_PORT_ID])
+            self.assertEqual(amp[const.STATUS], const.STATUS_ALLOCATED)
+            self.assertIn(amp[const.ROLE], const.AMPHORA_ROLES)
+
+            # Test that all of the fields from the amp list match those
+            # from a show for the LB we created.
+            amp_obj = self.lb_admin_amphora_client.show_amphora(
+                amphora_id=amp[const.ID])
+            for field in show_amphora_response_fields:
+                self.assertEqual(amp[field], amp_obj[field])
+
     @decorators.idempotent_id('b7fc231b-dcfa-47a5-99f3-ec5ddcc48f30')
     def test_amphora_update(self):
         """Tests the amphora agent configuration update API
diff --git a/octavia_tempest_plugin/tests/barbican_scenario/v2/test_tls_barbican.py b/octavia_tempest_plugin/tests/barbican_scenario/v2/test_tls_barbican.py
index 84bfc20..a753a5c 100644
--- a/octavia_tempest_plugin/tests/barbican_scenario/v2/test_tls_barbican.py
+++ b/octavia_tempest_plugin/tests/barbican_scenario/v2/test_tls_barbican.py
@@ -749,8 +749,8 @@
                                 CONF.load_balancer.build_timeout)
 
         # Test that no client certificate fails to connect
-        self.assertRaisesRegex(
-            requests.exceptions.SSLError, ".*certificate required.*",
+        self.assertRaises(
+            requests.exceptions.SSLError,
             requests.get,
             'https://{0}:{1}'.format(self.lb_vip_address, LISTENER1_TCP_PORT),
             timeout=12, verify=False)
@@ -764,8 +764,8 @@
                     serialization.Encoding.PEM,
                     serialization.PrivateFormat.TraditionalOpenSSL,
                     serialization.NoEncryption()))
-                self.assertRaisesRegex(
-                    requests.exceptions.SSLError, ".*revoked.*", requests.get,
+                self.assertRaises(
+                    requests.exceptions.SSLError, requests.get,
                     'https://{0}:{1}'.format(self.lb_vip_address,
                                              LISTENER1_TCP_PORT),
                     timeout=12, verify=False, cert=(cert_file.name,
@@ -836,8 +836,8 @@
                     serialization.Encoding.PEM,
                     serialization.PrivateFormat.TraditionalOpenSSL,
                     serialization.NoEncryption()))
-                self.assertRaisesRegex(
-                    requests.exceptions.SSLError, ".*revoked.*", requests.get,
+                self.assertRaises(
+                    requests.exceptions.SSLError, requests.get,
                     'https://{0}:{1}'.format(self.lb_vip_address,
                                              LISTENER1_TCP_PORT),
                     timeout=12, verify=False, cert=(cert_file.name,
@@ -954,15 +954,15 @@
                                 CONF.load_balancer.build_timeout)
 
         # Test that no client certificate fails to connect to listener1
-        self.assertRaisesRegex(
-            requests.exceptions.SSLError, ".*certificate required.*",
+        self.assertRaises(
+            requests.exceptions.SSLError,
             requests.get,
             'https://{0}:{1}'.format(self.lb_vip_address, LISTENER1_TCP_PORT),
             timeout=12, verify=False)
 
         # Test that no client certificate fails to connect to listener2
-        self.assertRaisesRegex(
-            requests.exceptions.SSLError, ".*certificate required.*",
+        self.assertRaises(
+            requests.exceptions.SSLError,
             requests.get,
             'https://{0}:{1}'.format(self.lb_vip_address, LISTENER2_TCP_PORT),
             timeout=12, verify=False)
@@ -976,8 +976,8 @@
                     serialization.Encoding.PEM,
                     serialization.PrivateFormat.TraditionalOpenSSL,
                     serialization.NoEncryption()))
-                self.assertRaisesRegex(
-                    requests.exceptions.SSLError, ".*revoked.*", requests.get,
+                self.assertRaises(
+                    requests.exceptions.SSLError, requests.get,
                     'https://{0}:{1}'.format(self.lb_vip_address,
                                              LISTENER1_TCP_PORT),
                     timeout=12, verify=False, cert=(cert_file.name,
@@ -992,8 +992,8 @@
                     serialization.Encoding.PEM,
                     serialization.PrivateFormat.TraditionalOpenSSL,
                     serialization.NoEncryption()))
-                self.assertRaisesRegex(
-                    requests.exceptions.SSLError, ".*revoked.*", requests.get,
+                self.assertRaises(
+                    requests.exceptions.SSLError, requests.get,
                     'https://{0}:{1}'.format(self.lb_vip_address,
                                              LISTENER2_TCP_PORT),
                     timeout=12, verify=False, cert=(cert_file.name,
@@ -1040,8 +1040,8 @@
                     serialization.Encoding.PEM,
                     serialization.PrivateFormat.TraditionalOpenSSL,
                     serialization.NoEncryption()))
-                self.assertRaisesRegex(
-                    requests.exceptions.SSLError, ".*decrypt error.*",
+                self.assertRaises(
+                    requests.exceptions.SSLError,
                     requests.get, 'https://{0}:{1}'.format(self.lb_vip_address,
                                                            LISTENER2_TCP_PORT),
                     timeout=12, verify=False, cert=(cert_file.name,
@@ -1056,8 +1056,8 @@
                     serialization.Encoding.PEM,
                     serialization.PrivateFormat.TraditionalOpenSSL,
                     serialization.NoEncryption()))
-                self.assertRaisesRegex(
-                    requests.exceptions.SSLError, ".*decrypt error.*",
+                self.assertRaises(
+                    requests.exceptions.SSLError,
                     requests.get, 'https://{0}:{1}'.format(self.lb_vip_address,
                                                            LISTENER1_TCP_PORT),
                     timeout=12, verify=False, cert=(cert_file.name,
@@ -1072,8 +1072,8 @@
                     serialization.Encoding.PEM,
                     serialization.PrivateFormat.TraditionalOpenSSL,
                     serialization.NoEncryption()))
-                self.assertRaisesRegex(
-                    requests.exceptions.SSLError, ".*decrypt error.*",
+                self.assertRaises(
+                    requests.exceptions.SSLError,
                     requests.get, 'https://{0}:{1}'.format(self.lb_vip_address,
                                                            LISTENER2_TCP_PORT),
                     timeout=12, verify=False, cert=(cert_file.name,
@@ -1088,8 +1088,8 @@
                     serialization.Encoding.PEM,
                     serialization.PrivateFormat.TraditionalOpenSSL,
                     serialization.NoEncryption()))
-                self.assertRaisesRegex(
-                    requests.exceptions.SSLError, ".*decrypt error.*",
+                self.assertRaises(
+                    requests.exceptions.SSLError,
                     requests.get, 'https://{0}:{1}'.format(self.lb_vip_address,
                                                            LISTENER1_TCP_PORT),
                     timeout=12, verify=False, cert=(cert_file.name,
diff --git a/octavia_tempest_plugin/tests/scenario/v2/test_amphora.py b/octavia_tempest_plugin/tests/scenario/v2/test_amphora.py
deleted file mode 100644
index 95266e8..0000000
--- a/octavia_tempest_plugin/tests/scenario/v2/test_amphora.py
+++ /dev/null
@@ -1,189 +0,0 @@
-# Copyright 2018 GoDaddy
-#
-#    Licensed under the Apache License, Version 2.0 (the "License"); you may
-#    not use this file except in compliance with the License. You may obtain
-#    a copy of the License at
-#
-#         http://www.apache.org/licenses/LICENSE-2.0
-#
-#    Unless required by applicable law or agreed to in writing, software
-#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-#    License for the specific language governing permissions and limitations
-#    under the License.
-
-from uuid import UUID
-
-from dateutil import parser
-from tempest import config
-from tempest.lib.common.utils import data_utils
-from tempest.lib import decorators
-from tempest.lib import exceptions
-
-from octavia_tempest_plugin.common import constants as const
-from octavia_tempest_plugin.tests import test_base
-from octavia_tempest_plugin.tests import waiters
-
-CONF = config.CONF
-
-
-class AmphoraScenarioTest(test_base.LoadBalancerBaseTest):
-    """Test the amphora object API."""
-
-    @classmethod
-    def skip_checks(cls):
-        super(AmphoraScenarioTest, cls).skip_checks()
-
-        if CONF.load_balancer.provider not in const.AMPHORA_PROVIDERS:
-            raise cls.skipException("Amphora tests require provider 'amphora' "
-                                    "or 'octavia' (alias to 'amphora', "
-                                    " deprecated) set")
-
-    @classmethod
-    def resource_setup(cls):
-        """Setup resources needed by the tests."""
-        super(AmphoraScenarioTest, cls).resource_setup()
-
-        lb_name = data_utils.rand_name("lb_member_lb1_amphora")
-        lb_kwargs = {const.PROVIDER: CONF.load_balancer.provider,
-                     const.NAME: lb_name}
-
-        cls._setup_lb_network_kwargs(lb_kwargs)
-
-        lb = cls.mem_lb_client.create_loadbalancer(**lb_kwargs)
-        cls.lb_id = lb[const.ID]
-        cls.addClassResourceCleanup(
-            cls.mem_lb_client.cleanup_loadbalancer,
-            cls.lb_id)
-
-        waiters.wait_for_status(cls.mem_lb_client.show_loadbalancer,
-                                cls.lb_id, const.PROVISIONING_STATUS,
-                                const.ACTIVE,
-                                CONF.load_balancer.lb_build_interval,
-                                CONF.load_balancer.lb_build_timeout)
-
-    def _expected_amp_count(self, amp_list):
-        self.assertNotEmpty(amp_list)
-        if amp_list[0][const.ROLE] in (const.ROLE_MASTER, const.ROLE_BACKUP):
-            return 2
-        return 1
-
-    @decorators.idempotent_id('a0e9ff99-2c4f-45d5-81c9-78d3107c236f')
-    def test_amphora_list_and_show(self):
-        """Tests amphora show API.
-
-        * Show amphora details.
-        * Validate the show reflects the requested values.
-        * Validates that other accounts cannot see the amphora.
-        """
-        lb_name = data_utils.rand_name("lb_member_lb2_amphora-list")
-        lb = self.mem_lb_client.create_loadbalancer(
-            name=lb_name, provider=CONF.load_balancer.provider,
-            vip_network_id=self.lb_member_vip_net[const.ID])
-        lb_id = lb[const.ID]
-        self.addCleanup(
-            self.mem_lb_client.cleanup_loadbalancer,
-            lb_id)
-
-        waiters.wait_for_status(self.mem_lb_client.show_loadbalancer,
-                                lb_id,
-                                const.PROVISIONING_STATUS,
-                                const.ACTIVE,
-                                CONF.load_balancer.lb_build_interval,
-                                CONF.load_balancer.lb_build_timeout)
-
-        # Test that a user with lb_admin role can list the amphora
-        if CONF.load_balancer.RBAC_test_type == const.ADVANCED:
-            amphora_client = self.os_roles_lb_admin.amphora_client
-            amphora_adm = amphora_client.list_amphorae()
-            self.assertGreaterEqual(
-                len(amphora_adm), 2 * self._expected_amp_count(amphora_adm))
-
-        # Test that a different user, with load balancer member role, cannot
-        # see this amphora
-        if not CONF.load_balancer.RBAC_test_type == const.NONE:
-            member2_client = self.os_roles_lb_member2.amphora_client
-            self.assertRaises(exceptions.Forbidden,
-                              member2_client.list_amphorae)
-
-        # Test that a user, without the load balancer member role, cannot
-        # list amphorae
-        if CONF.load_balancer.RBAC_test_type == const.ADVANCED:
-            self.assertRaises(
-                exceptions.Forbidden,
-                self.os_primary.amphora_client.list_amphorae)
-
-        # Test that a user with cloud admin role can list the amphorae
-        if not CONF.load_balancer.RBAC_test_type == const.NONE:
-            adm = self.lb_admin_amphora_client.list_amphorae()
-            self.assertGreaterEqual(len(adm),
-                                    2 * self._expected_amp_count(adm))
-
-        # Get an actual list of the amphorae
-        amphorae = self.lb_admin_amphora_client.list_amphorae()
-
-        # There should be AT LEAST 2, there may be more depending on the
-        # configured topology, or if there are other LBs created besides ours
-        self.assertGreaterEqual(
-            len(amphorae), 2 * self._expected_amp_count(amphorae))
-
-        show_amphora_response_fields = const.SHOW_AMPHORA_RESPONSE_FIELDS
-        if self.lb_admin_amphora_client.is_version_supported(
-                self.api_version, '2.1'):
-            show_amphora_response_fields.append('created_at')
-            show_amphora_response_fields.append('updated_at')
-            show_amphora_response_fields.append('image_id')
-
-        for amp in amphorae:
-
-            # Make sure all of the fields exist on the amp list records
-            for field in show_amphora_response_fields:
-                self.assertIn(field, amp)
-
-            amp_id = amp[const.ID]
-            amp_obj = self.lb_admin_amphora_client.show_amphora(
-                amphora_id=amp_id)
-
-            # Make sure all of the fields exist on the amp show record
-            for field in show_amphora_response_fields:
-                self.assertIn(field, amp_obj)
-
-            # Verify a few of the fields are the right type
-            if self.lb_admin_amphora_client.is_version_supported(
-                    self.api_version, '2.1'):
-                parser.parse(amp_obj[const.CREATED_AT])
-                parser.parse(amp_obj[const.UPDATED_AT])
-            UUID(amp_obj[const.ID])
-            self.assertIn(amp_obj[const.STATUS], const.AMPHORA_STATUSES)
-
-            # We might have gotten unassigned/spare amps?
-            if amp_obj[const.STATUS] == const.STATUS_ALLOCATED:
-                # Only check the state of fields for the LB we created,
-                # otherwise some fields (HA_PORT_ID) may not yet be
-                # populated in amps for parallel tests.
-                if lb_id == amp_obj[const.LOADBALANCER_ID]:
-                    UUID(amp_obj[const.HA_PORT_ID])
-                    UUID(amp_obj[const.LOADBALANCER_ID])
-                    UUID(amp_obj[const.COMPUTE_ID])
-                    UUID(amp_obj[const.VRRP_PORT_ID])
-                    self.assertIn(amp_obj[const.ROLE], const.AMPHORA_ROLES)
-            else:
-                self.assertIsNone(amp_obj[const.ROLE])
-
-            # Test that all of the fields from the amp list match those
-            # from a show
-            for field in show_amphora_response_fields:
-                self.assertEqual(amp[field], amp_obj[field])
-
-        # Test filtering by loadbalancer_id
-        amphorae = self.lb_admin_amphora_client.list_amphorae(
-            query_params='{loadbalancer_id}={lb_id}'.format(
-                loadbalancer_id=const.LOADBALANCER_ID, lb_id=self.lb_id))
-        self.assertEqual(self._expected_amp_count(amphorae), len(amphorae))
-        self.assertEqual(self.lb_id, amphorae[0][const.LOADBALANCER_ID])
-
-        amphorae = self.lb_admin_amphora_client.list_amphorae(
-            query_params='{loadbalancer_id}={lb_id}'.format(
-                loadbalancer_id=const.LOADBALANCER_ID, lb_id=lb_id))
-        self.assertEqual(self._expected_amp_count(amphorae), len(amphorae))
-        self.assertEqual(lb_id, amphorae[0][const.LOADBALANCER_ID])
diff --git a/releasenotes/source/conf.py b/releasenotes/source/conf.py
index a346f01..8437073 100644
--- a/releasenotes/source/conf.py
+++ b/releasenotes/source/conf.py
@@ -43,8 +43,9 @@
 ]
 
 # openstackdocstheme options
-repository_name = 'openstack/octavia-tempest-plugin'
-use_storyboard = True
+openstackdocs_repo_name = 'openstack/octavia-tempest-plugin'
+openstackdocs_auto_name = False
+openstackdocs_use_storyboard = True
 
 # Add any paths that contain templates here, relative to this directory.
 templates_path = ['_templates']
@@ -102,7 +103,7 @@
 # show_authors = False
 
 # The name of the Pygments (syntax highlighting) style to use.
-pygments_style = 'sphinx'
+pygments_style = 'native'
 
 # A list of ignored prefixes for module index sorting.
 # modindex_common_prefix = []
diff --git a/requirements.txt b/requirements.txt
index 8020630..b30b450 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -4,7 +4,6 @@
 
 cryptography>=2.1 # BSD/Apache-2.0
 python-dateutil>=2.5.3 # BSD
-ipaddress>=1.0.17;python_version<'3.3' # PSF
 pbr!=2.1.0,>=2.0.0 # Apache-2.0
 oslo.config>=5.2.0 # Apache-2.0
 oslo.log>=3.36.0  # Apache-2.0
diff --git a/zuul.d/jobs.yaml b/zuul.d/jobs.yaml
index 60d9150..38b2d04 100644
--- a/zuul.d/jobs.yaml
+++ b/zuul.d/jobs.yaml
@@ -463,6 +463,9 @@
     vars:
       devstack_localrc:
         USE_PYTHON3: False
+    required-projects:
+      - name: openstack/diskimage-builder
+        override-checkout: 2.30.0
 
 - job:
     name: octavia-v2-dsvm-scenario-stable-train
@@ -473,6 +476,9 @@
     name: octavia-v2-dsvm-scenario-stable-stein
     parent: octavia-v2-dsvm-scenario
     override-checkout: stable/stein
+    required-projects:
+      - name: openstack/diskimage-builder
+        override-checkout: 2.30.0
 
 # Legacy jobs for the transition to the act-stdby two node jobs
 - job:
@@ -504,6 +510,9 @@
           USE_PYTHON3: False
           LIBVIRT_TYPE: kvm
           LIBVIRT_CPU_MODE: host-passthrough
+    required-projects:
+      - name: openstack/diskimage-builder
+        override-checkout: 2.30.0
 
 - job:
     name: octavia-v2-act-stdby-dsvm-scenario-two-node
@@ -589,6 +598,9 @@
     name: octavia-v2-dsvm-tls-barbican-stable-stein
     parent: octavia-v2-dsvm-tls-barbican
     override-checkout: stable/stein
+    required-projects:
+      - name: openstack/diskimage-builder
+        override-checkout: 2.30.0
 
 - job:
     name: octavia-v2-dsvm-tls-barbican-stable-rocky
@@ -621,6 +633,9 @@
     vars:
       devstack_localrc:
         USE_PYTHON3: False
+    required-projects:
+      - name: openstack/diskimage-builder
+        override-checkout: 2.30.0
 
 - job:
     name: octavia-v2-dsvm-spare-pool-stable-train
@@ -631,6 +646,9 @@
     name: octavia-v2-dsvm-spare-pool-stable-stein
     parent: octavia-v2-dsvm-spare-pool
     override-checkout: stable/stein
+    required-projects:
+      - name: openstack/diskimage-builder
+        override-checkout: 2.30.0
 
 - job:
     name: octavia-v2-dsvm-cinder-amphora
@@ -723,6 +741,9 @@
     vars:
       devstack_localrc:
         USE_PYTHON3: False
+    required-projects:
+      - name: openstack/diskimage-builder
+        override-checkout: 2.30.0
 
 - job:
     name: octavia-v2-act-stdby-iptables-dsvm-py2-scenario-centos-7
@@ -766,3 +787,6 @@
     name: octavia-v2-act-stdby-dsvm-scenario-stable-stein
     parent: octavia-v2-act-stdby-dsvm-scenario
     override-checkout: stable/stein
+    required-projects:
+      - name: openstack/diskimage-builder
+        override-checkout: 2.30.0