Merge "Remove misleading arguments"
diff --git a/README.rst b/README.rst
index 3c0463b..f1dac1c 100644
--- a/README.rst
+++ b/README.rst
@@ -92,18 +92,18 @@
    be done using the :ref:`tempest_run` command. This can be done by either
    running::
 
-     $ tempest run
+    $ tempest run
 
    from the Tempest workspace directory. Or you can use the ``--workspace``
    argument to run in the workspace you created regarless of your current
    working directory. For example::
 
-     $ tempest run --workspace cloud-01
+    $ tempest run --workspace cloud-01
 
    There is also the option to use testr directly, or any `testr`_ based test
    runner, like `ostestr`_. For example, from the workspace dir run::
 
-     $ ostestr --regex '(?!.*\[.*\bslow\b.*\])(^tempest\.(api|scenario))'
+    $ ostestr --regex '(?!.*\[.*\bslow\b.*\])(^tempest\.(api|scenario))'
 
    will run the same set of tests as the default gate jobs.
 
@@ -161,9 +161,9 @@
 of the configuration.
 
 You can generate a new sample tempest.conf file, run the following
-command from the top level of the Tempest directory:
+command from the top level of the Tempest directory::
 
-  tox -egenconfig
+    $ tox -egenconfig
 
 The most important pieces that are needed are the user ids, openstack
 endpoint, and basic flavors and images needed to run tests.
@@ -257,11 +257,11 @@
 and run the tests or use tox to do the same. Tox also contains several existing
 job configurations. For example::
 
-   $ tox -efull
+    $ tox -efull
 
 which will run the same set of tests as the OpenStack gate. (it's exactly how
 the gate invokes Tempest) Or::
 
-  $ tox -esmoke
+    $ tox -esmoke
 
 to run the tests tagged as smoke.
diff --git a/releasenotes/source/index.rst b/releasenotes/source/index.rst
index 2c22408..0ec0e94 100644
--- a/releasenotes/source/index.rst
+++ b/releasenotes/source/index.rst
@@ -5,10 +5,10 @@
  .. toctree::
     :maxdepth: 1
 
+    unreleased
     v12.0.0
     v11.0.0
     v10.0.0
-    unreleased
 
 Indices and tables
 ==================
diff --git a/tempest/api/compute/admin/test_migrations.py b/tempest/api/compute/admin/test_migrations.py
index 6113c04..62dbfe4 100644
--- a/tempest/api/compute/admin/test_migrations.py
+++ b/tempest/api/compute/admin/test_migrations.py
@@ -31,6 +31,8 @@
         super(MigrationsAdminTest, cls).setup_clients()
         cls.client = cls.os_adm.migrations_client
         cls.flavors_admin_client = cls.os_adm.flavors_client
+        cls.admin_hosts_client = cls.os_adm.hosts_client
+        cls.admin_servers_client = cls.os_adm.servers_client
 
     @test.idempotent_id('75c0b83d-72a0-4cf8-a153-631e83e7d53f')
     def test_list_migrations(self):
@@ -103,3 +105,28 @@
 
         server = self.servers_client.show_server(server['id'])['server']
         self.assertEqual(flavor['id'], server['flavor']['id'])
+
+    @test.idempotent_id('4bf0be52-3b6f-4746-9a27-3143636fe30d')
+    @testtools.skipUnless(CONF.compute_feature_enabled.cold_migration,
+                          'Cold migration not available.')
+    def test_cold_migration(self):
+        if CONF.compute.min_compute_nodes < 2:
+            msg = "Less than 2 compute nodes, skipping multinode tests."
+            raise self.skipException(msg)
+
+        server = self.create_test_server(wait_until="ACTIVE")
+        src_host = self.admin_servers_client.show_server(
+            server['id'])['server']['OS-EXT-SRV-ATTR:host']
+
+        self.admin_servers_client.migrate_server(server['id'])
+
+        waiters.wait_for_server_status(self.servers_client,
+                                       server['id'], 'VERIFY_RESIZE')
+
+        self.servers_client.confirm_resize_server(server['id'])
+        waiters.wait_for_server_status(self.servers_client,
+                                       server['id'], 'ACTIVE')
+        dst_host = self.admin_servers_client.show_server(
+            server['id'])['server']['OS-EXT-SRV-ATTR:host']
+
+        self.assertNotEqual(src_host, dst_host)
diff --git a/tempest/api/compute/admin/test_servers.py b/tempest/api/compute/admin/test_servers.py
index aabb40c..c9ffcca 100755
--- a/tempest/api/compute/admin/test_servers.py
+++ b/tempest/api/compute/admin/test_servers.py
@@ -102,14 +102,18 @@
         params = {'tenant_id': tenant_id}
         body = self.client.list_servers(detail=True, **params)
         servers = body['servers']
