Merge "Use assertLessEqual for downtime validation"
diff --git a/tempest/api/image/v2/test_images.py b/tempest/api/image/v2/test_images.py
index 1d05f13..b723977 100644
--- a/tempest/api/image/v2/test_images.py
+++ b/tempest/api/image/v2/test_images.py
@@ -819,21 +819,8 @@
         # Add a new location
         new_loc = {'metadata': {'foo': 'bar'},
                    'url': CONF.image.http_image}
-
-        # NOTE(danms): If glance was unable to fetch the remote image via
-        # HTTP, it will return BadRequest. Because this can be transient in
-        # CI, we try this a few times before we agree that it has failed
-        # for a reason worthy of failing the test.
-        for i in range(BAD_REQUEST_RETRIES):
-            try:
-                self.client.update_image(image['id'], [
-                    dict(add='/locations/-', value=new_loc)])
-                break
-            except lib_exc.BadRequest:
-                if i + 1 == BAD_REQUEST_RETRIES:
-                    raise
-                else:
-                    time.sleep(1)
+        self._update_image_with_retries(image['id'], [
+            dict(add='/locations/-', value=new_loc)])
 
         # The image should now be active, with one location that looks
         # like we expect
@@ -858,20 +845,14 @@
     def test_set_location(self):
         self._check_set_location()
 
-    def _check_set_multiple_locations(self):
-        image = self._check_set_location()
-
-        new_loc = {'metadata': {'speed': '88mph'},
-                   'url': '%s#new' % CONF.image.http_image}
-
+    def _update_image_with_retries(self, image, patch):
         # NOTE(danms): If glance was unable to fetch the remote image via
         # HTTP, it will return BadRequest. Because this can be transient in
         # CI, we try this a few times before we agree that it has failed
         # for a reason worthy of failing the test.
         for i in range(BAD_REQUEST_RETRIES):
             try:
-                self.client.update_image(image['id'], [
-                    dict(add='/locations/-', value=new_loc)])
+                self.client.update_image(image, patch)
                 break
             except lib_exc.BadRequest:
                 if i + 1 == BAD_REQUEST_RETRIES:
@@ -879,6 +860,15 @@
                 else:
                     time.sleep(1)
 
+    def _check_set_multiple_locations(self):
+        image = self._check_set_location()
+
+        new_loc = {'metadata': {'speed': '88mph'},
+                   'url': '%s#new' % CONF.image.http_image}
+        self._update_image_with_retries(image['id'],
+                                        [dict(add='/locations/-',
+                                              value=new_loc)])
+
         # The image should now have two locations and the last one
         # (locations are ordered) should have the new URL.
         image = self.client.show_image(image['id'])
@@ -989,8 +979,9 @@
                                        'os_hash_algo': 'sha512'},
                    'metadata': {},
                    'url': CONF.image.http_image}
-        self.client.update_image(image['id'], [
-            dict(add='/locations/-', value=new_loc)])
+        self._update_image_with_retries(image['id'],
+                                        [dict(add='/locations/-',
+                                              value=new_loc)])
 
         # Expect that all of our values ended up on the image
         image = self.client.show_image(image['id'])
@@ -1017,8 +1008,9 @@
                                 'os_hash_algo': orig_image['os_hash_algo']},
             'metadata': {},
             'url': '%s#new' % CONF.image.http_image}
-        self.client.update_image(orig_image['id'], [
-            dict(add='/locations/-', value=new_loc)])
+        self._update_image_with_retries(orig_image['id'],
+                                        [dict(add='/locations/-',
+                                              value=new_loc)])
 
         # Setting the same exact values on a new location should work
         image = self.client.show_image(orig_image['id'])
