Add negative test for live migration

No negative test exists to check for conflict response code when live
migration fails for that reason.  Add new negative test for live
migration of VM in suspended state to trigger conflict response code.

Jenkins job tempest-dsvm-neutron-scenario-multinode-lvm-multibackend
gate uses tempest regex that does not pick up the live migration
negative test file with old file name:

DEVSTACK_GATE_TEMPEST_REGEX=
'(^tempest\.(scenario|api\.compute\.admin\.test_(live_|)migration))'

Rename negative live migration file so that it gets picked up by multi
node gate jenkins job.

Change-Id: I1bb9895d99fbc7feca7335df24f2305e261dbb10
diff --git a/tempest/api/compute/admin/test_live_migration.py b/tempest/api/compute/admin/test_live_migration.py
index 3859e64..705e567 100644
--- a/tempest/api/compute/admin/test_live_migration.py
+++ b/tempest/api/compute/admin/test_live_migration.py
@@ -29,13 +29,13 @@
 LOG = logging.getLogger(__name__)
 
 
-class LiveBlockMigrationTestJSON(base.BaseV2ComputeAdminTest):
+class LiveMigrationTest(base.BaseV2ComputeAdminTest):
     max_microversion = '2.24'
     block_migration = None
 
     @classmethod
     def skip_checks(cls):
-        super(LiveBlockMigrationTestJSON, cls).skip_checks()
+        super(LiveMigrationTest, cls).skip_checks()
 
         if not CONF.compute_feature_enabled.live_migration:
             skip_msg = ("%s skipped as live-migration is "
@@ -47,26 +47,10 @@
 
     @classmethod
     def setup_clients(cls):
-        super(LiveBlockMigrationTestJSON, cls).setup_clients()
+        super(LiveMigrationTest, cls).setup_clients()
         cls.admin_hosts_client = cls.os_admin.hosts_client
         cls.admin_migration_client = cls.os_admin.migrations_client
 
-    @classmethod
-    def _get_compute_hostnames(cls):
-        body = cls.admin_hosts_client.list_hosts()['hosts']
-        return [
-            host_record['host_name']
-            for host_record in body
-            if host_record['service'] == 'compute'
-        ]
-
-    def _get_server_details(self, server_id):
-        body = self.admin_servers_client.show_server(server_id)['server']
-        return body
-
-    def _get_host_for_server(self, server_id):
-        return self._get_server_details(server_id)['OS-EXT-SRV-ATTR:host']
-
     def _migrate_server_to(self, server_id, dest_host, volume_backed=False):
         kwargs = dict()
         block_migration = getattr(self, 'block_migration', None)
@@ -79,11 +63,6 @@
             server_id, host=dest_host, block_migration=block_migration,
             **kwargs)
 
-    def _get_host_other_than(self, host):
-        for target_host in self._get_compute_hostnames():
-            if host != target_host:
-                return target_host
-
     def _live_migrate(self, server_id, target_host, state,
                       volume_backed=False):
         self._migrate_server_to(server_id, target_host, volume_backed)
@@ -97,7 +76,7 @@
             if (live_migration['instance_uuid'] == server_id):
                 msg += "\n%s" % live_migration
         msg += "]"
