Merge "Revert "Revert "Mark "test_live_migration_with_trunk" as unstable"""
diff --git a/tempest/api/compute/servers/test_server_actions.py b/tempest/api/compute/servers/test_server_actions.py
index e74ff18..af58433 100644
--- a/tempest/api/compute/servers/test_server_actions.py
+++ b/tempest/api/compute/servers/test_server_actions.py
@@ -816,3 +816,118 @@
                                           backup_type='daily',
                                           rotation=2,
                                           name=backup1)
+
+
+class ServerActionsV293TestJSON(base.BaseV2ComputeTest):
+
+    min_microversion = '2.93'
+    volume_min_microversion = '3.68'
+
+    @classmethod
+    def setup_credentials(cls):
+        cls.prepare_instance_network()
+        super(ServerActionsV293TestJSON, cls).setup_credentials()
+
+    @classmethod
+    def resource_setup(cls):
+        super(ServerActionsV293TestJSON, cls).resource_setup()
+        cls.server_id = cls.recreate_server(None, validatable=True)
+
+    @utils.services('volume')
+    @decorators.idempotent_id('6652dab9-ea24-4c93-ab5a-93d79c3041cf')
+    def test_rebuild_volume_backed_server(self):
+        """Test rebuilding a volume backed server"""
+        # We have to create a new server that is volume-backed since the one
+        # from setUp is not volume-backed.
+        kwargs = {'volume_backed': True,
+                  'wait_until': 'ACTIVE'}
+        validation_resources = {}
+        if CONF.validation.run_validation:
+            validation_resources = self.get_test_validation_resources(
+                self.os_primary)
+            kwargs.update({'validatable': True,
+                           'validation_resources': validation_resources})
+        server = self.create_test_server(**kwargs)
+        server = self.servers_client.show_server(server['id'])['server']
+        self.addCleanup(self.delete_server, server['id'])
+        volume_id = server['os-extended-volumes:volumes_attached'][0]['id']
+        volume_before_rebuild = self.volumes_client.show_volume(volume_id)
+        image_before_rebuild = (
+            volume_before_rebuild['volume']
+            ['volume_image_metadata']['image_id'])
+        # Verify that image inside volume is our initial image before rebuild
+        self.assertEqual(self.image_ref, image_before_rebuild)
+
+        # Authentication is attempted in the following order of priority:
+        # 1.The key passed in, if one was passed in.
+        # 2.Any key we can find through an SSH agent (if allowed).
+        # 3.Any "id_rsa", "id_dsa" or "id_ecdsa" key discoverable in
+        #   ~/.ssh/ (if allowed).
+        # 4.Plain username/password auth, if a password was given.
+        linux_client = remote_client.RemoteClient(
+            self.get_server_ip(server, validation_resources),
+            self.ssh_user,
+            password=None,
+            pkey=validation_resources['keypair']['private_key'],
+            server=server,
+            servers_client=self.servers_client)
+        output = linux_client.exec_command('touch test_file')
+        # No output means success
+        self.assertEqual('', output.strip())
+
+        # The server should be rebuilt using the provided image and data
+        meta = {'rebuild': 'server'}
+        new_name = data_utils.rand_name(self.__class__.__name__ + '-server')
+        password = 'rebuildPassw0rd'
+        rebuilt_server = self.servers_client.rebuild_server(
+            server['id'],
+            self.image_ref_alt,
+            name=new_name,
+            metadata=meta,
+            adminPass=password)['server']
+
+        # Verify the properties in the initial response are correct
+        self.assertEqual(server['id'], rebuilt_server['id'])
+        rebuilt_image_id = rebuilt_server['image']
+        # Since it is a volume backed server, image id will remain empty
+        self.assertEqual('', rebuilt_image_id)
+        self.assert_flavor_equal(self.flavor_ref, rebuilt_server['flavor'])
+
+        # Verify the server properties after the rebuild completes
+        waiters.wait_for_server_status(self.servers_client,
+                                       rebuilt_server['id'], 'ACTIVE')
+        server = self.servers_client.show_server(
+            rebuilt_server['id'])['server']
+        volume_id = server['os-extended-volumes:volumes_attached'][0]['id']
+        volume_after_rebuild = self.volumes_client.show_volume(volume_id)
+        image_after_rebuild = (
+            volume_after_rebuild['volume']
+            ['volume_image_metadata']['image_id'])
+
+        self.assertEqual(new_name, server['name'])
+        # Verify that volume ID remains same before and after rebuild
+        self.assertEqual(volume_before_rebuild['volume']['id'],
+                         volume_after_rebuild['volume']['id'])
+        # Verify that image inside volume is our final image after rebuild
+        self.assertEqual(self.image_ref_alt, image_after_rebuild)
+
+        # Authentication is attempted in the following order of priority:
+        # 1.The key passed in, if one was passed in.
+        # 2.Any key we can find through an SSH agent (if allowed).
+        # 3.Any "id_rsa", "id_dsa" or "id_ecdsa" key discoverable in
+        #   ~/.ssh/ (if allowed).
+        # 4.Plain username/password auth, if a password was given.
+        linux_client = remote_client.RemoteClient(
+            self.get_server_ip(rebuilt_server, validation_resources),
+            self.ssh_alt_user,
+            password,
+            validation_resources['keypair']['private_key'],
+            server=rebuilt_server,
+            servers_client=self.servers_client)
+        linux_client.validate_authentication()
+        e = self.assertRaises(lib_exc.SSHExecCommandFailed,
+                              linux_client.exec_command,
+                              'cat test_file')
+        # If we rebuilt the boot volume, then we should not find
+        # the file we touched.
+        self.assertIn('No such file or directory', str(e))
diff --git a/tempest/api/image/v2/admin/test_images.py b/tempest/api/image/v2/admin/test_images.py
index a77b2f2..ce50c5d 100644
--- a/tempest/api/image/v2/admin/test_images.py
+++ b/tempest/api/image/v2/admin/test_images.py
@@ -60,6 +60,24 @@
         self.assertNotEqual(created_image_info['owner'],
                             updated_image_info['owner'])
 
