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
This commit is contained in:
Tom Patzig 2017-11-29 12:56:45 +01:00
parent 8b63ceb10d
commit 290355e185
4 changed files with 5 additions and 78 deletions

View File

@ -717,9 +717,7 @@ class BootAndLiveMigrateServer(utils.NovaScenario):
server = self._boot_server(image, flavor, **kwargs) server = self._boot_server(image, flavor, **kwargs)
self.sleep_between(min_sleep, max_sleep) self.sleep_between(min_sleep, max_sleep)
new_host = self._find_host_to_migrate(server) self._live_migrate(server, block_migration, disk_over_commit)
self._live_migrate(server, new_host,
block_migration, disk_over_commit)
self._delete_server(server) self._delete_server(server)
@ -774,9 +772,7 @@ class BootServerFromVolumeAndLiveMigrate(utils.NovaScenario,
**kwargs) **kwargs)
self.sleep_between(min_sleep, max_sleep) self.sleep_between(min_sleep, max_sleep)
new_host = self._find_host_to_migrate(server) self._live_migrate(server, block_migration, disk_over_commit)
self._live_migrate(server, new_host,
block_migration, disk_over_commit)
self._delete_server(server, force=force_delete) self._delete_server(server, force=force_delete)
@ -832,9 +828,7 @@ class BootServerAttachCreatedVolumeAndLiveMigrate(utils.NovaScenario,
self.sleep_between(min_sleep, max_sleep) self.sleep_between(min_sleep, max_sleep)
new_host = self._find_host_to_migrate(server) self._live_migrate(server, block_migration, disk_over_commit)
self._live_migrate(server, new_host,
block_migration, disk_over_commit)
self._detach_volume(server, volume) self._detach_volume(server, volume)

View File

@ -13,7 +13,6 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
import random
from oslo_config import cfg from oslo_config import cfg
@ -737,12 +736,11 @@ class NovaScenario(scenario.OpenStackScenario):
) )
@atomic.action_timer("nova.live_migrate") @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): disk_over_commit=False, skip_host_check=False):
"""Run live migration of the given server. """Run live migration of the given server.
:param server: Server object :param server: Server object
:param target_host: Specifies the target compute node to migrate
:param block_migration: Specifies the migration type :param block_migration: Specifies the migration type
:param disk_over_commit: Specifies whether to overcommit migrated :param disk_over_commit: Specifies whether to overcommit migrated
instance or not instance or not
@ -751,8 +749,7 @@ class NovaScenario(scenario.OpenStackScenario):
""" """
server_admin = self.admin_clients("nova").servers.get(server.id) server_admin = self.admin_clients("nova").servers.get(server.id)
host_pre_migrate = getattr(server_admin, "OS-EXT-SRV-ATTR:host") host_pre_migrate = getattr(server_admin, "OS-EXT-SRV-ATTR:host")
server_admin.live_migrate(target_host, server_admin.live_migrate(block_migration=block_migration,
block_migration=block_migration,
disk_over_commit=disk_over_commit) disk_over_commit=disk_over_commit)
utils.wait_for_status( utils.wait_for_status(
server, server,
@ -769,30 +766,6 @@ class NovaScenario(scenario.OpenStackScenario):
"Live Migration failed: Migration complete " "Live Migration failed: Migration complete "
"but instance did not change host: %s" % host_pre_migrate) "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") @atomic.action_timer("nova.migrate")
def _migrate(self, server, skip_host_check=False): def _migrate(self, server, skip_host_check=False):
"""Run migration of the given server. """Run migration of the given server.

View File

@ -705,8 +705,6 @@ class NovaServersTestCase(test.ScenarioTestCase):
scenario.generate_random_name = mock.MagicMock(return_value="name") scenario.generate_random_name = mock.MagicMock(return_value="name")
scenario._boot_server = mock.MagicMock(return_value=fake_server) scenario._boot_server = mock.MagicMock(return_value=fake_server)
scenario.sleep_between = mock.MagicMock() scenario.sleep_between = mock.MagicMock()
scenario._find_host_to_migrate = mock.MagicMock(
return_value="host_name")
scenario._live_migrate = mock.MagicMock() scenario._live_migrate = mock.MagicMock()
scenario._delete_server = 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.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, scenario._live_migrate.assert_called_once_with(fake_server,
"host_name",
False, False) False, False)
scenario._delete_server.assert_called_once_with(fake_server) 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.generate_random_name = mock.MagicMock(return_value="name")
scenario._boot_server = mock.MagicMock(return_value=fake_server) scenario._boot_server = mock.MagicMock(return_value=fake_server)
scenario.sleep_between = mock.MagicMock() scenario.sleep_between = mock.MagicMock()
scenario._find_host_to_migrate = mock.MagicMock(
return_value="host_name")
scenario._live_migrate = mock.MagicMock() scenario._live_migrate = mock.MagicMock()
scenario._delete_server = 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.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, scenario._live_migrate.assert_called_once_with(fake_server,
"host_name",
False, False) False, False)
scenario._delete_server.assert_called_once_with(fake_server, scenario._delete_server.assert_called_once_with(fake_server,
force=False) force=False)
@ -784,8 +774,6 @@ class NovaServersTestCase(test.ScenarioTestCase):
scenario.sleep_between = mock.MagicMock() scenario.sleep_between = mock.MagicMock()
scenario._find_host_to_migrate = mock.MagicMock(
return_value="host_name")
scenario._live_migrate = mock.MagicMock() scenario._live_migrate = mock.MagicMock()
scenario._boot_server = mock.MagicMock(return_value=fake_server) scenario._boot_server = mock.MagicMock(return_value=fake_server)
@ -806,7 +794,6 @@ class NovaServersTestCase(test.ScenarioTestCase):
fake_volume) fake_volume)
scenario.sleep_between.assert_called_once_with(10, 20) scenario.sleep_between.assert_called_once_with(10, 20)
scenario._live_migrate.assert_called_once_with(fake_server, scenario._live_migrate.assert_called_once_with(fake_server,
"host_name",
False, False) False, False)
cinder.delete_volume.assert_called_once_with(fake_volume) cinder.delete_volume.assert_called_once_with(fake_volume)

View File

@ -649,11 +649,9 @@ class NovaScenarioTestCase(test.ScenarioTestCase):
"nova.detach_volume") "nova.detach_volume")
def test__live_migrate_server(self): def test__live_migrate_server(self):
fake_host = mock.MagicMock()
self.admin_clients("nova").servers.get(return_value=self.server) self.admin_clients("nova").servers.get(return_value=self.server)
nova_scenario = utils.NovaScenario(context=self.context) nova_scenario = utils.NovaScenario(context=self.context)
nova_scenario._live_migrate(self.server, nova_scenario._live_migrate(self.server,
fake_host,
block_migration=False, block_migration=False,
disk_over_commit=False, disk_over_commit=False,
skip_host_check=True) skip_host_check=True)
@ -669,31 +667,6 @@ class NovaScenarioTestCase(test.ScenarioTestCase):
self._test_atomic_action_timer(nova_scenario.atomic_actions(), self._test_atomic_action_timer(nova_scenario.atomic_actions(),
"nova.live_migrate") "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): def test__migrate_server(self):
fake_server = self.server fake_server = self.server
setattr(fake_server, "OS-EXT-SRV-ATTR:host", "a1") setattr(fake_server, "OS-EXT-SRV-ATTR:host", "a1")