-        self.assertEqual(target_host, self._get_host_for_server(server_id),
+        self.assertEqual(target_host, self.get_host_for_server(server_id),
                          msg)
 
     def _test_live_migration(self, state='ACTIVE', volume_backed=False):
@@ -114,8 +93,8 @@
         # Live migrate an instance to another host
         server_id = self.create_test_server(wait_until="ACTIVE",
                                             volume_backed=volume_backed)['id']
-        source_host = self._get_host_for_server(server_id)
-        destination_host = self._get_host_other_than(source_host)
+        source_host = self.get_host_for_server(server_id)
+        destination_host = self.get_host_other_than(server_id)
 
         if state == 'PAUSED':
             self.admin_servers_client.pause_server(server_id)
@@ -158,8 +137,7 @@
     def test_iscsi_volume(self):
         server = self.create_test_server(wait_until="ACTIVE")
         server_id = server['id']
-        actual_host = self._get_host_for_server(server_id)
-        target_host = self._get_host_other_than(actual_host)
+        target_host = self.get_host_other_than(server_id)
 
         volume = self.create_volume()
 
@@ -174,11 +152,11 @@
         server = self.admin_servers_client.show_server(server_id)['server']
         volume_id2 = server["os-extended-volumes:volumes_attached"][0]["id"]
 
-        self.assertEqual(target_host, self._get_host_for_server(server_id))
+        self.assertEqual(target_host, self.get_host_for_server(server_id))
         self.assertEqual(volume_id1, volume_id2)
 
 
-class LiveBlockMigrationRemoteConsolesV26TestJson(LiveBlockMigrationTestJSON):
+class LiveMigrationRemoteConsolesV26Test(LiveMigrationTest):
     min_microversion = '2.6'
     max_microversion = 'latest'
 
@@ -201,8 +179,8 @@
         hints = {'different_host': server01_id}
         server02_id = self.create_test_server(scheduler_hints=hints,
                                               wait_until='ACTIVE')['id']
-        host01_id = self._get_host_for_server(server01_id)
-        host02_id = self._get_host_for_server(server02_id)
+        host01_id = self.get_host_for_server(server01_id)
+        host02_id = self.get_host_for_server(server02_id)
         self.assertNotEqual(host01_id, host02_id)
 
         # At this step we have 2 instances on different hosts, both with
@@ -216,7 +194,7 @@
         self._migrate_server_to(server01_id, host02_id)
         waiters.wait_for_server_status(self.servers_client,
                                        server01_id, 'ACTIVE')
-        self.assertEqual(host02_id, self._get_host_for_server(server01_id))
+        self.assertEqual(host02_id, self.get_host_for_server(server01_id))
         self._verify_console_interaction(server01_id)
         # At this point, both instances have a valid serial console
         # connection, which means the ports got updated.
@@ -252,7 +230,7 @@
         self.assertIn(data, console_output)
 
 
-class LiveAutoBlockMigrationV225TestJSON(LiveBlockMigrationTestJSON):
+class LiveAutoBlockMigrationV225Test(LiveMigrationTest):
     min_microversion = '2.25'
     max_microversion = 'latest'
     block_migration = 'auto'
diff --git a/tempest/api/compute/admin/test_live_block_migration_negative.py b/tempest/api/compute/admin/test_live_migration_negative.py
similarity index 72%
rename from tempest/api/compute/admin/test_live_block_migration_negative.py
rename to tempest/api/compute/admin/test_live_migration_negative.py
index ab63154..deabbc2 100644
--- a/tempest/api/compute/admin/test_live_block_migration_negative.py
+++ b/tempest/api/compute/admin/test_live_migration_negative.py
@@ -23,10 +23,10 @@
 CONF = config.CONF
 
 
-class LiveBlockMigrationNegativeTestJSON(base.BaseV2ComputeAdminTest):
+class LiveMigrationNegativeTest(base.BaseV2ComputeAdminTest):
     @classmethod
     def skip_checks(cls):
-        super(LiveBlockMigrationNegativeTestJSON, cls).skip_checks()
+        super(LiveMigrationNegativeTest, cls).skip_checks()
         if not CONF.compute_feature_enabled.live_migration:
             raise cls.skipException("Live migration is not enabled")
 
@@ -47,3 +47,17 @@
                           server['id'], target_host)
         waiters.wait_for_server_status(self.servers_client, server['id'],
                                        'ACTIVE')
+
+    @decorators.attr(type=['negative'])
+    @decorators.idempotent_id('6e2f94f5-2ee8-4830-bef5-5bc95bb0795b')
+    def test_live_block_migration_suspended(self):
+        server = self.create_test_server(wait_until="ACTIVE")
+
+        self.admin_servers_client.suspend_server(server['id'])
+        waiters.wait_for_server_status(self.servers_client,
+                                       server['id'], 'SUSPENDED')
+
+        destination_host = self.get_host_other_than(server['id'])
+
+        self.assertRaises(lib_exc.Conflict, self._migrate_server_to,
+                          server['id'], destination_host)
diff --git a/tempest/api/compute/base.py b/tempest/api/compute/base.py
index 429ded5..56a976d 100644
--- a/tempest/api/compute/base.py
+++ b/tempest/api/compute/base.py
@@ -479,3 +479,21 @@
         self.addCleanup(client.wait_for_resource_deletion, flavor['id'])
         self.addCleanup(client.delete_flavor, flavor['id'])
         return flavor
+
+    def get_host_for_server(self, server_id):
+        server_details = self.admin_servers_client.show_server(server_id)
+        return server_details['server']['OS-EXT-SRV-ATTR:host']
+
+    def get_host_other_than(self, server_id):
+        source_host = self.get_host_for_server(server_id)
+
+        list_hosts_resp = self.os_admin.hosts_client.list_hosts()['hosts']
+        hosts = [
+            host_record['host_name']
+            for host_record in list_hosts_resp
+            if host_record['service'] == 'compute'
+        ]
+
+        for target_host in hosts:
+            if source_host != target_host:
+                return target_host