+    @decorators.idempotent_id('f6ab4aa0-035e-4664-9f2d-c57c6df50605')
+    def test_list_public_image(self):
+        """Test create image as admin and list public image as none admin"""
+        name = data_utils.rand_name(self.__class__.__name__ + '-Image')
+        image = self.admin_client.create_image(
+            name=name,
+            container_format='bare',
+            visibility='public',
+            disk_format='raw')
+        waiters.wait_for_image_status(self.admin_client, image['id'], 'queued')
+        created_image = self.admin_client.show_image(image['id'])
+        self.assertEqual(image['id'], created_image['id'])
+        self.addCleanup(self.admin_client.delete_image, image['id'])
+
+        images_list = self.client.list_images()['images']
+        fetched_images_id = [img['id'] for img in images_list]
+        self.assertIn(image['id'], fetched_images_id)
+
 
 class ImportCopyImagesTest(base.BaseV2ImageAdminTest):
     """Test the import copy-image operations"""
diff --git a/tempest/api/image/v2/test_images.py b/tempest/api/image/v2/test_images.py
index fecd5a7..977ad82 100644
--- a/tempest/api/image/v2/test_images.py
+++ b/tempest/api/image/v2/test_images.py
@@ -22,6 +22,7 @@
 from tempest.common import waiters
 from tempest import config
 from tempest.lib.common.utils import data_utils
+from tempest.lib.common.utils import test_utils
 from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
 
@@ -733,6 +734,30 @@
         body = self.schemas_client.show_schema(schema)
         self.assertEqual("images", body['name'])
 
+    @decorators.idempotent_id('d43f3efc-da4c-4af9-b636-868f0c6acedb')
+    def test_list_hidden_image(self):
+        image = self.client.create_image(os_hidden=True)
+        image = image['image'] if 'image' in image else image
+        self.addCleanup(self.client.wait_for_resource_deletion, image['id'])
+        self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+                        self.client.delete_image, image['id'])
+        images_list = self.client.list_images()['images']
+        fetched_images_id = [img['id'] for img in images_list]
+        self.assertNotIn(image['id'], fetched_images_id)
+
+    @decorators.idempotent_id('fdb96b81-257b-42ac-978b-ddeefa3760e4')
+    def test_list_update_hidden_image(self):
+        image = self.create_image()
+        images_list = self.client.list_images()['images']
+        fetched_images_id = [img['id'] for img in images_list]
+        self.assertIn(image['id'], fetched_images_id)
+
+        self.client.update_image(image['id'],
+                                 [dict(replace='/os_hidden', value=True)])
+        images_list = self.client.list_images()['images']
+        fetched_images_id = [img['id'] for img in images_list]
+        self.assertNotIn(image['id'], fetched_images_id)
+
 
 class ListSharedImagesTest(base.BaseV2ImageTest):
     """Here we test the listing of a shared image information"""
diff --git a/tempest/scenario/test_network_advanced_server_ops.py b/tempest/scenario/test_network_advanced_server_ops.py
index e6c6eb6..2c7c085 100644
--- a/tempest/scenario/test_network_advanced_server_ops.py
+++ b/tempest/scenario/test_network_advanced_server_ops.py
@@ -270,6 +270,11 @@
         new_host = self.get_host_for_server(server['id'])
         self.assertNotEqual(old_host, new_host, 'Server did not migrate')
 