@@ -1052,17 +1044,17 @@
 
             # This should always fail due to the mismatch
             self.assertRaises(lib_exc.Conflict,
-                              self.client.update_image,
-                              orig_image['id'], [
-                                  dict(add='/locations/-', value=new_loc)])
+                              self._update_image_with_retries,
+                              orig_image['id'],
+                              [dict(add='/locations/-', value=new_loc)])
 
         # Now try to add a new location with all of the substitutions,
         # which should also fail
         new_loc['validation_data'] = values
         self.assertRaises(lib_exc.Conflict,
-                          self.client.update_image,
-                          orig_image['id'], [
-                              dict(add='/locations/-', value=new_loc)])
+                          self._update_image_with_retries,
+                          orig_image['id'],
+                          [dict(add='/locations/-', value=new_loc)])
 
         # Make sure nothing has changed on our image after all the
         # above failures
diff --git a/zuul.d/integrated-gate.yaml b/zuul.d/integrated-gate.yaml
index 32c017a..f1e6c01 100644
--- a/zuul.d/integrated-gate.yaml
+++ b/zuul.d/integrated-gate.yaml
@@ -73,7 +73,11 @@
     parent: devstack-tempest
     # This job version is with swift enabled on py3
     # as swift is ready on py3 from stable/ussuri onwards.
-    branches: ^(?!stable/(ocata|pike|queens|rocky|stein|train)).*$
+    # As this use 'integrated-full' tox env which is not
+    # available in old tempest used till stable/wallaby,
+    # this job definition is only for stable/xena onwards
+    # and separate job definition until stable/wallaby
+    branches: ^(?!stable/(ocata|pike|queens|rocky|stein|train|ussuri|victoria|wallaby)).*$
     description: |
       Base integration test with Neutron networking, horizon, swift enable,
       and py3.
@@ -406,20 +410,20 @@
         - tempest-integrated-networking
         # Do not run it on ussuri until below issue is fixed
         # https://storyboard.openstack.org/#!/story/2010057
-        # and job is broken on wallaby branch due to the issue
+        # and job is broken up to wallaby branch due to the issue
         # described in https://review.opendev.org/872341
         - openstacksdk-functional-devstack:
-            branches: ^(?!stable/(ussuri|wallaby)).*$
+            branches: ^(?!stable/(ussuri|victoria|wallaby)).*$
     gate:
       jobs:
         - grenade
         - tempest-integrated-networking
         # Do not run it on ussuri until below issue is fixed
         # https://storyboard.openstack.org/#!/story/2010057
-        # and job is broken on wallaby branch due to the issue
+        # and job is broken up to wallaby branch due to the issue
         # described in https://review.opendev.org/872341
         - openstacksdk-functional-devstack:
-            branches: ^(?!stable/(ussuri|wallaby)).*$
+            branches: ^(?!stable/(ussuri|victoria|wallaby)).*$
 
 - project-template:
     name: integrated-gate-compute
@@ -443,15 +447,15 @@
             branches: ^stable/(wallaby|xena|yoga).*$
         # Do not run it on ussuri until below issue is fixed
         # https://storyboard.openstack.org/#!/story/2010057
-        # and job is broken on wallaby branch due to the issue
+        # and job is broken up to wallaby branch due to the issue
         # described in https://review.opendev.org/872341
         - openstacksdk-functional-devstack:
-            branches: ^(?!stable/(ussuri|wallaby)).*$
+            branches: ^(?!stable/(ussuri|victoria|wallaby)).*$
     gate:
       jobs:
         - tempest-integrated-compute
         - openstacksdk-functional-devstack:
-            branches: ^(?!stable/(ussuri|wallaby)).*$
+            branches: ^(?!stable/(ussuri|victoria|wallaby)).*$
     periodic-weekly:
       jobs:
         # centos-9-stream is tested from zed release onwards
@@ -473,20 +477,20 @@
         - tempest-integrated-placement
         # Do not run it on ussuri until below issue is fixed
         # https://storyboard.openstack.org/#!/story/2010057
-        # and job is broken on wallaby branch due to the issue
+        # and job is broken up to wallaby branch due to the issue
         # described in https://review.opendev.org/872341
         - openstacksdk-functional-devstack:
-            branches: ^(?!stable/ussuri).*$
+            branches: ^(?!stable/(ussuri|victoria|wallaby)).*$
     gate:
       jobs:
         - grenade
         - tempest-integrated-placement
         # Do not run it on ussuri until below issue is fixed
         # https://storyboard.openstack.org/#!/story/2010057
