diff options
Diffstat (limited to 'nova/tests/scheduler/test_scheduler.py')
-rw-r--r-- | nova/tests/scheduler/test_scheduler.py | 506 |
1 files changed, 18 insertions, 488 deletions
diff --git a/nova/tests/scheduler/test_scheduler.py b/nova/tests/scheduler/test_scheduler.py index 0574f6d2e..99de672c4 100644 --- a/nova/tests/scheduler/test_scheduler.py +++ b/nova/tests/scheduler/test_scheduler.py @@ -22,20 +22,16 @@ Tests For Scheduler import mox from nova.compute import api as compute_api -from nova.compute import flavors -from nova.compute import power_state -from nova.compute import rpcapi as compute_rpcapi from nova.compute import task_states from nova.compute import utils as compute_utils from nova.compute import vm_states from nova.conductor import api as conductor_api +from nova.conductor.tasks import live_migrate from nova import context from nova import db from nova import exception from nova.image import glance -from nova.openstack.common import jsonutils from nova.openstack.common.notifier import api as notifier -from nova.openstack.common import rpc from nova.openstack.common.rpc import common as rpc_common from nova.scheduler import driver from nova.scheduler import manager @@ -45,7 +41,6 @@ from nova.tests import fake_instance_actions from nova.tests.image import fake as fake_image from nova.tests import matchers from nova.tests.scheduler import fakes -from nova import utils class SchedulerManagerTestCase(test.NoDBTestCase): @@ -220,11 +215,11 @@ class SchedulerManagerTestCase(test.NoDBTestCase): block_migration = False disk_over_commit = False - self._mox_schedule_method_helper('schedule_live_migration') + self.mox.StubOutWithMock(self.manager, '_schedule_live_migration') self.mox.StubOutWithMock(compute_utils, 'add_instance_fault_from_exc') self.mox.StubOutWithMock(db, 'instance_update_and_get_original') - self.manager.driver.schedule_live_migration(self.context, + self.manager._schedule_live_migration(self.context, inst, dest, block_migration, disk_over_commit).AndRaise( exception.NoValidHost(reason="")) db.instance_update_and_get_original(self.context, inst["uuid"], @@ -253,11 +248,11 @@ class SchedulerManagerTestCase(test.NoDBTestCase): block_migration = False disk_over_commit = False - self._mox_schedule_method_helper('schedule_live_migration') + self.mox.StubOutWithMock(self.manager, '_schedule_live_migration') self.mox.StubOutWithMock(compute_utils, 'add_instance_fault_from_exc') self.mox.StubOutWithMock(db, 'instance_update_and_get_original') - self.manager.driver.schedule_live_migration(self.context, + self.manager._schedule_live_migration(self.context, inst, dest, block_migration, disk_over_commit).AndRaise( exception.ComputeServiceUnavailable(host="src")) db.instance_update_and_get_original(self.context, inst["uuid"], @@ -277,6 +272,17 @@ class SchedulerManagerTestCase(test.NoDBTestCase): self.context, inst, dest, block_migration, disk_over_commit) + def test_live_migrate(self): + instance = {'host': 'h'} + self.mox.StubOutClassWithMocks(live_migrate, "LiveMigrationTask") + task = live_migrate.LiveMigrationTask(self.context, instance, + "dest", "bm", "doc", self.manager.driver.select_hosts) + task.execute() + + self.mox.ReplayAll() + self.manager.live_migration(self.context, instance, "dest", + "bm", "doc") + def test_live_migration_set_vmstate_error(self): inst = {"uuid": "fake-instance-id", "vm_state": vm_states.ACTIVE, } @@ -285,11 +291,11 @@ class SchedulerManagerTestCase(test.NoDBTestCase): block_migration = False disk_over_commit = False - self._mox_schedule_method_helper('schedule_live_migration') + self.mox.StubOutWithMock(self.manager, '_schedule_live_migration') self.mox.StubOutWithMock(compute_utils, 'add_instance_fault_from_exc') self.mox.StubOutWithMock(db, 'instance_update_and_get_original') - self.manager.driver.schedule_live_migration(self.context, + self.manager._schedule_live_migration(self.context, inst, dest, block_migration, disk_over_commit).AndRaise( ValueError) db.instance_update_and_get_original(self.context, inst["uuid"], @@ -464,482 +470,6 @@ class SchedulerTestCase(test.NoDBTestCase): result = self.driver.hosts_up(self.context, self.topic) self.assertEqual(result, ['host2']) - def _live_migration_instance(self): - inst_type = {'memory_mb': 1024, 'root_gb': 40, 'deleted_at': None, - 'name': u'm1.medium', 'deleted': 0, 'created_at': None, - 'ephemeral_gb': 0, 'updated_at': None, 'disabled': False, - 'vcpus': 2, 'extra_specs': {}, 'swap': 0, - 'rxtx_factor': 1.0, 'is_public': True, 'flavorid': u'3', - 'vcpu_weight': None, 'id': 1} - - sys_meta = utils.dict_to_metadata( - flavors.save_flavor_info({}, inst_type)) - return {'id': 31337, - 'uuid': 'fake_uuid', - 'name': 'fake-instance', - 'host': 'fake_host1', - 'power_state': power_state.RUNNING, - 'memory_mb': 1024, - 'root_gb': 1024, - 'ephemeral_gb': 0, - 'vm_state': '', - 'task_state': '', - 'instance_type_id': inst_type['id'], - 'image_ref': 'fake-image-ref', - 'system_metadata': sys_meta} - - def test_live_migration_basic(self): - # Test basic schedule_live_migration functionality. - self.mox.StubOutWithMock(self.driver, '_live_migration_src_check') - self.mox.StubOutWithMock(self.driver, '_live_migration_dest_check') - self.mox.StubOutWithMock(self.driver, '_live_migration_common_check') - self.mox.StubOutWithMock(self.driver.compute_rpcapi, - 'check_can_live_migrate_destination') - self.mox.StubOutWithMock(self.driver.compute_rpcapi, - 'live_migration') - - dest = 'fake_host2' - block_migration = False - disk_over_commit = False - instance = jsonutils.to_primitive(self._live_migration_instance()) - - self.driver._live_migration_src_check(self.context, instance) - self.driver._live_migration_dest_check(self.context, instance, - dest).AndReturn(dest) - self.driver._live_migration_common_check(self.context, instance, - dest) - self.driver.compute_rpcapi.check_can_live_migrate_destination( - self.context, instance, dest, block_migration, - disk_over_commit).AndReturn({}) - self.driver.compute_rpcapi.live_migration(self.context, - host=instance['host'], instance=instance, dest=dest, - block_migration=block_migration, migrate_data={}) - - self.mox.ReplayAll() - self.driver.schedule_live_migration(self.context, - instance=instance, dest=dest, - block_migration=block_migration, - disk_over_commit=disk_over_commit) - - def test_live_migration_all_checks_pass(self): - # Test live migration when all checks pass. - - self.mox.StubOutWithMock(servicegroup.API, 'service_is_up') - self.mox.StubOutWithMock(db, 'service_get_by_compute_host') - self.mox.StubOutWithMock(rpc, 'call') - self.mox.StubOutWithMock(self.driver.compute_rpcapi, - 'live_migration') - - dest = 'fake_host2' - block_migration = True - disk_over_commit = True - instance = jsonutils.to_primitive(self._live_migration_instance()) - - # Source checks - db.service_get_by_compute_host(self.context, - instance['host']).AndReturn('fake_service2') - self.servicegroup_api.service_is_up('fake_service2').AndReturn(True) - - # Destination checks (compute is up, enough memory, disk) - db.service_get_by_compute_host(self.context, - dest).AndReturn('fake_service3') - self.servicegroup_api.service_is_up('fake_service3').AndReturn(True) - # assert_compute_node_has_enough_memory() - db.service_get_by_compute_host(self.context, dest).AndReturn( - {'compute_node': [{'memory_mb': 2048, - 'free_disk_gb': 512, - 'local_gb_used': 512, - 'free_ram_mb': 1280, - 'local_gb': 1024, - 'vcpus': 4, - 'vcpus_used': 2, - 'updated_at': None, - 'hypervisor_version': 1}]}) - - # Common checks (same hypervisor, etc) - db.service_get_by_compute_host(self.context, dest).AndReturn( - {'compute_node': [{'hypervisor_type': 'xen', - 'hypervisor_version': 1}]}) - db.service_get_by_compute_host(self.context, - instance['host']).AndReturn( - {'compute_node': [{'hypervisor_type': 'xen', - 'hypervisor_version': 1, - 'cpu_info': 'fake_cpu_info'}]}) - - rpc.call(self.context, "compute.fake_host2", - {"method": 'check_can_live_migrate_destination', - "namespace": None, - "args": {'instance': instance, - 'block_migration': block_migration, - 'disk_over_commit': disk_over_commit}, - "version": compute_rpcapi.ComputeAPI.BASE_RPC_API_VERSION}, - None).AndReturn({}) - - self.driver.compute_rpcapi.live_migration(self.context, - host=instance['host'], instance=instance, dest=dest, - block_migration=block_migration, migrate_data={}) - - self.mox.ReplayAll() - result = self.driver.schedule_live_migration(self.context, - instance=instance, dest=dest, - block_migration=block_migration, - disk_over_commit=disk_over_commit) - self.assertEqual(result, None) - - def test_live_migration_instance_not_running(self): - # The instance given by instance_id is not running. - - dest = 'fake_host2' - block_migration = False - disk_over_commit = False - instance = self._live_migration_instance() - instance['power_state'] = power_state.NOSTATE - - self.assertRaises(exception.InstanceNotRunning, - self.driver.schedule_live_migration, self.context, - instance=instance, dest=dest, - block_migration=block_migration, - disk_over_commit=disk_over_commit) - - def test_live_migration_compute_src_not_exist(self): - # Raise exception when src compute node is does not exist. - - self.mox.StubOutWithMock(servicegroup.API, 'service_is_up') - self.mox.StubOutWithMock(db, 'service_get_by_compute_host') - - dest = 'fake_host2' - block_migration = False - disk_over_commit = False - instance = self._live_migration_instance() - - # Compute down - db.service_get_by_compute_host(self.context, - instance['host']).AndRaise( - exception.ComputeHostNotFound(host='fake')) - - self.mox.ReplayAll() - self.assertRaises(exception.ComputeServiceUnavailable, - self.driver.schedule_live_migration, self.context, - instance=instance, dest=dest, - block_migration=block_migration, - disk_over_commit=disk_over_commit) - - def test_live_migration_compute_src_not_alive(self): - # Raise exception when src compute node is not alive. - - self.mox.StubOutWithMock(servicegroup.API, 'service_is_up') - self.mox.StubOutWithMock(db, 'service_get_by_compute_host') - - dest = 'fake_host2' - block_migration = False - disk_over_commit = False - instance = self._live_migration_instance() - - # Compute down - db.service_get_by_compute_host(self.context, - instance['host']).AndReturn('fake_service2') - self.servicegroup_api.service_is_up('fake_service2').AndReturn(False) - - self.mox.ReplayAll() - self.assertRaises(exception.ComputeServiceUnavailable, - self.driver.schedule_live_migration, self.context, - instance=instance, dest=dest, - block_migration=block_migration, - disk_over_commit=disk_over_commit) - - def test_live_migration_compute_dest_not_exist(self): - # Raise exception when dest compute node does not exist. - - self.mox.StubOutWithMock(self.driver, '_live_migration_src_check') - self.mox.StubOutWithMock(db, 'service_get_by_compute_host') - - dest = 'fake_host2' - block_migration = False - disk_over_commit = False - instance = self._live_migration_instance() - - self.driver._live_migration_src_check(self.context, instance) - # Compute down - db.service_get_by_compute_host(self.context, - dest).AndRaise(exception.NotFound()) - - self.mox.ReplayAll() - self.assertRaises(exception.ComputeServiceUnavailable, - self.driver.schedule_live_migration, self.context, - instance=instance, dest=dest, - block_migration=block_migration, - disk_over_commit=disk_over_commit) - - def test_live_migration_compute_dest_not_alive(self): - # Raise exception when dest compute node is not alive. - - self.mox.StubOutWithMock(self.driver, '_live_migration_src_check') - self.mox.StubOutWithMock(db, 'service_get_by_compute_host') - self.mox.StubOutWithMock(servicegroup.API, 'service_is_up') - - dest = 'fake_host2' - block_migration = False - disk_over_commit = False - instance = self._live_migration_instance() - - self.driver._live_migration_src_check(self.context, instance) - db.service_get_by_compute_host(self.context, - dest).AndReturn('fake_service3') - # Compute is down - self.servicegroup_api.service_is_up('fake_service3').AndReturn(False) - - self.mox.ReplayAll() - self.assertRaises(exception.ComputeServiceUnavailable, - self.driver.schedule_live_migration, self.context, - instance=instance, dest=dest, - block_migration=block_migration, - disk_over_commit=disk_over_commit) - - def test_live_migration_dest_check_service_same_host(self): - # Confirms exception raises in case dest and src is same host. - - self.mox.StubOutWithMock(self.driver, '_live_migration_src_check') - block_migration = False - instance = self._live_migration_instance() - # make dest same as src - dest = instance['host'] - - self.driver._live_migration_src_check(self.context, instance) - - self.mox.ReplayAll() - self.assertRaises(exception.UnableToMigrateToSelf, - self.driver.schedule_live_migration, self.context, - instance=instance, dest=dest, - block_migration=block_migration, - disk_over_commit=False) - - def test_live_migration_dest_check_service_lack_memory(self): - # Confirms exception raises when dest doesn't have enough memory. - - # Flag needed to make FilterScheduler test hit memory limit since the - # default for it is to allow memory overcommit by a factor of 1.5. - self.flags(ram_allocation_ratio=1.0) - - self.mox.StubOutWithMock(self.driver, '_live_migration_src_check') - self.mox.StubOutWithMock(db, 'service_get_by_compute_host') - self.mox.StubOutWithMock(servicegroup.API, 'service_is_up') - self.mox.StubOutWithMock(self.driver, '_get_compute_info') - - dest = 'fake_host2' - block_migration = False - disk_over_commit = False - instance = self._live_migration_instance() - - self.driver._live_migration_src_check(self.context, instance) - db.service_get_by_compute_host(self.context, - dest).AndReturn('fake_service3') - self.servicegroup_api.service_is_up('fake_service3').AndReturn(True) - - self.driver._get_compute_info(self.context, dest).AndReturn( - {'memory_mb': 2048, - 'free_disk_gb': 512, - 'local_gb_used': 512, - 'free_ram_mb': 512, - 'local_gb': 1024, - 'vcpus': 4, - 'vcpus_used': 2, - 'updated_at': None}) - - self.mox.ReplayAll() - self.assertRaises(exception.MigrationError, - self.driver.schedule_live_migration, self.context, - instance=instance, dest=dest, - block_migration=block_migration, - disk_over_commit=disk_over_commit) - - def test_live_migration_different_hypervisor_type_raises(self): - # Confirm live_migration to hypervisor of different type raises. - self.mox.StubOutWithMock(self.driver, '_live_migration_src_check') - self.mox.StubOutWithMock(self.driver, '_live_migration_dest_check') - self.mox.StubOutWithMock(rpc, 'queue_get_for') - self.mox.StubOutWithMock(rpc, 'call') - self.mox.StubOutWithMock(rpc, 'cast') - self.mox.StubOutWithMock(db, 'service_get_by_compute_host') - - dest = 'fake_host2' - block_migration = False - disk_over_commit = False - instance = self._live_migration_instance() - - self.driver._live_migration_src_check(self.context, instance) - self.driver._live_migration_dest_check(self.context, instance, - dest).AndReturn(dest) - - db.service_get_by_compute_host(self.context, dest).AndReturn( - {'compute_node': [{'hypervisor_type': 'xen', - 'hypervisor_version': 1}]}) - db.service_get_by_compute_host(self.context, - instance['host']).AndReturn( - {'compute_node': [{'hypervisor_type': 'not-xen', - 'hypervisor_version': 1}]}) - - self.mox.ReplayAll() - self.assertRaises(exception.InvalidHypervisorType, - self.driver.schedule_live_migration, self.context, - instance=instance, dest=dest, - block_migration=block_migration, - disk_over_commit=disk_over_commit) - - def test_live_migration_dest_hypervisor_version_older_raises(self): - # Confirm live migration to older hypervisor raises. - self.mox.StubOutWithMock(self.driver, '_live_migration_src_check') - self.mox.StubOutWithMock(self.driver, '_live_migration_dest_check') - self.mox.StubOutWithMock(rpc, 'queue_get_for') - self.mox.StubOutWithMock(rpc, 'call') - self.mox.StubOutWithMock(rpc, 'cast') - self.mox.StubOutWithMock(db, 'service_get_by_compute_host') - - dest = 'fake_host2' - block_migration = False - disk_over_commit = False - instance = self._live_migration_instance() - - self.driver._live_migration_src_check(self.context, instance) - self.driver._live_migration_dest_check(self.context, instance, - dest).AndReturn(dest) - - db.service_get_by_compute_host(self.context, dest).AndReturn( - {'compute_node': [{'hypervisor_type': 'xen', - 'hypervisor_version': 1}]}) - db.service_get_by_compute_host(self.context, - instance['host']).AndReturn( - {'compute_node': [{'hypervisor_type': 'xen', - 'hypervisor_version': 2}]}) - self.mox.ReplayAll() - self.assertRaises(exception.DestinationHypervisorTooOld, - self.driver.schedule_live_migration, self.context, - instance=instance, dest=dest, - block_migration=block_migration, - disk_over_commit=disk_over_commit) - - def test_live_migration_dest_check_auto_set_host(self): - instance = self._live_migration_instance() - - # Confirm dest is picked by scheduler if not set. - self.mox.StubOutWithMock(self.driver, 'select_hosts') - self.mox.StubOutWithMock(flavors, 'extract_flavor') - - request_spec = {'instance_properties': instance, - 'instance_type': {}, - 'instance_uuids': [instance['uuid']], - 'image': self.image_service.show(self.context, - instance['image_ref']) - } - ignore_hosts = [instance['host']] - filter_properties = {'ignore_hosts': ignore_hosts} - - flavors.extract_flavor(instance).AndReturn({}) - self.driver.select_hosts(self.context, request_spec, - filter_properties).AndReturn(['fake_host2']) - - self.mox.ReplayAll() - result = self.driver._live_migration_dest_check(self.context, instance, - None, ignore_hosts) - self.assertEqual('fake_host2', result) - - def test_live_migration_dest_check_no_image(self): - instance = self._live_migration_instance() - instance['image_ref'] = '' - - # Confirm dest is picked by scheduler if not set. - self.mox.StubOutWithMock(self.driver, 'select_hosts') - self.mox.StubOutWithMock(flavors, 'extract_flavor') - - request_spec = {'instance_properties': instance, - 'instance_type': {}, - 'instance_uuids': [instance['uuid']], - 'image': None - } - ignore_hosts = [instance['host']] - filter_properties = {'ignore_hosts': ignore_hosts} - - flavors.extract_flavor(instance).AndReturn({}) - self.driver.select_hosts(self.context, request_spec, - filter_properties).AndReturn(['fake_host2']) - - self.mox.ReplayAll() - result = self.driver._live_migration_dest_check(self.context, instance, - None, ignore_hosts) - self.assertEqual('fake_host2', result) - - def test_live_migration_auto_set_dest(self): - instance = self._live_migration_instance() - - # Confirm scheduler picks target host if none given. - self.mox.StubOutWithMock(flavors, 'extract_flavor') - self.mox.StubOutWithMock(self.driver, '_live_migration_src_check') - self.mox.StubOutWithMock(self.driver, 'select_hosts') - self.mox.StubOutWithMock(self.driver, '_live_migration_common_check') - self.mox.StubOutWithMock(rpc, 'call') - self.mox.StubOutWithMock(self.driver.compute_rpcapi, 'live_migration') - - dest = None - block_migration = False - disk_over_commit = False - request_spec = {'instance_properties': instance, - 'instance_type': {}, - 'instance_uuids': [instance['uuid']], - 'image': self.image_service.show(self.context, - instance['image_ref']) - } - - self.driver._live_migration_src_check(self.context, instance) - - flavors.extract_flavor( - instance).MultipleTimes().AndReturn({}) - - # First selected host raises exception.InvalidHypervisorType - self.driver.select_hosts(self.context, request_spec, - {'ignore_hosts': [instance['host']]}).AndReturn(['fake_host2']) - self.driver._live_migration_common_check(self.context, instance, - 'fake_host2').AndRaise(exception.InvalidHypervisorType()) - - # Second selected host raises exception.InvalidCPUInfo - self.driver.select_hosts(self.context, request_spec, - {'ignore_hosts': [instance['host'], - 'fake_host2']}).AndReturn(['fake_host3']) - self.driver._live_migration_common_check(self.context, instance, - 'fake_host3') - rpc.call(self.context, "compute.fake_host3", - {"method": 'check_can_live_migrate_destination', - "namespace": None, - "args": {'instance': instance, - 'block_migration': block_migration, - 'disk_over_commit': disk_over_commit}, - "version": compute_rpcapi.ComputeAPI.BASE_RPC_API_VERSION}, - None).AndRaise(exception.InvalidCPUInfo(reason="")) - - # Third selected host pass all checks - self.driver.select_hosts(self.context, request_spec, - {'ignore_hosts': [instance['host'], - 'fake_host2', - 'fake_host3']}).AndReturn(['fake_host4']) - self.driver._live_migration_common_check(self.context, instance, - 'fake_host4') - rpc.call(self.context, "compute.fake_host4", - {"method": 'check_can_live_migrate_destination', - "namespace": None, - "args": {'instance': instance, - 'block_migration': block_migration, - 'disk_over_commit': disk_over_commit}, - "version": compute_rpcapi.ComputeAPI.BASE_RPC_API_VERSION}, - None).AndReturn({}) - self.driver.compute_rpcapi.live_migration(self.context, - host=instance['host'], instance=instance, dest='fake_host4', - block_migration=block_migration, migrate_data={}) - - self.mox.ReplayAll() - result = self.driver.schedule_live_migration(self.context, - instance=instance, dest=dest, - block_migration=block_migration, - disk_over_commit=disk_over_commit) - self.assertEqual(result, None) - def test_handle_schedule_error_adds_instance_fault(self): instance = {'uuid': 'fake-uuid'} self.mox.StubOutWithMock(db, 'instance_update_and_get_original') |