-        self.assertEqual([], servers)
+        servers_name = map(lambda x: x['name'], servers)
+        self.assertNotIn(self.s1_name, servers_name)
+        self.assertNotIn(self.s2_name, servers_name)
 
-        # List the admin tenant which has no servers
+        # List the admin tenant shouldn't get servers created by other tenants
         admin_tenant_id = self.client.tenant_id
         params = {'all_tenants': '', 'tenant_id': admin_tenant_id}
         body = self.client.list_servers(detail=True, **params)
         servers = body['servers']
-        self.assertEqual([], servers)
+        servers_name = map(lambda x: x['name'], servers)
+        self.assertNotIn(self.s1_name, servers_name)
+        self.assertNotIn(self.s2_name, servers_name)
 
     @test.idempotent_id('86c7a8f7-50cf-43a9-9bac-5b985317134f')
     def test_list_servers_filter_by_exist_host(self):
diff --git a/tempest/api/volume/test_volume_metadata.py b/tempest/api/volume/test_volume_metadata.py
index e529538..ee1744d 100644
--- a/tempest/api/volume/test_volume_metadata.py
+++ b/tempest/api/volume/test_volume_metadata.py
@@ -26,11 +26,10 @@
         super(VolumesV2MetadataTest, cls).resource_setup()
         # Create a volume
         cls.volume = cls.create_volume()
-        cls.volume_id = cls.volume['id']
 
     def tearDown(self):
         # Update the metadata to {}
-        self.volumes_client.update_volume_metadata(self.volume_id, {})
+        self.volumes_client.update_volume_metadata(self.volume['id'], {})
         super(VolumesV2MetadataTest, self).tearDown()
 
     @test.idempotent_id('6f5b125b-f664-44bf-910f-751591fe5769')
@@ -41,17 +40,17 @@
                     "key3": "value3",
                     "key4": "<value&special_chars>"}
 
-        body = self.volumes_client.create_volume_metadata(self.volume_id,
+        body = self.volumes_client.create_volume_metadata(self.volume['id'],
                                                           metadata)['metadata']
         # Get the metadata of the volume
         body = self.volumes_client.show_volume_metadata(
-            self.volume_id)['metadata']
+            self.volume['id'])['metadata']
         self.assertThat(body.items(), matchers.ContainsAll(metadata.items()))
         # Delete one item metadata of the volume
         self.volumes_client.delete_volume_metadata_item(
-            self.volume_id, "key1")
+            self.volume['id'], "key1")
         body = self.volumes_client.show_volume_metadata(
-            self.volume_id)['metadata']
+            self.volume['id'])['metadata']
         self.assertNotIn("key1", body)
         del metadata["key1"]
         self.assertThat(body.items(), matchers.ContainsAll(metadata.items()))
@@ -68,17 +67,17 @@
 
         # Create metadata for the volume
         body = self.volumes_client.create_volume_metadata(
-            self.volume_id, metadata)['metadata']
+            self.volume['id'], metadata)['metadata']
         # Get the metadata of the volume
         body = self.volumes_client.show_volume_metadata(
-            self.volume_id)['metadata']
+            self.volume['id'])['metadata']
         self.assertThat(body.items(), matchers.ContainsAll(metadata.items()))
         # Update metadata
         body = self.volumes_client.update_volume_metadata(
-            self.volume_id, update)['metadata']
+            self.volume['id'], update)['metadata']
         # Get the metadata of the volume
         body = self.volumes_client.show_volume_metadata(
-            self.volume_id)['metadata']
+            self.volume['id'])['metadata']
         self.assertEqual(update, body)
 
     @test.idempotent_id('862261c5-8df4-475a-8c21-946e50e36a20')
