From eabce92ceea2493baf0d68e6fe6a264c7a573291 Mon Sep 17 00:00:00 2001 From: Tom Patzig Date: Wed, 29 Nov 2017 12:56:45 +0100 Subject: [PATCH] Do not use own function to find migration target The nova scenarios BootServerAttachCreatedVolumeAndLiveMigrate, BootServerFromVolumeAndLiveMigrate, BootAndLiveMigrateServer are using rally's own function to find a suitable target compute host for live migration. This function does not support all filters that are available and configured in nova. This function only filters computes on AZ level. For example it completely ignores flavor-aggregate mappings (AggregateInstanceExtraSpecsFilter). This leads to wrong target host selection and thus a failing live migration. This patch removes the function _find_host_to_migrate and the argument target_host that was given into the function _live_migrate. This leaves the target host selection completely up to nova, for live migration, which allows to benefit from the whole nova scheduler filters implementation, to find a suitable host. Change-Id: Ide64667a5e482b10b8935e9ebd7655c0004c6a0b Closes-Bug: #1734914 --- .../openstack/scenarios/nova/servers.py | 12 ++----- .../plugins/openstack/scenarios/nova/utils.py | 31 ++----------------- .../openstack/scenarios/nova/test_servers.py | 13 -------- .../openstack/scenarios/nova/test_utils.py | 27 ---------------- 4 files changed, 5 insertions(+), 78 deletions(-) diff --git a/rally/plugins/openstack/scenarios/nova/servers.py b/rally/plugins/openstack/scenarios/nova/servers.py index 223a0fe5..cb6d742f 100755 --- a/rally/plugins/openstack/scenarios/nova/servers.py +++ b/rally/plugins/openstack/scenarios/nova/servers.py @@ -717,9 +717,7 @@ class BootAndLiveMigrateServer(utils.NovaScenario): server = self._boot_server(image, flavor, **kwargs) self.sleep_between(min_sleep, max_sleep) - new_host = self._find_host_to_migrate(server) - self._live_migrate(server, new_host, - block_migration, disk_over_commit) + self._live_migrate(server, block_migration, disk_over_commit) self._delete_server(server) @@ -774,9 +772,7 @@ class BootServerFromVolumeAndLiveMigrate(utils.NovaScenario, **kwargs) self.sleep_between(min_sleep, max_sleep) - new_host = self._find_host_to_migrate(server) - self._live_migrate(server, new_host, - block_migration, disk_over_commit) + self._live_migrate(server, block_migration, disk_over_commit) self._delete_server(server, force=force_delete) @@ -832,9 +828,7 @@ class BootServerAttachCreatedVolumeAndLiveMigrate(utils.NovaScenario, self.sleep_between(min_sleep, max_sleep) - new_host = self._find_host_to_migrate(server) - self._live_migrate(server, new_host, - block_migration, disk_over_commit) + self._live_migrate(server, block_migration, disk_over_commit) self._detach_volume(server, volume) diff --git a/rally/plugins/openstack/scenarios/nova/utils.py b/rally/plugins/openstack/scenarios/nova/utils.py index ee83be4c..0ae03964 100644 --- a/rally/plugins/openstack/scenarios/nova/utils.py +++ b/rally/plugins/openstack/scenarios/nova/utils.py @@ -13,7 +13,6 @@ # License for the specific language governing permissions and limitations # under the License. -import random from oslo_config import cfg @@ -737,12 +736,11 @@ class NovaScenario(scenario.OpenStackScenario): ) @atomic.action_timer("nova.live_migrate") - def _live_migrate(self, server, target_host, block_migration=False, + def _live_migrate(self, server, block_migration=False, disk_over_commit=False, skip_host_check=False): """Run live migration of the given server. :param server: Server object - :param target_host: Specifies the target compute node to migrate :param block_migration: Specifies the migration type :param disk_over_commit: Specifies whether to overcommit migrated instance or not @@ -751,8 +749,7 @@ class NovaScenario(scenario.OpenStackScenario): """ server_admin = self.admin_clients("nova").servers.get(server.id) host_pre_migrate = getattr(server_admin, "OS-EXT-SRV-ATTR:host") - server_admin.live_migrate(target_host, - block_migration=block_migration, + server_admin.live_migrate(block_migration=block_migration, disk_over_commit=disk_over_commit) utils.wait_for_status( server, @@ -769,30 +766,6 @@ class NovaScenario(scenario.OpenStackScenario): "Live Migration failed: Migration complete " "but instance did not change host: %s" % host_pre_migrate) - @atomic.action_timer("nova.find_host_to_migrate") - def _find_host_to_migrate(self, server): - """Find a compute node for live migration. - - :param server: Server object - """ - server_admin = self.admin_clients("nova").servers.get(server.id) - host = getattr(server_admin, "OS-EXT-SRV-ATTR:host") - az_name = getattr(server_admin, "OS-EXT-AZ:availability_zone") - az = None - for a in self.admin_clients("nova").availability_zones.list(): - if az_name == a.zoneName: - az = a - break - try: - new_host = random.choice( - [key for key, value in az.hosts.items() - if key != host and - value.get("nova-compute", {}).get("available", False)]) - return new_host - except IndexError: - raise exceptions.RallyException( - "Live Migration failed: No valid host found to migrate") - @atomic.action_timer("nova.migrate") def _migrate(self, server, skip_host_check=False): """Run migration of the given server. diff --git a/tests/unit/plugins/openstack/scenarios/nova/test_servers.py b/tests/unit/plugins/openstack/scenarios/nova/test_servers.py index 7f090815..5e628b5f 100644 --- a/tests/unit/plugins/openstack/scenarios/nova/test_servers.py +++ b/tests/unit/plugins/openstack/scenarios/nova/test_servers.py @@ -705,8 +705,6 @@ class NovaServersTestCase(test.ScenarioTestCase): scenario.generate_random_name = mock.MagicMock(return_value="name") scenario._boot_server = mock.MagicMock(return_value=fake_server) scenario.sleep_between = mock.MagicMock() - scenario._find_host_to_migrate = mock.MagicMock( - return_value="host_name") scenario._live_migrate = mock.MagicMock() scenario._delete_server = mock.MagicMock() @@ -717,10 +715,7 @@ class NovaServersTestCase(test.ScenarioTestCase): scenario.sleep_between.assert_called_once_with(10, 20) - scenario._find_host_to_migrate.assert_called_once_with(fake_server) - scenario._live_migrate.assert_called_once_with(fake_server, - "host_name", False, False) scenario._delete_server.assert_called_once_with(fake_server) @@ -734,8 +729,6 @@ class NovaServersTestCase(test.ScenarioTestCase): scenario.generate_random_name = mock.MagicMock(return_value="name") scenario._boot_server = mock.MagicMock(return_value=fake_server) scenario.sleep_between = mock.MagicMock() - scenario._find_host_to_migrate = mock.MagicMock( - return_value="host_name") scenario._live_migrate = mock.MagicMock() scenario._delete_server = mock.MagicMock() @@ -757,10 +750,7 @@ class NovaServersTestCase(test.ScenarioTestCase): scenario.sleep_between.assert_called_once_with(10, 20) - scenario._find_host_to_migrate.assert_called_once_with(fake_server) - scenario._live_migrate.assert_called_once_with(fake_server, - "host_name", False, False) scenario._delete_server.assert_called_once_with(fake_server, force=False) @@ -784,8 +774,6 @@ class NovaServersTestCase(test.ScenarioTestCase): scenario.sleep_between = mock.MagicMock() - scenario._find_host_to_migrate = mock.MagicMock( - return_value="host_name") scenario._live_migrate = mock.MagicMock() scenario._boot_server = mock.MagicMock(return_value=fake_server) @@ -806,7 +794,6 @@ class NovaServersTestCase(test.ScenarioTestCase): fake_volume) scenario.sleep_between.assert_called_once_with(10, 20) scenario._live_migrate.assert_called_once_with(fake_server, - "host_name", False, False) cinder.delete_volume.assert_called_once_with(fake_volume) diff --git a/tests/unit/plugins/openstack/scenarios/nova/test_utils.py b/tests/unit/plugins/openstack/scenarios/nova/test_utils.py index 571feeb8..1294674c 100644 --- a/tests/unit/plugins/openstack/scenarios/nova/test_utils.py +++ b/tests/unit/plugins/openstack/scenarios/nova/test_utils.py @@ -649,11 +649,9 @@ class NovaScenarioTestCase(test.ScenarioTestCase): "nova.detach_volume") def test__live_migrate_server(self): - fake_host = mock.MagicMock() self.admin_clients("nova").servers.get(return_value=self.server) nova_scenario = utils.NovaScenario(context=self.context) nova_scenario._live_migrate(self.server, - fake_host, block_migration=False, disk_over_commit=False, skip_host_check=True) @@ -669,31 +667,6 @@ class NovaScenarioTestCase(test.ScenarioTestCase): self._test_atomic_action_timer(nova_scenario.atomic_actions(), "nova.live_migrate") - def test__find_host_to_migrate(self): - fake_server = self.server - fake_host = {"nova-compute": {"available": True}} - fake_host_compute_off = {"nova-compute": {"available": False}} - fake_host_no_compute = {"nova-conductor": {"available": True}} - self.admin_clients("nova").servers.get.return_value = fake_server - self.admin_clients("nova").availability_zones.list.return_value = [ - mock.MagicMock(zoneName="a", - hosts={"a1": fake_host, "a2": fake_host, - "a3": fake_host}), - mock.MagicMock(zoneName="b", - hosts={"b1": fake_host, "b2": fake_host, - "b3": fake_host, "b4": fake_host_compute_off, - "b5": fake_host_no_compute}), - mock.MagicMock(zoneName="c", - hosts={"c1": fake_host, - "c2": fake_host, "c3": fake_host}) - ] - setattr(fake_server, "OS-EXT-SRV-ATTR:host", "b2") - setattr(fake_server, "OS-EXT-AZ:availability_zone", "b") - nova_scenario = utils.NovaScenario(context=self.context) - - self.assertIn( - nova_scenario._find_host_to_migrate(fake_server), ["b1", "b3"]) - def test__migrate_server(self): fake_server = self.server setattr(fake_server, "OS-EXT-SRV-ATTR:host", "a1")