Provide ReqSpec to live-migrate conductor task
Since the RequestSpec object is now persisted in the API layer every time that we start an instance, we can now fetch it from the API DB and pass it thru the ComputeTask API to the conductor so it can directly call the scheduler with it. Partially-Implements: blueprint check-destination-on-migrations Change-Id: I9d6472220b941072eb3f998c949755c967fb71f6
This commit is contained in:
parent
d51c5670d8
commit
111a852e79
|
@ -3283,10 +3283,17 @@ class API(base.Base):
|
|||
|
||||
self._record_action_start(context, instance,
|
||||
instance_actions.LIVE_MIGRATION)
|
||||
|
||||
try:
|
||||
request_spec = objects.RequestSpec.get_by_instance_uuid(
|
||||
context, instance.uuid)
|
||||
except exception.RequestSpecNotFound:
|
||||
# Some old instances can still have no RequestSpec object attached
|
||||
# to them, we need to support the old way
|
||||
request_spec = None
|
||||
self.compute_task_api.live_migrate_instance(context, instance,
|
||||
host_name, block_migration=block_migration,
|
||||
disk_over_commit=disk_over_commit)
|
||||
disk_over_commit=disk_over_commit,
|
||||
request_spec=request_spec)
|
||||
|
||||
@check_instance_lock
|
||||
@check_instance_cell
|
||||
|
|
|
@ -75,11 +75,12 @@ class LocalComputeTaskAPI(object):
|
|||
reservations=reservations, clean_shutdown=clean_shutdown)
|
||||
|
||||
def live_migrate_instance(self, context, instance, host_name,
|
||||
block_migration, disk_over_commit):
|
||||
block_migration, disk_over_commit,
|
||||
request_spec=None):
|
||||
scheduler_hint = {'host': host_name}
|
||||
self._manager.migrate_server(
|
||||
context, instance, scheduler_hint, True, False, None,
|
||||
block_migration, disk_over_commit, None)
|
||||
block_migration, disk_over_commit, None, request_spec=request_spec)
|
||||
|
||||
def build_instances(self, context, instances, image,
|
||||
filter_properties, admin_password, injected_files,
|
||||
|
@ -185,11 +186,12 @@ class ComputeTaskAPI(object):
|
|||
reservations=reservations, clean_shutdown=clean_shutdown)
|
||||
|
||||
def live_migrate_instance(self, context, instance, host_name,
|
||||
block_migration, disk_over_commit):
|
||||
block_migration, disk_over_commit,
|
||||
request_spec=None):
|
||||
scheduler_hint = {'host': host_name}
|
||||
self.conductor_compute_rpcapi.migrate_server(
|
||||
context, instance, scheduler_hint, True, False, None,
|
||||
block_migration, disk_over_commit, None)
|
||||
block_migration, disk_over_commit, None, request_spec=request_spec)
|
||||
|
||||
def build_instances(self, context, instances, image, filter_properties,
|
||||
admin_password, injected_files, requested_networks,
|
||||
|
|
|
@ -144,7 +144,7 @@ class ComputeTaskManager(base.Base):
|
|||
may involve coordinating activities on multiple compute nodes.
|
||||
"""
|
||||
|
||||
target = messaging.Target(namespace='compute_task', version='1.12')
|
||||
target = messaging.Target(namespace='compute_task', version='1.13')
|
||||
|
||||
def __init__(self):
|
||||
super(ComputeTaskManager, self).__init__()
|
||||
|
@ -175,7 +175,7 @@ class ComputeTaskManager(base.Base):
|
|||
exception.UnsupportedPolicyException)
|
||||
def migrate_server(self, context, instance, scheduler_hint, live, rebuild,
|
||||
flavor, block_migration, disk_over_commit, reservations=None,
|
||||
clean_shutdown=True):
|
||||
clean_shutdown=True, request_spec=None):
|
||||
if instance and not isinstance(instance, nova_object.NovaObject):
|
||||
# NOTE(danms): Until v2 of the RPC API, we need to tolerate
|
||||
# old-world instance objects here
|
||||
|
@ -191,7 +191,7 @@ class ComputeTaskManager(base.Base):
|
|||
flavor = objects.Flavor.get_by_id(context, flavor['id'])
|
||||
if live and not rebuild and not flavor:
|
||||
self._live_migrate(context, instance, scheduler_hint,
|
||||
block_migration, disk_over_commit)
|
||||
block_migration, disk_over_commit, request_spec)
|
||||
elif not live and not rebuild and flavor:
|
||||
instance_uuid = instance.uuid
|
||||
with compute_utils.EventReporter(context, 'cold_migrate',
|
||||
|
@ -272,7 +272,7 @@ class ComputeTaskManager(base.Base):
|
|||
pass
|
||||
|
||||
def _live_migrate(self, context, instance, scheduler_hint,
|
||||
block_migration, disk_over_commit):
|
||||
block_migration, disk_over_commit, request_spec):
|
||||
destination = scheduler_hint.get("host")
|
||||
|
||||
def _set_vm_state(context, instance, ex, vm_state=None,
|
||||
|
@ -304,7 +304,7 @@ class ComputeTaskManager(base.Base):
|
|||
|
||||
task = self._build_live_migrate_task(context, instance, destination,
|
||||
block_migration, disk_over_commit,
|
||||
migration)
|
||||
migration, request_spec)
|
||||
try:
|
||||
task.execute()
|
||||
except (exception.NoValidHost,
|
||||
|
@ -337,13 +337,15 @@ class ComputeTaskManager(base.Base):
|
|||
raise exception.MigrationError(reason=six.text_type(ex))
|
||||
|
||||
def _build_live_migrate_task(self, context, instance, destination,
|
||||
block_migration, disk_over_commit, migration):
|
||||
block_migration, disk_over_commit, migration,
|
||||
request_spec=None):
|
||||
return live_migrate.LiveMigrationTask(context, instance,
|
||||
destination, block_migration,
|
||||
disk_over_commit, migration,
|
||||
self.compute_rpcapi,
|
||||
self.servicegroup_api,
|
||||
self.scheduler_client)
|
||||
self.scheduler_client,
|
||||
request_spec)
|
||||
|
||||
def _build_cold_migrate_task(self, context, instance, flavor,
|
||||
filter_properties, request_spec, reservations,
|
||||
|
|
|
@ -268,6 +268,7 @@ class ComputeTaskAPI(object):
|
|||
1.10 - Made migrate_server() and build_instances() send flavor objects
|
||||
1.11 - Added clean_shutdown to migrate_server()
|
||||
1.12 - Added request_spec to rebuild_instance()
|
||||
1.13 - Added request_spec to migrate_server()
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
|
@ -280,14 +281,19 @@ class ComputeTaskAPI(object):
|
|||
|
||||
def migrate_server(self, context, instance, scheduler_hint, live, rebuild,
|
||||
flavor, block_migration, disk_over_commit,
|
||||
reservations=None, clean_shutdown=True):
|
||||
reservations=None, clean_shutdown=True, request_spec=None):
|
||||
kw = {'instance': instance, 'scheduler_hint': scheduler_hint,
|
||||
'live': live, 'rebuild': rebuild, 'flavor': flavor,
|
||||
'block_migration': block_migration,
|
||||
'disk_over_commit': disk_over_commit,
|
||||
'reservations': reservations,
|
||||
'clean_shutdown': clean_shutdown}
|
||||
version = '1.11'
|
||||
'clean_shutdown': clean_shutdown,
|
||||
'request_spec': request_spec,
|
||||
}
|
||||
version = '1.13'
|
||||
if not self.client.can_send_version(version):
|
||||
del kw['request_spec']
|
||||
version = '1.11'
|
||||
if not self.client.can_send_version(version):
|
||||
del kw['clean_shutdown']
|
||||
version = '1.10'
|
||||
|
|
|
@ -38,7 +38,7 @@ CONF.register_opt(migrate_opt)
|
|||
class LiveMigrationTask(base.TaskBase):
|
||||
def __init__(self, context, instance, destination,
|
||||
block_migration, disk_over_commit, migration, compute_rpcapi,
|
||||
servicegroup_api, scheduler_client):
|
||||
servicegroup_api, scheduler_client, request_spec=None):
|
||||
super(LiveMigrationTask, self).__init__(context, instance)
|
||||
self.destination = destination
|
||||
self.block_migration = block_migration
|
||||
|
@ -50,6 +50,7 @@ class LiveMigrationTask(base.TaskBase):
|
|||
self.compute_rpcapi = compute_rpcapi
|
||||
self.servicegroup_api = servicegroup_api
|
||||
self.scheduler_client = scheduler_client
|
||||
self.request_spec = request_spec
|
||||
|
||||
def _execute(self):
|
||||
self._check_instance_is_active()
|
||||
|
@ -165,22 +166,32 @@ class LiveMigrationTask(base.TaskBase):
|
|||
attempted_hosts = [self.source]
|
||||
image = utils.get_image_from_system_metadata(
|
||||
self.instance.system_metadata)
|
||||
request_spec = scheduler_utils.build_request_spec(self.context, image,
|
||||
[self.instance])
|
||||
filter_properties = {'ignore_hosts': attempted_hosts}
|
||||
# TODO(sbauza): Remove that once setup_instance_group() accepts a
|
||||
# RequestSpec object
|
||||
request_spec = {'instance_properties': {'uuid': self.instance.uuid}}
|
||||
scheduler_utils.setup_instance_group(self.context, request_spec,
|
||||
filter_properties)
|
||||
if not self.request_spec:
|
||||
# NOTE(sbauza): We were unable to find an original RequestSpec
|
||||
# object - probably because the instance is old.
|
||||
# We need to mock that the old way
|
||||
request_spec = objects.RequestSpec.from_components(
|
||||
self.context, self.instance.uuid, image,
|
||||
self.instance.flavor, self.instance.numa_topology,
|
||||
self.instance.pci_requests,
|
||||
filter_properties, None, self.instance.availability_zone
|
||||
)
|
||||
else:
|
||||
request_spec = self.request_spec
|
||||
|
||||
host = None
|
||||
while host is None:
|
||||
self._check_not_over_max_retries(attempted_hosts)
|
||||
filter_properties = {'ignore_hosts': attempted_hosts}
|
||||
scheduler_utils.setup_instance_group(self.context, request_spec,
|
||||
filter_properties)
|
||||
# TODO(sbauza): Hydrate here the object until we modify the
|
||||
# scheduler.utils methods to directly use the RequestSpec object
|
||||
spec_obj = objects.RequestSpec.from_primitives(
|
||||
self.context, request_spec, filter_properties)
|
||||
request_spec.ignore_hosts = attempted_hosts
|
||||
try:
|
||||
host = self.scheduler_client.select_destinations(self.context,
|
||||
spec_obj)[0]['host']
|
||||
request_spec)[0]['host']
|
||||
except messaging.RemoteError as ex:
|
||||
# TODO(ShaoHe Feng) There maybe multi-scheduler, and the
|
||||
# scheduling algorithm is R-R, we can let other scheduler try.
|
||||
|
|
|
@ -53,7 +53,7 @@ class MigrateServerSamplesJsonTest(test_servers.ServersSampleBase):
|
|||
def test_post_live_migrate_server(self):
|
||||
# Get api samples to server live migrate request.
|
||||
def fake_live_migrate(_self, context, instance, scheduler_hint,
|
||||
block_migration, disk_over_commit):
|
||||
block_migration, disk_over_commit, request_spec):
|
||||
self.assertEqual(self.uuid, instance["uuid"])
|
||||
host = scheduler_hint["host"]
|
||||
self.assertEqual(self.compute.host, host)
|
||||
|
|
|
@ -10052,21 +10052,29 @@ class ComputeAPITestCase(BaseTestCase):
|
|||
instance, instance_uuid = self._run_instance()
|
||||
|
||||
rpcapi = self.compute_api.compute_task_api
|
||||
self.mox.StubOutWithMock(self.compute_api, '_record_action_start')
|
||||
self.mox.StubOutWithMock(rpcapi, 'live_migrate_instance')
|
||||
self.compute_api._record_action_start(self.context, instance,
|
||||
'live-migration')
|
||||
rpcapi.live_migrate_instance(self.context, instance, 'fake_dest_host',
|
||||
block_migration=True,
|
||||
disk_over_commit=True)
|
||||
fake_spec = objects.RequestSpec()
|
||||
|
||||
self.mox.ReplayAll()
|
||||
@mock.patch.object(rpcapi, 'live_migrate_instance')
|
||||
@mock.patch.object(objects.RequestSpec, 'get_by_instance_uuid')
|
||||
@mock.patch.object(self.compute_api, '_record_action_start')
|
||||
def do_test(record_action_start, get_by_instance_uuid,
|
||||
live_migrate_instance):
|
||||
get_by_instance_uuid.return_value = fake_spec
|
||||
|
||||
self.compute_api.live_migrate(self.context, instance,
|
||||
block_migration=True,
|
||||
disk_over_commit=True,
|
||||
host_name='fake_dest_host')
|
||||
self.compute_api.live_migrate(self.context, instance,
|
||||
block_migration=True,
|
||||
disk_over_commit=True,
|
||||
host_name='fake_dest_host')
|
||||
|
||||
record_action_start.assert_called_once_with(self.context, instance,
|
||||
'live-migration')
|
||||
live_migrate_instance.assert_called_once_with(
|
||||
self.context, instance, 'fake_dest_host',
|
||||
block_migration=True,
|
||||
disk_over_commit=True,
|
||||
request_spec=fake_spec)
|
||||
|
||||
do_test()
|
||||
instance.refresh()
|
||||
self.assertEqual(instance['task_state'], task_states.MIGRATING)
|
||||
|
||||
|
|
|
@ -1788,9 +1788,10 @@ class _ComputeAPIUnitTestMixIn(object):
|
|||
instance = self._create_instance_obj(params=paused_state)
|
||||
self._live_migrate_instance(instance)
|
||||
|
||||
@mock.patch.object(objects.RequestSpec, 'get_by_instance_uuid')
|
||||
@mock.patch.object(objects.Instance, 'save')
|
||||
@mock.patch.object(objects.InstanceAction, 'action_start')
|
||||
def _live_migrate_instance(self, instance, _save, _action):
|
||||
def _live_migrate_instance(self, instance, _save, _action, get_spec):
|
||||
# TODO(gilliard): This logic is upside-down (different
|
||||
# behaviour depending on which class this method is mixed-into. Once
|
||||
# we have cellsv2 we can remove this kind of logic from this test
|
||||
|
@ -1798,6 +1799,8 @@ class _ComputeAPIUnitTestMixIn(object):
|
|||
api = self.compute_api.cells_rpcapi
|
||||
else:
|
||||
api = conductor.api.ComputeTaskAPI
|
||||
fake_spec = objects.RequestSpec()
|
||||
get_spec.return_value = fake_spec
|
||||
with mock.patch.object(api, 'live_migrate_instance') as task:
|
||||
self.compute_api.live_migrate(self.context, instance,
|
||||
block_migration=True,
|
||||
|
@ -1807,7 +1810,8 @@ class _ComputeAPIUnitTestMixIn(object):
|
|||
task.assert_called_once_with(self.context, instance,
|
||||
'fake_dest_host',
|
||||
block_migration=True,
|
||||
disk_over_commit=True)
|
||||
disk_over_commit=True,
|
||||
request_spec=fake_spec)
|
||||
|
||||
def test_swap_volume_volume_api_usage(self):
|
||||
# This test ensures that volume_id arguments are passed to volume_api
|
||||
|
|
|
@ -370,9 +370,10 @@ class CellsConductorAPIRPCRedirect(test.NoDBTestCase):
|
|||
self.compute_api.resize(self.context, instance)
|
||||
self.assertTrue(self.cells_rpcapi.resize_instance.called)
|
||||
|
||||
@mock.patch.object(objects.RequestSpec, 'get_by_instance_uuid')
|
||||
@mock.patch.object(compute_api.API, '_record_action_start')
|
||||
@mock.patch.object(objects.Instance, 'save')
|
||||
def test_live_migrate_instance(self, instance_save, _record):
|
||||
def test_live_migrate_instance(self, instance_save, _record, _get_spec):
|
||||
orig_system_metadata = {}
|
||||
instance = fake_instance.fake_instance_obj(self.context,
|
||||
vm_state=vm_states.ACTIVE, cell_name='fake-cell',
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
# under the License.
|
||||
|
||||
import mock
|
||||
from mox3 import mox
|
||||
import oslo_messaging as messaging
|
||||
|
||||
from nova.compute import power_state
|
||||
|
@ -49,13 +48,15 @@ class LiveMigrationTaskTestCase(test.NoDBTestCase):
|
|||
self.block_migration = "bm"
|
||||
self.disk_over_commit = "doc"
|
||||
self.migration = objects.Migration()
|
||||
self.fake_spec = objects.RequestSpec()
|
||||
self._generate_task()
|
||||
|
||||
def _generate_task(self):
|
||||
self.task = live_migrate.LiveMigrationTask(self.context,
|
||||
self.instance, self.destination, self.block_migration,
|
||||
self.disk_over_commit, self.migration, compute_rpcapi.ComputeAPI(),
|
||||
servicegroup.API(), scheduler_client.SchedulerClient())
|
||||
servicegroup.API(), scheduler_client.SchedulerClient(),
|
||||
self.fake_spec)
|
||||
|
||||
def test_execute_with_destination(self):
|
||||
self.mox.StubOutWithMock(self.task, '_check_host_is_up')
|
||||
|
@ -252,9 +253,7 @@ class LiveMigrationTaskTestCase(test.NoDBTestCase):
|
|||
|
||||
def test_find_destination_works(self):
|
||||
self.mox.StubOutWithMock(utils, 'get_image_from_system_metadata')
|
||||
self.mox.StubOutWithMock(scheduler_utils, 'build_request_spec')
|
||||
self.mox.StubOutWithMock(scheduler_utils, 'setup_instance_group')
|
||||
self.mox.StubOutWithMock(objects.RequestSpec, 'from_primitives')
|
||||
self.mox.StubOutWithMock(self.task.scheduler_client,
|
||||
'select_destinations')
|
||||
self.mox.StubOutWithMock(self.task,
|
||||
|
@ -263,16 +262,11 @@ class LiveMigrationTaskTestCase(test.NoDBTestCase):
|
|||
|
||||
utils.get_image_from_system_metadata(
|
||||
self.instance.system_metadata).AndReturn("image")
|
||||
scheduler_utils.build_request_spec(self.context, mox.IgnoreArg(),
|
||||
mox.IgnoreArg()).AndReturn({})
|
||||
fake_props = {'instance_properties': {'uuid': self.instance_uuid}}
|
||||
scheduler_utils.setup_instance_group(
|
||||
self.context, {}, {'ignore_hosts': [self.instance_host]})
|
||||
fake_spec = objects.RequestSpec()
|
||||
objects.RequestSpec.from_primitives(
|
||||
self.context, mox.IgnoreArg(),
|
||||
mox.IgnoreArg()).AndReturn(fake_spec)
|
||||
self.context, fake_props, {'ignore_hosts': [self.instance_host]})
|
||||
self.task.scheduler_client.select_destinations(
|
||||
self.context, fake_spec).AndReturn(
|
||||
self.context, self.fake_spec).AndReturn(
|
||||
[{'host': 'host1'}])
|
||||
self.task._check_compatible_with_source_hypervisor("host1")
|
||||
self.task._call_livem_checks_on_host("host1")
|
||||
|
@ -280,30 +274,57 @@ class LiveMigrationTaskTestCase(test.NoDBTestCase):
|
|||
self.mox.ReplayAll()
|
||||
self.assertEqual("host1", self.task._find_destination())
|
||||
|
||||
def test_find_destination_works_with_no_request_spec(self):
|
||||
task = live_migrate.LiveMigrationTask(
|
||||
self.context, self.instance, self.destination,
|
||||
self.block_migration, self.disk_over_commit, self.migration,
|
||||
compute_rpcapi.ComputeAPI(), servicegroup.API(),
|
||||
scheduler_client.SchedulerClient(), request_spec=None)
|
||||
another_spec = objects.RequestSpec()
|
||||
self.instance.flavor = objects.Flavor()
|
||||
self.instance.numa_topology = None
|
||||
self.instance.pci_requests = None
|
||||
|
||||
@mock.patch.object(task, '_call_livem_checks_on_host')
|
||||
@mock.patch.object(task, '_check_compatible_with_source_hypervisor')
|
||||
@mock.patch.object(task.scheduler_client, 'select_destinations')
|
||||
@mock.patch.object(objects.RequestSpec, 'from_components')
|
||||
@mock.patch.object(scheduler_utils, 'setup_instance_group')
|
||||
@mock.patch.object(utils, 'get_image_from_system_metadata')
|
||||
def do_test(get_image, setup_ig, from_components, select_dest,
|
||||
check_compat, call_livem_checks):
|
||||
get_image.return_value = "image"
|
||||
from_components.return_value = another_spec
|
||||
select_dest.return_value = [{'host': 'host1'}]
|
||||
|
||||
self.assertEqual("host1", task._find_destination())
|
||||
|
||||
get_image.assert_called_once_with(self.instance.system_metadata)
|
||||
fake_props = {'instance_properties': {'uuid': self.instance_uuid}}
|
||||
setup_ig.assert_called_once_with(
|
||||
self.context, fake_props,
|
||||
{'ignore_hosts': [self.instance_host]}
|
||||
)
|
||||
select_dest.assert_called_once_with(self.context, another_spec)
|
||||
check_compat.assert_called_once_with("host1")
|
||||
call_livem_checks.assert_called_once_with("host1")
|
||||
do_test()
|
||||
|
||||
def test_find_destination_no_image_works(self):
|
||||
self.instance['image_ref'] = ''
|
||||
|
||||
self.mox.StubOutWithMock(scheduler_utils, 'build_request_spec')
|
||||
self.mox.StubOutWithMock(scheduler_utils, 'setup_instance_group')
|
||||
self.mox.StubOutWithMock(objects.RequestSpec, 'from_primitives')
|
||||
self.mox.StubOutWithMock(self.task.scheduler_client,
|
||||
'select_destinations')
|
||||
self.mox.StubOutWithMock(self.task,
|
||||
'_check_compatible_with_source_hypervisor')
|
||||
self.mox.StubOutWithMock(self.task, '_call_livem_checks_on_host')
|
||||
|
||||
scheduler_utils.build_request_spec(
|
||||
self.context,
|
||||
{'properties': {'hw_disk_bus': 'scsi'}},
|
||||
mox.IgnoreArg()).AndReturn({})
|
||||
fake_props = {'instance_properties': {'uuid': self.instance_uuid}}
|
||||
scheduler_utils.setup_instance_group(
|
||||
self.context, {}, {'ignore_hosts': [self.instance_host]})
|
||||
fake_spec = objects.RequestSpec()
|
||||
objects.RequestSpec.from_primitives(
|
||||
self.context, mox.IgnoreArg(),
|
||||
mox.IgnoreArg()).AndReturn(fake_spec)
|
||||
self.context, fake_props, {'ignore_hosts': [self.instance_host]})
|
||||
self.task.scheduler_client.select_destinations(self.context,
|
||||
fake_spec).AndReturn(
|
||||
self.fake_spec).AndReturn(
|
||||
[{'host': 'host1'}])
|
||||
self.task._check_compatible_with_source_hypervisor("host1")
|
||||
self.task._call_livem_checks_on_host("host1")
|
||||
|
@ -313,9 +334,7 @@ class LiveMigrationTaskTestCase(test.NoDBTestCase):
|
|||
|
||||
def _test_find_destination_retry_hypervisor_raises(self, error):
|
||||
self.mox.StubOutWithMock(utils, 'get_image_from_system_metadata')
|
||||
self.mox.StubOutWithMock(scheduler_utils, 'build_request_spec')
|
||||
self.mox.StubOutWithMock(scheduler_utils, 'setup_instance_group')
|
||||
self.mox.StubOutWithMock(objects.RequestSpec, 'from_primitives')
|
||||
self.mox.StubOutWithMock(self.task.scheduler_client,
|
||||
'select_destinations')
|
||||
self.mox.StubOutWithMock(self.task,
|
||||
|
@ -324,25 +343,17 @@ class LiveMigrationTaskTestCase(test.NoDBTestCase):
|
|||
|
||||
utils.get_image_from_system_metadata(
|
||||
self.instance.system_metadata).AndReturn("image")
|
||||
scheduler_utils.build_request_spec(self.context, mox.IgnoreArg(),
|
||||
mox.IgnoreArg()).AndReturn({})
|
||||
fake_props = {'instance_properties': {'uuid': self.instance_uuid}}
|
||||
scheduler_utils.setup_instance_group(
|
||||
self.context, {}, {'ignore_hosts': [self.instance_host]})
|
||||
fake_spec = objects.RequestSpec()
|
||||
objects.RequestSpec.from_primitives(
|
||||
self.context, {}, mox.IgnoreArg()).AndReturn(fake_spec)
|
||||
self.context, fake_props, {'ignore_hosts': [self.instance_host]})
|
||||
self.task.scheduler_client.select_destinations(self.context,
|
||||
fake_spec).AndReturn(
|
||||
self.fake_spec).AndReturn(
|
||||
[{'host': 'host1'}])
|
||||
self.task._check_compatible_with_source_hypervisor("host1")\
|
||||
.AndRaise(error)
|
||||
|
||||
scheduler_utils.setup_instance_group(
|
||||
self.context, {}, {'ignore_hosts': [self.instance_host, "host1"]})
|
||||
objects.RequestSpec.from_primitives(
|
||||
self.context, {}, mox.IgnoreArg()).AndReturn(fake_spec)
|
||||
self.task.scheduler_client.select_destinations(self.context,
|
||||
fake_spec).AndReturn(
|
||||
self.fake_spec).AndReturn(
|
||||
[{'host': 'host2'}])
|
||||
self.task._check_compatible_with_source_hypervisor("host2")
|
||||
self.task._call_livem_checks_on_host("host2")
|
||||
|
@ -361,9 +372,7 @@ class LiveMigrationTaskTestCase(test.NoDBTestCase):
|
|||
def test_find_destination_retry_with_invalid_livem_checks(self):
|
||||
self.flags(migrate_max_retries=1)
|
||||
self.mox.StubOutWithMock(utils, 'get_image_from_system_metadata')
|
||||
self.mox.StubOutWithMock(scheduler_utils, 'build_request_spec')
|
||||
self.mox.StubOutWithMock(scheduler_utils, 'setup_instance_group')
|
||||
self.mox.StubOutWithMock(objects.RequestSpec, 'from_primitives')
|
||||
self.mox.StubOutWithMock(self.task.scheduler_client,
|
||||
'select_destinations')
|
||||
self.mox.StubOutWithMock(self.task,
|
||||
|
@ -372,28 +381,18 @@ class LiveMigrationTaskTestCase(test.NoDBTestCase):
|
|||
|
||||
utils.get_image_from_system_metadata(
|
||||
self.instance.system_metadata).AndReturn("image")
|
||||
scheduler_utils.build_request_spec(self.context, mox.IgnoreArg(),
|
||||
mox.IgnoreArg()).AndReturn({})
|
||||
fake_props = {'instance_properties': {'uuid': self.instance_uuid}}
|
||||
scheduler_utils.setup_instance_group(
|
||||
self.context, {}, {'ignore_hosts': [self.instance_host]})
|
||||
fake_spec = objects.RequestSpec()
|
||||
objects.RequestSpec.from_primitives(
|
||||
self.context, mox.IgnoreArg(),
|
||||
mox.IgnoreArg()).AndReturn(fake_spec)
|
||||
self.context, fake_props, {'ignore_hosts': [self.instance_host]})
|
||||
self.task.scheduler_client.select_destinations(self.context,
|
||||
fake_spec).AndReturn(
|
||||
self.fake_spec).AndReturn(
|
||||
[{'host': 'host1'}])
|
||||
self.task._check_compatible_with_source_hypervisor("host1")
|
||||
self.task._call_livem_checks_on_host("host1")\
|
||||
.AndRaise(exception.Invalid)
|
||||
|
||||
scheduler_utils.setup_instance_group(
|
||||
self.context, {}, {'ignore_hosts': [self.instance_host, "host1"]})
|
||||
objects.RequestSpec.from_primitives(
|
||||
self.context, mox.IgnoreArg(),
|
||||
mox.IgnoreArg()).AndReturn(fake_spec)
|
||||
self.task.scheduler_client.select_destinations(self.context,
|
||||
fake_spec).AndReturn(
|
||||
self.fake_spec).AndReturn(
|
||||
[{'host': 'host2'}])
|
||||
self.task._check_compatible_with_source_hypervisor("host2")
|
||||
self.task._call_livem_checks_on_host("host2")
|
||||
|
@ -404,9 +403,7 @@ class LiveMigrationTaskTestCase(test.NoDBTestCase):
|
|||
def test_find_destination_retry_with_failed_migration_pre_checks(self):
|
||||
self.flags(migrate_max_retries=1)
|
||||
self.mox.StubOutWithMock(utils, 'get_image_from_system_metadata')
|
||||
self.mox.StubOutWithMock(scheduler_utils, 'build_request_spec')
|
||||
self.mox.StubOutWithMock(scheduler_utils, 'setup_instance_group')
|
||||
self.mox.StubOutWithMock(objects.RequestSpec, 'from_primitives')
|
||||
self.mox.StubOutWithMock(self.task.scheduler_client,
|
||||
'select_destinations')
|
||||
self.mox.StubOutWithMock(self.task,
|
||||
|
@ -415,29 +412,18 @@ class LiveMigrationTaskTestCase(test.NoDBTestCase):
|
|||
|
||||
utils.get_image_from_system_metadata(
|
||||
self.instance.system_metadata).AndReturn("image")
|
||||
scheduler_utils.build_request_spec(self.context, mox.IgnoreArg(),
|
||||
mox.IgnoreArg()).AndReturn({})
|
||||
fake_props = {'instance_properties': {'uuid': self.instance_uuid}}
|
||||
scheduler_utils.setup_instance_group(
|
||||
self.context, {}, {'ignore_hosts': [self.instance_host]})
|
||||
fake_spec = objects.RequestSpec()
|
||||
objects.RequestSpec.from_primitives(
|
||||
self.context, mox.IgnoreArg(),
|
||||
mox.IgnoreArg()).AndReturn(fake_spec)
|
||||
self.context, fake_props, {'ignore_hosts': [self.instance_host]})
|
||||
self.task.scheduler_client.select_destinations(self.context,
|
||||
fake_spec).AndReturn(
|
||||
self.fake_spec).AndReturn(
|
||||
[{'host': 'host1'}])
|
||||
self.task._check_compatible_with_source_hypervisor("host1")
|
||||
self.task._call_livem_checks_on_host("host1")\
|
||||
.AndRaise(exception.MigrationPreCheckError("reason"))
|
||||
|
||||
scheduler_utils.setup_instance_group(
|
||||
self.context, {}, {'ignore_hosts': [self.instance_host, "host1"]})
|
||||
fake_spec = objects.RequestSpec()
|
||||
objects.RequestSpec.from_primitives(
|
||||
self.context, mox.IgnoreArg(),
|
||||
mox.IgnoreArg()).AndReturn(fake_spec)
|
||||
self.task.scheduler_client.select_destinations(self.context,
|
||||
fake_spec).AndReturn(
|
||||
self.fake_spec).AndReturn(
|
||||
[{'host': 'host2'}])
|
||||
self.task._check_compatible_with_source_hypervisor("host2")
|
||||
self.task._call_livem_checks_on_host("host2")
|
||||
|
@ -448,9 +434,7 @@ class LiveMigrationTaskTestCase(test.NoDBTestCase):
|
|||
def test_find_destination_retry_exceeds_max(self):
|
||||
self.flags(migrate_max_retries=0)
|
||||
self.mox.StubOutWithMock(utils, 'get_image_from_system_metadata')
|
||||
self.mox.StubOutWithMock(scheduler_utils, 'build_request_spec')
|
||||
self.mox.StubOutWithMock(scheduler_utils, 'setup_instance_group')
|
||||
self.mox.StubOutWithMock(objects.RequestSpec, 'from_primitives')
|
||||
self.mox.StubOutWithMock(self.task.scheduler_client,
|
||||
'select_destinations')
|
||||
self.mox.StubOutWithMock(self.task,
|
||||
|
@ -458,16 +442,11 @@ class LiveMigrationTaskTestCase(test.NoDBTestCase):
|
|||
|
||||
utils.get_image_from_system_metadata(
|
||||
self.instance.system_metadata).AndReturn("image")
|
||||
scheduler_utils.build_request_spec(self.context, mox.IgnoreArg(),
|
||||
mox.IgnoreArg()).AndReturn({})
|
||||
fake_props = {'instance_properties': {'uuid': self.instance_uuid}}
|
||||
scheduler_utils.setup_instance_group(
|
||||
self.context, {}, {'ignore_hosts': [self.instance_host]})
|
||||
fake_spec = objects.RequestSpec()
|
||||
objects.RequestSpec.from_primitives(
|
||||
self.context, mox.IgnoreArg(),
|
||||
mox.IgnoreArg()).AndReturn(fake_spec)
|
||||
self.context, fake_props, {'ignore_hosts': [self.instance_host]})
|
||||
self.task.scheduler_client.select_destinations(self.context,
|
||||
fake_spec).AndReturn(
|
||||
self.fake_spec).AndReturn(
|
||||
[{'host': 'host1'}])
|
||||
self.task._check_compatible_with_source_hypervisor("host1")\
|
||||
.AndRaise(exception.DestinationHypervisorTooOld)
|
||||
|
@ -481,23 +460,16 @@ class LiveMigrationTaskTestCase(test.NoDBTestCase):
|
|||
|
||||
def test_find_destination_when_runs_out_of_hosts(self):
|
||||
self.mox.StubOutWithMock(utils, 'get_image_from_system_metadata')
|
||||
self.mox.StubOutWithMock(scheduler_utils, 'build_request_spec')
|
||||
self.mox.StubOutWithMock(scheduler_utils, 'setup_instance_group')
|
||||
self.mox.StubOutWithMock(objects.RequestSpec, 'from_primitives')
|
||||
self.mox.StubOutWithMock(self.task.scheduler_client,
|
||||
'select_destinations')
|
||||
utils.get_image_from_system_metadata(
|
||||
self.instance.system_metadata).AndReturn("image")
|
||||
scheduler_utils.build_request_spec(self.context, mox.IgnoreArg(),
|
||||
mox.IgnoreArg()).AndReturn({})
|
||||
fake_props = {'instance_properties': {'uuid': self.instance_uuid}}
|
||||
scheduler_utils.setup_instance_group(
|
||||
self.context, {}, {'ignore_hosts': [self.instance_host]})
|
||||
fake_spec = objects.RequestSpec()
|
||||
objects.RequestSpec.from_primitives(
|
||||
self.context,
|
||||
mox.IgnoreArg(), mox.IgnoreArg()).AndReturn(fake_spec)
|
||||
self.context, fake_props, {'ignore_hosts': [self.instance_host]})
|
||||
self.task.scheduler_client.select_destinations(self.context,
|
||||
fake_spec).AndRaise(
|
||||
self.fake_spec).AndRaise(
|
||||
exception.NoValidHost(reason=""))
|
||||
|
||||
self.mox.ReplayAll()
|
||||
|
|
Loading…
Reference in New Issue