@@ -93,14 +92,14 @@
                   "key3": "value3_update"}
         # Create metadata for the volume
         body = self.volumes_client.create_volume_metadata(
-            self.volume_id, metadata)['metadata']
+            self.volume['id'], metadata)['metadata']
         self.assertThat(body.items(), matchers.ContainsAll(metadata.items()))
         # Update metadata item
         body = self.volumes_client.update_volume_metadata_item(
-            self.volume_id, "key3", update_item)['meta']
+            self.volume['id'], "key3", update_item)['meta']
         # Get the metadata of the volume
         body = self.volumes_client.show_volume_metadata(
-            self.volume_id)['metadata']
+            self.volume['id'])['metadata']
         self.assertThat(body.items(), matchers.ContainsAll(expect.items()))
 
 
diff --git a/tempest/clients.py b/tempest/clients.py
index b13b809..edc34bd 100644
--- a/tempest/clients.py
+++ b/tempest/clients.py
@@ -117,7 +117,7 @@
                     configuration[service_for_config] = (
                         config.service_client_config(service_for_config))
             except lib_exc.UnknownServiceClient:
-                LOG.warn(
+                LOG.warning(
                     'Could not load configuration for service %s' % service)
 
         return configuration
diff --git a/tempest/cmd/run.py b/tempest/cmd/run.py
index fef836c..236953c 100644
--- a/tempest/cmd/run.py
+++ b/tempest/cmd/run.py
@@ -264,8 +264,8 @@
 
             run_thread = threading.Thread(target=run_argv_thread)
             run_thread.start()
-            returncodes['subunit-trace'] = subunit_trace.trace(subunit_r,
-                                                               sys.stdout)
+            returncodes['subunit-trace'] = subunit_trace.trace(
+                subunit_r, sys.stdout, post_fails=True, print_failures=True)
             run_thread.join()
             subunit_r.close()
             # python version of pipefail
diff --git a/tempest/config.py b/tempest/config.py
index f6c89ae..b6fca7e 100644
--- a/tempest/config.py
+++ b/tempest/config.py
@@ -339,6 +339,10 @@
     cfg.BoolOpt('suspend',
                 default=True,
                 help="Does the test environment support suspend/resume?"),
+    cfg.BoolOpt('cold_migration',
+                default=True,
+                help="Does the test environment support cold migration "
+                     "available?"),
     cfg.BoolOpt('live_migration',
                 default=True,
                 help="Does the test environment support live migration "
diff --git a/tempest/scenario/test_minimum_basic.py b/tempest/scenario/test_minimum_basic.py
index 34a65cb..3ac6759 100644
--- a/tempest/scenario/test_minimum_basic.py
+++ b/tempest/scenario/test_minimum_basic.py
@@ -149,10 +149,18 @@
 
         # delete the floating IP, this should refresh the server addresses
         self.compute_floating_ips_client.delete_floating_ip(floating_ip['id'])
-        server = self.servers_client.show_server(server['id'])['server']
-        address = self._get_floating_ip_in_server_addresses(
-            floating_ip, server)
-        self.assertIsNone(
-            address,
-            "Floating IP '%s' should not be in server addresses: %s" %
-            (floating_ip['ip'], server['addresses']))
+
+        def is_floating_ip_detached_from_server():
+            server_info = self.servers_client.show_server(
+                server['id'])['server']
+            address = self._get_floating_ip_in_server_addresses(
+                floating_ip, server_info)
+            return (not address)
+
+        if not test_utils.call_until_true(
+            is_floating_ip_detached_from_server,
+            CONF.compute.build_timeout,
+            CONF.compute.build_interval):
+            msg = ("Floating IP '%s' should not be in server addresses: %s" %
+                   (floating_ip['ip'], server['addresses']))
+            raise exceptions.TimeoutException(msg)
diff --git a/test-requirements.txt b/test-requirements.txt
index 04c3d6d..567cf20 100644
--- a/test-requirements.txt
+++ b/test-requirements.txt
@@ -5,7 +5,7 @@
 # needed for doc build
 sphinx!=1.3b1,<1.3,>=1.2.1 # BSD
 python-subunit>=0.0.18 # Apache-2.0/BSD
-oslosphinx!=3.4.0,>=2.5.0 # Apache-2.0
+oslosphinx>=4.7.0 # Apache-2.0
 reno>=1.8.0 # Apache2
 mock>=2.0 # BSD
 coverage>=3.6 # Apache-2.0