+        # we first wait until the VM replies pings again, then check the
+        # network downtime
+        self._wait_server_status_and_check_network_connectivity(
+            server, keypair, floating_ip)
+
         downtime = downtime_meter.get_downtime()
         self.assertIsNotNone(downtime)
         LOG.debug("Downtime seconds measured with downtime_meter = %r",
@@ -280,9 +285,6 @@
             "Downtime of {} seconds is higher than expected '{}'".format(
                 downtime, allowed_downtime))
 
-        self._wait_server_status_and_check_network_connectivity(
-            server, keypair, floating_ip)
-
     @decorators.idempotent_id('25b188d7-0183-4b1e-a11d-15840c8e2fd6')
     @testtools.skipUnless(CONF.compute_feature_enabled.cold_migration,
                           'Cold migration is not available.')
diff --git a/zuul.d/base.yaml b/zuul.d/base.yaml
index 2d978c0..0ac893a 100644
--- a/zuul.d/base.yaml
+++ b/zuul.d/base.yaml
@@ -13,6 +13,8 @@
     roles: &base_roles
       - zuul: opendev.org/openstack/devstack
     vars: &base_vars
+      devstack_localrc:
+        IMAGE_URLS: http://download.cirros-cloud.net/0.6.2/cirros-0.6.2-x86_64-disk.img, http://download.cirros-cloud.net/0.6.1/cirros-0.6.1-x86_64-disk.img
       devstack_services:
         tempest: true
       devstack_local_conf:
diff --git a/zuul.d/integrated-gate.yaml b/zuul.d/integrated-gate.yaml
index ec5e9af..9197e64 100644
--- a/zuul.d/integrated-gate.yaml
+++ b/zuul.d/integrated-gate.yaml
@@ -276,7 +276,7 @@
     timeout: 10800
     # This job runs on stable/stein onwards.
     branches: ^(?!stable/(ocata|pike|queens|rocky)).*$
-    vars: &tempest_slow_vars
+    vars:
       tox_envlist: slow-serial
       devstack_localrc:
         CINDER_ENABLED_BACKENDS: lvm:lvmdriver-1,lvm:lvmdriver-2
@@ -286,7 +286,6 @@
       devstack_services:
         neutron-placement: true
         neutron-qos: true
-      tempest_concurrency: 2
     group-vars:
       # NOTE(mriedem): The ENABLE_VOLUME_MULTIATTACH variable is used on both
       # the controller and subnode prior to Rocky so we have to make sure the
@@ -302,16 +301,23 @@
     # as swift is ready on py3 from stable/ussuri onwards.
     timeout: 10800
     branches: ^(?!stable/(ocata|pike|queens|rocky|stein|train)).*$
-    vars: *tempest_slow_vars
-
-- job:
-    name: tempest-slow-parallel
-    parent: tempest-slow-py3
-    # This job run slow tests in parallel.
     vars:
       tox_envlist: slow
       devstack_localrc:
-        MYSQL_REDUCE_MEMORY: true
+        CINDER_ENABLED_BACKENDS: lvm:lvmdriver-1,lvm:lvmdriver-2
+        ENABLE_VOLUME_MULTIATTACH: true
+      devstack_plugins:
+        neutron: https://opendev.org/openstack/neutron
+      devstack_services:
+        neutron-placement: true
+        neutron-qos: true
+    group-vars:
+      # NOTE(mriedem): The ENABLE_VOLUME_MULTIATTACH variable is used on both
+      # the controller and subnode prior to Rocky so we have to make sure the
+      # variable is set in both locations.
+      subnode:
+        devstack_localrc:
+          ENABLE_VOLUME_MULTIATTACH: true
 
 - job:
     name: tempest-cinder-v2-api
diff --git a/zuul.d/project.yaml b/zuul.d/project.yaml
index 6e1ba5e..3223a1e 100644
--- a/zuul.d/project.yaml
+++ b/zuul.d/project.yaml
@@ -157,7 +157,6 @@
             irrelevant-files: *tempest-irrelevant-files
         - tempest-all:
             irrelevant-files: *tempest-irrelevant-files
-        - tempest-slow-parallel
         - tempest-full-parallel
         - tempest-full-zed-extra-tests
         - tempest-full-yoga-extra-tests
@@ -192,7 +191,6 @@
     periodic:
       jobs:
         - tempest-all
-        - tempest-slow-parallel
         - tempest-full-parallel
         - tempest-full-oslo-master
         - tempest-stestr-master
diff --git a/zuul.d/stable-jobs.yaml b/zuul.d/stable-jobs.yaml
index 0aa1aac..89435ce 100644
--- a/zuul.d/stable-jobs.yaml
+++ b/zuul.d/stable-jobs.yaml
@@ -276,7 +276,6 @@
       devstack_services:
         neutron-placement: true
         neutron-qos: true
-      tempest_concurrency: 2
     group-vars:
       # NOTE(mriedem): The ENABLE_VOLUME_MULTIATTACH variable is used on both
       # the controller and subnode prior to Rocky so we have to make sure the