-        # and job is broken on wallaby branch due to the issue
+        # and job is broken up to wallaby branch due to the issue
         # described in https://review.opendev.org/872341
         - openstacksdk-functional-devstack:
-            branches: ^(?!stable/(ussuri|wallaby)).*$
+            branches: ^(?!stable/(ussuri|victoria|wallaby)).*$
 
 - project-template:
     name: integrated-gate-storage
@@ -503,20 +507,20 @@
         - tempest-integrated-storage
         # Do not run it on ussuri until below issue is fixed
         # https://storyboard.openstack.org/#!/story/2010057
-        # and job is broken on wallaby branch due to the issue
+        # and job is broken up to wallaby branch due to the issue
         # described in https://review.opendev.org/872341
         - openstacksdk-functional-devstack:
-            branches: ^(?!stable/(ussuri|wallaby)).*$
+            branches: ^(?!stable/(ussuri|victoria|wallaby)).*$
     gate:
       jobs:
         - grenade
         - tempest-integrated-storage
         # Do not run it on ussuri until below issue is fixed
         # https://storyboard.openstack.org/#!/story/2010057
-        # and job is broken on wallaby branch due to the issue
+        # and job is broken up to wallaby branch due to the issue
         # described in https://review.opendev.org/872341
         - openstacksdk-functional-devstack:
-            branches: ^(?!stable/(ussuri|wallaby)).*$
+            branches: ^(?!stable/(ussuri|victoria|wallaby)).*$
 
 - project-template:
     name: integrated-gate-object-storage
@@ -531,17 +535,17 @@
         - tempest-integrated-object-storage
         # Do not run it on ussuri until below issue is fixed
         # https://storyboard.openstack.org/#!/story/2010057
-        # and job is broken on wallaby branch due to the issue
+        # and job is broken up to wallaby branch due to the issue
         # described in https://review.opendev.org/872341
         - openstacksdk-functional-devstack:
-            branches: ^(?!stable/(ussuri|wallaby)).*$
+            branches: ^(?!stable/(ussuri|victoria|wallaby)).*$
     gate:
       jobs:
         - grenade
         - tempest-integrated-object-storage
         # Do not run it on ussuri until below issue is fixed
         # https://storyboard.openstack.org/#!/story/2010057
-        # and job is broken on wallaby branch due to the issue
+        # and job is broken up to wallaby branch due to the issue
         # described in https://review.opendev.org/872341
         - openstacksdk-functional-devstack:
-            branches: ^(?!stable/(ussuri|wallaby)).*$
+            branches: ^(?!stable/(ussuri|victoria|wallaby)).*$
diff --git a/zuul.d/stable-jobs.yaml b/zuul.d/stable-jobs.yaml
index f70e79c..8aeb748 100644
--- a/zuul.d/stable-jobs.yaml
+++ b/zuul.d/stable-jobs.yaml
@@ -56,6 +56,36 @@
 - job:
     name: tempest-full-py3
     parent: devstack-tempest
+    # This job version is to use the 'full' tox env which
+    # is available for stable/ussuri to stable/wallaby also.
+    branches:
+      - stable/ussuri
+      - stable/victoria
+      - stable/wallaby
+    description: |
+      Base integration test with Neutron networking, horizon, swift enable,
+      and py3.
+      Former names for this job where:
+        * legacy-tempest-dsvm-py35
+        * gate-tempest-dsvm-py35
+    required-projects:
+      - openstack/horizon
+    vars:
+      tox_envlist: full
+      devstack_localrc:
+        USE_PYTHON3: true
+        FORCE_CONFIG_DRIVE: true
+        ENABLE_VOLUME_MULTIATTACH: true
+        GLANCE_USE_IMPORT_WORKFLOW: True
+      devstack_plugins:
+        neutron: https://opendev.org/openstack/neutron
+      devstack_services:
+        # Enbale horizon so that we can run horizon test.
+        horizon: true
+
+- job:
+    name: tempest-full-py3
+    parent: devstack-tempest
     # This job version is with swift disabled on py3
     # as swift was not ready on py3 until stable/train.
     branches: