def test_live_migration_dest_check_service_lack_memory(self): """Confirms exception raises when dest doesn't have enough memory.""" self.mox.StubOutWithMock(self.driver, "_live_migration_src_check") self.mox.StubOutWithMock(db, "service_get_all_compute_by_host") self.mox.StubOutWithMock(utils, "service_is_up") self.mox.StubOutWithMock(self.driver, "_get_compute_info") self.mox.StubOutWithMock(db, "instance_get_all_by_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) db.service_get_all_compute_by_host(self.context, dest).AndReturn(["fake_service3"]) utils.service_is_up("fake_service3").AndReturn(True) self.driver._get_compute_info(self.context, dest).AndReturn({"memory_mb": 2048}) db.instance_get_all_by_host(self.context, dest).AndReturn([dict(memory_mb=1024), dict(memory_mb=512)]) 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_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_all_compute_by_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) db.service_get_all_compute_by_host(self.context, dest).AndReturn( [{"compute_node": [{"hypervisor_type": "xen", "hypervisor_version": 1}]}] ) db.service_get_all_compute_by_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_service_same_host(self): """Confirms exception raises in case dest and src is same host.""" self.mox.StubOutWithMock(self.driver, "_live_migration_src_check") self.mox.StubOutWithMock(db, "service_get_all_compute_by_host") self.mox.StubOutWithMock(utils, "service_is_up") block_migration = False disk_over_commit = False instance = self._live_migration_instance() # make dest same as src dest = instance["host"] self.driver._live_migration_src_check(self.context, instance) db.service_get_all_compute_by_host(self.context, dest).AndReturn(["fake_service3"]) utils.service_is_up("fake_service3").AndReturn(True) 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_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_all_compute_by_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) db.service_get_all_compute_by_host(self.context, dest).AndReturn( [{'compute_node': [{'hypervisor_type': 'xen', 'hypervisor_version': 1}]}]) db.service_get_all_compute_by_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_compute_dest_not_alive(self): """Raise exception when dest compute node is not alive.""" self.mox.StubOutWithMock(db, 'instance_get') self.mox.StubOutWithMock(self.driver, '_live_migration_src_check') self.mox.StubOutWithMock(db, 'service_get_all_compute_by_host') self.mox.StubOutWithMock(utils, 'service_is_up') dest = 'fake_host2' block_migration = False instance = self._live_migration_instance() instance_id = instance['id'] db.instance_get(self.context, instance_id).AndReturn(instance) self.driver._live_migration_src_check(self.context, instance) db.service_get_all_compute_by_host(self.context, dest).AndReturn(['fake_service3']) # Compute is down utils.service_is_up('fake_service3').AndReturn(False) self.mox.ReplayAll() self.assertRaises(exception.ComputeServiceUnavailable, self.driver.schedule_live_migration, self.context, instance_id=instance_id, dest=dest, block_migration=block_migration)
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') self.mox.StubOutWithMock(db, 'service_get_all_compute_by_host') self.mox.StubOutWithMock(utils, 'service_is_up') block_migration = False disk_over_commit = False instance = self._live_migration_instance() # make dest same as src dest = instance['host'] self.driver._live_migration_src_check(self.context, instance) db.service_get_all_compute_by_host(self.context, dest).AndReturn(['fake_service3']) utils.service_is_up('fake_service3').AndReturn(True) 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_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_all_compute_by_host') self.mox.StubOutWithMock(utils, '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_all_compute_by_host(self.context, dest).AndReturn(['fake_service3']) # Compute is down utils.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_compute_src_not_alive(self): """Raise exception when src compute node is not alive.""" self.mox.StubOutWithMock(db, 'instance_get') self.mox.StubOutWithMock(utils, 'service_is_up') self.mox.StubOutWithMock(db, 'service_get_all_compute_by_host') dest = 'fake_host2' block_migration = False instance = self._live_migration_instance() instance_id = instance['id'] db.instance_get(self.context, instance_id).AndReturn(instance) # Compute down db.service_get_all_compute_by_host( self.context, instance['host']).AndReturn(['fake_service2']) utils.service_is_up('fake_service2').AndReturn(False) self.mox.ReplayAll() self.assertRaises(exception.ComputeServiceUnavailable, self.driver.schedule_live_migration, self.context, instance_id=instance_id, dest=dest, block_migration=block_migration)
def test_live_migration_dest_check_service_lack_memory(self): """Confirms exception raises when dest doesn't have enough memory.""" self.mox.StubOutWithMock(self.driver, '_live_migration_src_check') self.mox.StubOutWithMock(db, 'service_get_all_compute_by_host') self.mox.StubOutWithMock(servicegroup.API, 'service_is_up') self.mox.StubOutWithMock(self.driver, '_get_compute_info') self.mox.StubOutWithMock(db, 'instance_get_all_by_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) db.service_get_all_compute_by_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}) db.instance_get_all_by_host(self.context, dest).AndReturn( [dict(memory_mb=1024), dict(memory_mb=512)]) 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_compute_src_not_alive(self): """Raise exception when src compute node is not alive.""" self.mox.StubOutWithMock(db, 'instance_get') self.mox.StubOutWithMock(db, 'service_get_all_by_topic') self.mox.StubOutWithMock(utils, 'service_is_up') self.mox.StubOutWithMock(db, 'service_get_all_compute_by_host') dest = 'fake_host2' block_migration = False instance = self._live_migration_instance() db.instance_get(self.context, instance['id']).AndReturn(instance) # Volume up db.service_get_all_by_topic(self.context, 'volume').AndReturn( ['fake_service']) utils.service_is_up('fake_service').AndReturn(True) # Compute down db.service_get_all_compute_by_host(self.context, instance['host']).AndReturn(['fake_service2']) utils.service_is_up('fake_service2').AndReturn(False) self.mox.ReplayAll() self.assertRaises(exception.ComputeServiceUnavailable, self.driver.schedule_live_migration, self.context, instance_id=instance['id'], dest=dest, block_migration=block_migration)
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_all_compute_by_host") self.mox.StubOutWithMock(utils, "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_all_compute_by_host(self.context, dest).AndReturn(["fake_service3"]) # Compute is down utils.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_different_hypervisor_type_raises(self): """Confirm live_migration to hypervisor of different type raises""" self.mox.StubOutWithMock(db, 'instance_get') 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_all_compute_by_host') dest = 'fake_host2' block_migration = False disk_over_commit = False instance = self._live_migration_instance() instance_id = instance['id'] db.instance_get(self.context, instance_id).AndReturn(instance) self.driver._live_migration_src_check(self.context, instance) self.driver._live_migration_dest_check(self.context, instance, dest) db.service_get_all_compute_by_host(self.context, dest).AndReturn( [{'compute_node': [{'hypervisor_type': 'xen', 'hypervisor_version': 1}]}]) db.service_get_all_compute_by_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_id=instance_id, 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(db, 'instance_get') self.mox.StubOutWithMock(self.driver, '_live_migration_src_check') self.mox.StubOutWithMock(db, 'service_get_all_compute_by_host') self.mox.StubOutWithMock(utils, 'service_is_up') block_migration = False disk_over_commit = False instance = self._live_migration_instance() # make dest same as src dest = instance['host'] db.instance_get(self.context, instance['id']).AndReturn(instance) self.driver._live_migration_src_check(self.context, instance) db.service_get_all_compute_by_host(self.context, dest).AndReturn(['fake_service3']) utils.service_is_up('fake_service3').AndReturn(True) self.mox.ReplayAll() self.assertRaises(exception.UnableToMigrateToSelf, self.driver.schedule_live_migration, self.context, instance_id=instance['id'], dest=dest, block_migration=block_migration, disk_over_commit=False)
def test_live_migration_different_hypervisor_type_raises(self): """Confirm live_migration to hypervisor of different type raises""" self.mox.StubOutWithMock(db, 'instance_get') 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_all_compute_by_host') dest = 'fake_host2' block_migration = False disk_over_commit = False instance = self._live_migration_instance() instance_id = instance['id'] db.instance_get(self.context, instance_id).AndReturn(instance) self.driver._live_migration_src_check(self.context, instance) self.driver._live_migration_dest_check(self.context, instance, dest) db.service_get_all_compute_by_host(self.context, dest).AndReturn( [{'compute_node': [{'hypervisor_type': 'xen', 'hypervisor_version': 1}]}]) db.service_get_all_compute_by_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_id=instance_id, dest=dest, block_migration=block_migration, disk_over_commit=disk_over_commit)
def test_live_migration_dest_check_service_lack_memory(self): """Confirms exception raises when dest doesn't have enough memory.""" self.mox.StubOutWithMock(db, 'instance_get') self.mox.StubOutWithMock(self.driver, '_live_migration_src_check') self.mox.StubOutWithMock(db, 'service_get_all_compute_by_host') self.mox.StubOutWithMock(utils, 'service_is_up') self.mox.StubOutWithMock(self.driver, '_get_compute_info') self.mox.StubOutWithMock(db, 'instance_get_all_by_host') dest = 'fake_host2' block_migration = False disk_over_commit = False instance = self._live_migration_instance() db.instance_get(self.context, instance['id']).AndReturn(instance) self.driver._live_migration_src_check(self.context, instance) db.service_get_all_compute_by_host(self.context, dest).AndReturn(['fake_service3']) utils.service_is_up('fake_service3').AndReturn(True) self.driver._get_compute_info(self.context, dest, 'memory_mb').AndReturn(2048) db.instance_get_all_by_host(self.context, dest).AndReturn( [dict(memory_mb=1024), dict(memory_mb=512)]) self.mox.ReplayAll() self.assertRaises(exception.MigrationError, self.driver.schedule_live_migration, self.context, instance_id=instance['id'], dest=dest, block_migration=block_migration, disk_over_commit=disk_over_commit)
def _live_migration_common_check(self, context, instance_ref, dest, block_migration, disk_over_commit): """Live migration common check routine. Below checkings are followed by http://wiki.libvirt.org/page/TodoPreMigrationChecks :param context: security context :param instance_ref: nova.db.sqlalchemy.models.Instance object :param dest: destination host :param block_migration: if true, block_migration. :param disk_over_commit: if True, consider real(not virtual) disk size. """ # Checking shared storage connectivity # if block migration, instances_paths should not be on shared storage. shared = self.mounted_on_same_shared_storage(context, instance_ref, dest) if block_migration: if shared: reason = _("Block migration can not be used " "with shared storage.") raise exception.InvalidSharedStorage(reason=reason, path=dest) elif not shared: reason = _("Live migration can not be used " "without shared storage.") raise exception.InvalidSharedStorage(reason=reason, path=dest) # Checking destination host exists. dservice_refs = db.service_get_all_compute_by_host(context, dest) dservice_ref = dservice_refs[0]["compute_node"][0] # Checking original host( where instance was launched at) exists. try: oservice_refs = db.service_get_all_compute_by_host(context, instance_ref["host"]) except exception.NotFound: raise exception.SourceHostUnavailable() oservice_ref = oservice_refs[0]["compute_node"][0] # Checking hypervisor is same. orig_hypervisor = oservice_ref["hypervisor_type"] dest_hypervisor = dservice_ref["hypervisor_type"] if orig_hypervisor != dest_hypervisor: raise exception.InvalidHypervisorType() # Checkng hypervisor version. orig_hypervisor = oservice_ref["hypervisor_version"] dest_hypervisor = dservice_ref["hypervisor_version"] if orig_hypervisor > dest_hypervisor: raise exception.DestinationHypervisorTooOld() # Checking cpuinfo. try: self.compute_rpcapi.compare_cpu(context, oservice_ref["cpu_info"], dest) except exception.InvalidCPUInfo: src = instance_ref["host"] LOG.exception(_("host %(dest)s is not compatible with " "original host %(src)s.") % locals()) raise
def _live_migration_common_check(self, context, instance_ref, dest): """Live migration common check routine. Below checkings are followed by http://wiki.libvirt.org/page/TodoPreMigrationChecks :param context: security context :param instance_ref: nova.db.sqlalchemy.models.Instance object :param dest: destination host """ # Checking shared storage connectivity self.mounted_on_same_shared_storage(context, instance_ref, dest) # Checking dest exists. dservice_refs = db.service_get_all_compute_by_host(context, dest) dservice_ref = dservice_refs[0]['compute_node'][0] # Checking original host( where instance was launched at) exists. try: oservice_refs = db.service_get_all_compute_by_host(context, instance_ref['launched_on']) except exception.NotFound: raise exception.Invalid(_("host %s where instance was launched " "does not exist.") % instance_ref['launched_on']) oservice_ref = oservice_refs[0]['compute_node'][0] # Checking hypervisor is same. orig_hypervisor = oservice_ref['hypervisor_type'] dest_hypervisor = dservice_ref['hypervisor_type'] if orig_hypervisor != dest_hypervisor: raise exception.Invalid(_("Different hypervisor type" "(%(orig_hypervisor)s->" "%(dest_hypervisor)s)')" % locals())) # Checkng hypervisor version. orig_hypervisor = oservice_ref['hypervisor_version'] dest_hypervisor = dservice_ref['hypervisor_version'] if orig_hypervisor > dest_hypervisor: raise exception.Invalid(_("Older hypervisor version" "(%(orig_hypervisor)s->" "%(dest_hypervisor)s)") % locals()) # Checking cpuinfo. try: rpc.call(context, db.queue_get_for(context, FLAGS.compute_topic, dest), {"method": 'compare_cpu', "args": {'cpu_info': oservice_ref['cpu_info']}}) except rpc.RemoteError: src = instance_ref['host'] logging.exception(_("host %(dest)s is not compatible with " "original host %(src)s.") % locals()) raise
def _live_migration_common_check(self, context, instance_ref, dest): """Live migration common check routine. Below checkings are followed by http://wiki.libvirt.org/page/TodoPreMigrationChecks :param context: security context :param instance_ref: nova.db.sqlalchemy.models.Instance object :param dest: destination host """ # Checking shared storage connectivity self.mounted_on_same_shared_storage(context, instance_ref, dest) # Checking dest exists. dservice_refs = db.service_get_all_compute_by_host(context, dest) dservice_ref = dservice_refs[0]['compute_node'][0] # Checking original host( where instance was launched at) exists. try: oservice_refs = db.service_get_all_compute_by_host( context, instance_ref['launched_on']) except exception.NotFound: raise exception.SourceHostUnavailable() oservice_ref = oservice_refs[0]['compute_node'][0] # Checking hypervisor is same. orig_hypervisor = oservice_ref['hypervisor_type'] dest_hypervisor = dservice_ref['hypervisor_type'] if orig_hypervisor != dest_hypervisor: raise exception.InvalidHypervisorType() # Checkng hypervisor version. orig_hypervisor = oservice_ref['hypervisor_version'] dest_hypervisor = dservice_ref['hypervisor_version'] if orig_hypervisor > dest_hypervisor: raise exception.DestinationHypervisorTooOld() # Checking cpuinfo. try: rpc.call( context, db.queue_get_for(context, FLAGS.compute_topic, dest), { "method": 'compare_cpu', "args": { 'cpu_info': oservice_ref['cpu_info'] } }) except rpc.RemoteError: src = instance_ref['host'] logging.exception( _("host %(dest)s is not compatible with " "original host %(src)s.") % locals()) raise
def test_block_migration_dest_check_service_lack_disk(self): """Confirms exception raises when dest doesn't have enough disk.""" self.mox.StubOutWithMock(db, 'instance_get') self.mox.StubOutWithMock(self.driver, '_live_migration_src_check') self.mox.StubOutWithMock(db, 'service_get_all_compute_by_host') self.mox.StubOutWithMock(utils, 'service_is_up') self.mox.StubOutWithMock(self.driver, 'assert_compute_node_has_enough_memory') self.mox.StubOutWithMock(self.driver, '_get_compute_info') self.mox.StubOutWithMock(db, 'instance_get_all_by_host') self.mox.StubOutWithMock(rpc, 'queue_get_for') self.mox.StubOutWithMock(rpc, 'call') dest = 'fake_host2' block_migration = True disk_over_commit = True instance = self._live_migration_instance() db.instance_get(self.context, instance['id']).AndReturn(instance) self.driver._live_migration_src_check(self.context, instance) db.service_get_all_compute_by_host(self.context, dest).AndReturn(['fake_service3']) utils.service_is_up('fake_service3').AndReturn(True) # Enough memory self.driver.assert_compute_node_has_enough_memory(self.context, instance, dest) # Not enough disk self.driver._get_compute_info(self.context, dest, 'disk_available_least').AndReturn(1023) rpc.queue_get_for(self.context, FLAGS.compute_topic, instance['host']).AndReturn('src_queue') instance_disk_info_msg = { 'method': 'get_instance_disk_info', 'args': { 'instance_name': instance['name'], }, 'version': compute_rpcapi.ComputeAPI.RPC_API_VERSION, } instance_disk_info = [{'disk_size': 1024 * (1024 ** 3)}] rpc.call(self.context, 'src_queue', instance_disk_info_msg, None).AndReturn(jsonutils.dumps(instance_disk_info)) self.mox.ReplayAll() self.assertRaises(exception.MigrationError, self.driver.schedule_live_migration, self.context, instance_id=instance['id'], dest=dest, block_migration=block_migration, disk_over_commit=disk_over_commit)
def test_block_migration_dest_check_service_lack_disk(self): """Confirms exception raises when dest doesn't have enough disk.""" self.mox.StubOutWithMock(db, 'instance_get') self.mox.StubOutWithMock(self.driver, '_live_migration_src_check') self.mox.StubOutWithMock(db, 'service_get_all_compute_by_host') self.mox.StubOutWithMock(utils, 'service_is_up') self.mox.StubOutWithMock(self.driver, 'assert_compute_node_has_enough_memory') self.mox.StubOutWithMock(self.driver, '_get_compute_info') self.mox.StubOutWithMock(db, 'instance_get_all_by_host') self.mox.StubOutWithMock(rpc, 'queue_get_for') self.mox.StubOutWithMock(rpc, 'call') dest = 'fake_host2' block_migration = True disk_over_commit = True instance = self._live_migration_instance() db.instance_get(self.context, instance['id']).AndReturn(instance) self.driver._live_migration_src_check(self.context, instance) db.service_get_all_compute_by_host(self.context, dest).AndReturn(['fake_service3']) utils.service_is_up('fake_service3').AndReturn(True) # Enough memory self.driver.assert_compute_node_has_enough_memory(self.context, instance, dest) # Not enough disk self.driver._get_compute_info(self.context, dest, 'disk_available_least').AndReturn(1023) rpc.queue_get_for(self.context, FLAGS.compute_topic, instance['host']).AndReturn('src_queue') instance_disk_info_msg = { 'method': 'get_instance_disk_info', 'args': { 'instance_name': instance['name'], }, 'version': compute_rpcapi.ComputeAPI.BASE_RPC_API_VERSION, } instance_disk_info = [{'disk_size': 1024 * (1024 ** 3)}] rpc.call(self.context, 'src_queue', instance_disk_info_msg, None).AndReturn(jsonutils.dumps(instance_disk_info)) self.mox.ReplayAll() self.assertRaises(exception.MigrationError, self.driver.schedule_live_migration, self.context, instance_id=instance['id'], dest=dest, block_migration=block_migration, disk_over_commit=disk_over_commit)
def test_live_migration_dest_host_incompatable_cpu_raises(self): self.mox.StubOutWithMock(db, 'instance_get') self.mox.StubOutWithMock(self.driver, '_live_migration_src_check') self.mox.StubOutWithMock(self.driver, '_live_migration_dest_check') self.mox.StubOutWithMock(db, 'queue_get_for') self.mox.StubOutWithMock(rpc, 'call') self.mox.StubOutWithMock(rpc, 'cast') self.mox.StubOutWithMock(db, 'service_get_all_compute_by_host') dest = 'fake_host2' block_migration = False disk_over_commit = False instance = self._live_migration_instance() db.instance_get(self.context, instance['id']).AndReturn(instance) self.driver._live_migration_src_check(self.context, instance) self.driver._live_migration_dest_check(self.context, instance, dest, block_migration, disk_over_commit) db.queue_get_for(self.context, FLAGS.compute_topic, dest).AndReturn('dest_queue') db.queue_get_for(self.context, FLAGS.compute_topic, instance['host']).AndReturn('src_queue') tmp_filename = 'test-filename' rpc.call(self.context, 'dest_queue', {'method': 'create_shared_storage_test_file'} ).AndReturn(tmp_filename) rpc.call(self.context, 'src_queue', {'method': 'check_shared_storage_test_file', 'args': {'filename': tmp_filename}}).AndReturn(True) rpc.call(self.context, 'dest_queue', {'method': 'cleanup_shared_storage_test_file', 'args': {'filename': tmp_filename}}) db.service_get_all_compute_by_host(self.context, dest).AndReturn( [{'compute_node': [{'hypervisor_type': 'xen', 'hypervisor_version': 1}]}]) db.service_get_all_compute_by_host(self.context, instance['host']).AndReturn( [{'compute_node': [{'hypervisor_type': 'xen', 'hypervisor_version': 1, 'cpu_info': 'fake_cpu_info'}]}]) db.queue_get_for(self.context, FLAGS.compute_topic, dest).AndReturn('dest_queue') rpc.call(self.context, 'dest_queue', {'method': 'compare_cpu', 'args': {'cpu_info': 'fake_cpu_info'}}).AndRaise( rpc.RemoteError()) self.mox.ReplayAll() self.assertRaises(rpc_common.RemoteError, self.driver.schedule_live_migration, self.context, instance_id=instance['id'], dest=dest, block_migration=block_migration)
def test_describe_host(self): """ Makes sure that describe_host returns the correct information given our fake input. """ ctx = context.get_admin_context() self.mox.StubOutWithMock(db, 'service_get_all_compute_by_host') host_name = 'host_c1' db.service_get_all_compute_by_host(ctx, host_name).AndReturn( [{'host': 'fake_host', 'compute_node': [ {'vcpus': 4, 'vcpus_used': 1, 'memory_mb': 8192, 'memory_mb_used': 2048, 'local_gb': 1024, 'local_gb_used': 648} ] }]) self.mox.StubOutWithMock(db, 'instance_get_all_by_host') db.instance_get_all_by_host(ctx, 'fake_host').AndReturn( [{'project_id': 42, 'vcpus': 1, 'memory_mb': 2048, 'root_gb': 648, 'ephemeral_gb': 0, }]) self.mox.ReplayAll() result = self.api.describe_host(ctx, host_name) self.assertEqual(result, [{'resource': {'cpu': 4, 'disk_gb': 1024, 'host': 'host_c1', 'memory_mb': 8192, 'project': '(total)'}}, {'resource': {'cpu': 1, 'disk_gb': 648, 'host': 'host_c1', 'memory_mb': 2048, 'project': '(used_now)'}}, {'resource': {'cpu': 1, 'disk_gb': 648, 'host': 'host_c1', 'memory_mb': 2048, 'project': '(used_max)'}}, {'resource': {'cpu': 1, 'disk_gb': 648, 'host': 'host_c1', 'memory_mb': 2048, 'project': 42}}] ) self.mox.VerifyAll()
def test_show_host_resources(self): host = 'fake_host' computes = [{'host': host, 'compute_node': [{'vcpus': 4, 'vcpus_used': 2, 'memory_mb': 1024, 'memory_mb_used': 512, 'local_gb': 1024, 'local_gb_used': 512}]}] instances = [{'project_id': 'project1', 'vcpus': 1, 'memory_mb': 128, 'root_gb': 128, 'ephemeral_gb': 0}, {'project_id': 'project1', 'vcpus': 2, 'memory_mb': 256, 'root_gb': 384, 'ephemeral_gb': 0}, {'project_id': 'project2', 'vcpus': 2, 'memory_mb': 256, 'root_gb': 256, 'ephemeral_gb': 0}] self.mox.StubOutWithMock(db, 'service_get_all_compute_by_host') self.mox.StubOutWithMock(db, 'instance_get_all_by_host') db.service_get_all_compute_by_host(self.context, host).AndReturn( computes) db.instance_get_all_by_host(self.context, host).AndReturn(instances) self.mox.ReplayAll() result = self.manager.show_host_resources(self.context, host) expected = {'usage': {'project1': {'memory_mb': 384, 'vcpus': 3, 'root_gb': 512, 'ephemeral_gb': 0}, 'project2': {'memory_mb': 256, 'vcpus': 2, 'root_gb': 256, 'ephemeral_gb': 0}}, 'resource': {'vcpus': 4, 'vcpus_used': 2, 'local_gb': 1024, 'local_gb_used': 512, 'memory_mb': 1024, 'memory_mb_used': 512}} self.assertDictMatch(result, expected)
def test_show_host_resources(self): host = 'fake_host' computes = [{'host': host, 'compute_node': [{'vcpus': 4, 'vcpus_used': 2, 'memory_mb': 1024, 'memory_mb_used': 512, 'local_gb': 1024, 'local_gb_used': 512}]}] instances = [{'project_id': 'project1', 'vcpus': 1, 'memory_mb': 128, 'root_gb': 128, 'ephemeral_gb': 0}, {'project_id': 'project1', 'vcpus': 2, 'memory_mb': 256, 'root_gb': 384, 'ephemeral_gb': 0}, {'project_id': 'project2', 'vcpus': 2, 'memory_mb': 256, 'root_gb': 256, 'ephemeral_gb': 0}] self.mox.StubOutWithMock(db, 'service_get_all_compute_by_host') self.mox.StubOutWithMock(db, 'instance_get_all_by_host') db.service_get_all_compute_by_host(self.context, host).AndReturn( computes) db.instance_get_all_by_host(self.context, host).AndReturn(instances) self.mox.ReplayAll() result = self.manager.show_host_resources(self.context, host) expected = {'usage': {'project1': {'memory_mb': 384, 'vcpus': 3, 'root_gb': 512, 'ephemeral_gb': 0}, 'project2': {'memory_mb': 256, 'vcpus': 2, 'root_gb': 256, 'ephemeral_gb': 0}}, 'resource': {'vcpus': 4, 'vcpus_used': 2, 'local_gb': 1024, 'local_gb_used': 512, 'memory_mb': 1024, 'memory_mb_used': 512}} self.assertThat(result, matchers.DictMatches(expected))
def _live_migration_dest_check(self, context, instance_ref, dest): """Live migration check routine (for destination host). :param context: security context :param instance_ref: nova.db.sqlalchemy.models.Instance object :param dest: destination host """ # Checking dest exists and compute node. dservice_refs = db.service_get_all_compute_by_host(context, dest) dservice_ref = dservice_refs[0] # Checking dest host is alive. if not self.service_is_up(dservice_ref): raise exception.Invalid(_("%s is not alive(time " "synchronize problem?)") % dest) # Checking whether The host where instance is running # and dest is not same. src = instance_ref['host'] if dest == src: ec2_id = instance_ref['hostname'] raise exception.Invalid(_("%(dest)s is where %(ec2_id)s is " "running now. choose other host.") % locals()) # Checking dst host still has enough capacities. self.assert_compute_node_has_enough_resources(context, instance_ref, dest)
def _live_migration_src_check(self, context, instance_ref): """Live migration check routine (for src host). :param context: security context :param instance_ref: nova.db.sqlalchemy.models.Instance object """ # Checking instance is running. if (power_state.RUNNING != instance_ref['state'] or \ 'running' != instance_ref['state_description']): ec2_id = instance_ref['hostname'] raise exception.InstanceNotRunning(instance_id=ec2_id) # Checing volume node is running when any volumes are mounted # to the instance. if len(instance_ref['volumes']) != 0: services = db.service_get_all_by_topic(context, 'volume') if len(services) < 1 or not self.service_is_up(services[0]): raise exception.VolumeServiceUnavailable() # Checking src host exists and compute node src = instance_ref['host'] services = db.service_get_all_compute_by_host(context, src) # Checking src host is alive. if not self.service_is_up(services[0]): raise exception.ComputeServiceUnavailable(host=src)
def update_available_resource(self, ctxt, host): """Updates compute manager resource info on ComputeNode table. This method is called when nova-coompute launches, and whenever admin executes "nova-manage service update_resource". :param ctxt: security context :param host: hostname that compute manager is currently running """ dic = self._max_baremetal_resources(ctxt) #dic = self._sum_baremetal_resources(ctxt) dic['hypervisor_type'] = self.get_hypervisor_type() dic['hypervisor_version'] = self.get_hypervisor_version() dic['cpu_info'] = 'baremetal cpu' try: service_ref = db.service_get_all_compute_by_host(ctxt, host)[0] except exception.NotFound: raise exception.ComputeServiceUnavailable(host=host) dic['service_id'] = service_ref['id'] compute_node_ref = service_ref['compute_node'] if not compute_node_ref: LOG.info(_('Compute_service record created for %s ') % host) db.compute_node_create(ctxt, dic) else: LOG.info(_('Compute_service record updated for %s ') % host) db.compute_node_update(ctxt, compute_node_ref[0]['id'], dic)
def update_available_resource(self, ctxt, host): """Updates compute manager resource info on ComputeNode table. Since we don't have a real hypervisor, pretend we have lots of disk and ram. """ try: service_ref = db.service_get_all_compute_by_host(ctxt, host)[0] except exception.NotFound: raise exception.ComputeServiceUnavailable(host=host) # Updating host information dic = { "vcpus": 1, "memory_mb": 4096, "local_gb": 1028, "vcpus_used": 0, "memory_mb_used": 0, "local_gb_used": 0, "hypervisor_type": "fake", "hypervisor_version": "1.0", "service_id": service_ref["id"], "cpu_info": "?", } compute_node_ref = service_ref["compute_node"] if not compute_node_ref: LOG.info(_("Compute_service record created for %s ") % host) db.compute_node_create(ctxt, dic) else: LOG.info(_("Compute_service record updated for %s ") % host) db.compute_node_update(ctxt, compute_node_ref[0]["id"], dic)
def assert_compute_node_has_enough_resources(self, context, instance_ref, dest): """Checks if destination host has enough resource for live migration. Currently, only memory checking has been done. If storage migration(block migration, meaning live-migration without any shared storage) will be available, local storage checking is also necessary. :param context: security context :param instance_ref: nova.db.sqlalchemy.models.Instance object :param dest: destination host """ # Getting instance information ec2_id = instance_ref['hostname'] # Getting host information service_refs = db.service_get_all_compute_by_host(context, dest) compute_node_ref = service_refs[0]['compute_node'][0] mem_total = int(compute_node_ref['memory_mb']) mem_used = int(compute_node_ref['memory_mb_used']) mem_avail = mem_total - mem_used mem_inst = instance_ref['memory_mb'] if mem_avail <= mem_inst: raise exception.NotEmpty(_("Unable to migrate %(ec2_id)s " "to destination: %(dest)s " "(host:%(mem_avail)s " "<= instance:%(mem_inst)s)") % locals())
def _live_migration_src_check(self, context, instance_ref): """Live migration check routine (for src host). :param context: security context :param instance_ref: nova.db.sqlalchemy.models.Instance object """ # Checking instance is running. if (power_state.RUNNING != instance_ref['state'] or \ 'running' != instance_ref['state_description']): ec2_id = instance_ref['hostname'] raise exception.Invalid(_('Instance(%s) is not running') % ec2_id) # Checing volume node is running when any volumes are mounted # to the instance. if len(instance_ref['volumes']) != 0: services = db.service_get_all_by_topic(context, 'volume') if len(services) < 1 or not self.service_is_up(services[0]): raise exception.Invalid( _("volume node is not alive" "(time synchronize problem?)")) # Checking src host exists and compute node src = instance_ref['host'] services = db.service_get_all_compute_by_host(context, src) # Checking src host is alive. if not self.service_is_up(services[0]): raise exception.Invalid( _("%s is not alive(time " "synchronize problem?)") % src)
def _live_migration_dest_check(self, context, instance_ref, dest): """Live migration check routine (for destination host). :param context: security context :param instance_ref: nova.db.sqlalchemy.models.Instance object :param dest: destination host """ # Checking dest exists and compute node. dservice_refs = db.service_get_all_compute_by_host(context, dest) dservice_ref = dservice_refs[0] # Checking dest host is alive. if not self.service_is_up(dservice_ref): raise exception.Invalid( _("%s is not alive(time " "synchronize problem?)") % dest) # Checking whether The host where instance is running # and dest is not same. src = instance_ref['host'] if dest == src: ec2_id = instance_ref['hostname'] raise exception.Invalid( _("%(dest)s is where %(ec2_id)s is " "running now. choose other host.") % locals()) # Checking dst host still has enough capacities. self.assert_compute_node_has_enough_resources(context, instance_ref, dest)
def assert_compute_node_has_enough_resources(self, context, instance_ref, dest): """Checks if destination host has enough resource for live migration. Currently, only memory checking has been done. If storage migration(block migration, meaning live-migration without any shared storage) will be available, local storage checking is also necessary. :param context: security context :param instance_ref: nova.db.sqlalchemy.models.Instance object :param dest: destination host """ # Getting instance information ec2_id = instance_ref['hostname'] # Getting host information service_refs = db.service_get_all_compute_by_host(context, dest) compute_node_ref = service_refs[0]['compute_node'][0] mem_total = int(compute_node_ref['memory_mb']) mem_used = int(compute_node_ref['memory_mb_used']) mem_avail = mem_total - mem_used mem_inst = instance_ref['memory_mb'] if mem_avail <= mem_inst: raise exception.NotEmpty( _("Unable to migrate %(ec2_id)s " "to destination: %(dest)s " "(host:%(mem_avail)s " "<= instance:%(mem_inst)s)") % locals())
def _live_migration_dest_check(self, context, instance_ref, dest, block_migration, disk_over_commit): """Live migration check routine (for destination host). :param context: security context :param instance_ref: nova.db.sqlalchemy.models.Instance object :param dest: destination host :param block_migration: if true, block_migration. :param disk_over_commit: if True, consider real(not virtual) disk size. """ # Checking dest exists and compute node. dservice_refs = db.service_get_all_compute_by_host(context, dest) dservice_ref = dservice_refs[0] # Checking dest host is alive. if not utils.service_is_up(dservice_ref): raise exception.ComputeServiceUnavailable(host=dest) # Checking whether The host where instance is running # and dest is not same. src = instance_ref['host'] if dest == src: raise exception.UnableToMigrateToSelf( instance_id=instance_ref['uuid'], host=dest) # Checking dst host still has enough capacities. self.assert_compute_node_has_enough_resources(context, instance_ref, dest, block_migration, disk_over_commit)
def _live_migration_src_check(self, context, instance_ref): """Live migration check routine (for src host). :param context: security context :param instance_ref: nova.db.sqlalchemy.models.Instance object """ # Checking instance is running. if (power_state.RUNNING != instance_ref['state'] or \ 'running' != instance_ref['state_description']): ec2_id = instance_ref['hostname'] raise exception.Invalid(_('Instance(%s) is not running') % ec2_id) # Checing volume node is running when any volumes are mounted # to the instance. if len(instance_ref['volumes']) != 0: services = db.service_get_all_by_topic(context, 'volume') if len(services) < 1 or not self.service_is_up(services[0]): raise exception.Invalid(_("volume node is not alive" "(time synchronize problem?)")) # Checking src host exists and compute node src = instance_ref['host'] services = db.service_get_all_compute_by_host(context, src) # Checking src host is alive. if not self.service_is_up(services[0]): raise exception.Invalid(_("%s is not alive(time " "synchronize problem?)") % src)
def update_available_resource(self, ctxt, host): """Updates compute manager resource info on ComputeNode table. Since we don't have a real hypervisor, pretend we have lots of disk and ram. """ try: service_ref = db.service_get_all_compute_by_host(ctxt, host)[0] except exception.NotFound: raise exception.ComputeServiceUnavailable(host=host) # Updating host information dic = {'vcpus': 1, 'memory_mb': 4096, 'local_gb': 1028, 'vcpus_used': 0, 'memory_mb_used': 0, 'local_gb_used': 0, 'hypervisor_type': 'fake', 'hypervisor_version': '1.0', 'service_id': service_ref['id'], 'cpu_info': '?'} compute_node_ref = service_ref['compute_node'] if not compute_node_ref: LOG.info(_('Compute_service record created for %s ') % host) db.compute_node_create(ctxt, dic) else: LOG.info(_('Compute_service record updated for %s ') % host) db.compute_node_update(ctxt, compute_node_ref[0]['id'], dic)
def _live_migration_src_check(self, context, instance_ref): """Live migration check routine (for src host). :param context: security context :param instance_ref: nova.db.sqlalchemy.models.Instance object """ # Checking instance is running. if instance_ref['power_state'] != power_state.RUNNING and not ( FLAGS.libvirt_type == 'xen' and instance_ref['power_state'] == power_state.BLOCKED): raise exception.InstanceNotRunning( instance_id=instance_ref['uuid']) # Checing volume node is running when any volumes are mounted # to the instance. if len(instance_ref['volumes']) != 0: services = db.service_get_all_by_topic(context, 'volume') if len(services) < 1 or not utils.service_is_up(services[0]): raise exception.VolumeServiceUnavailable() # Checking src host exists and compute node src = instance_ref['host'] services = db.service_get_all_compute_by_host(context, src) # Checking src host is alive. if not utils.service_is_up(services[0]): raise exception.ComputeServiceUnavailable(host=src)
def _live_migration_dest_check(self, context, instance_ref, dest, block_migration): """Live migration check routine (for destination host). :param context: security context :param instance_ref: nova.db.sqlalchemy.models.Instance object :param dest: destination host """ # Checking dest exists and compute node. dservice_refs = db.service_get_all_compute_by_host(context, dest) dservice_ref = dservice_refs[0] # Checking dest host is alive. if not self.service_is_up(dservice_ref): raise exception.ComputeServiceUnavailable(host=dest) # Checking whether The host where instance is running # and dest is not same. src = instance_ref['host'] if dest == src: instance_id = ec2utils.id_to_ec2_id(instance_ref['id']) raise exception.UnableToMigrateToSelf(instance_id=instance_id, host=dest) # Checking dst host still has enough capacities. self.assert_compute_node_has_enough_resources(context, instance_ref, dest, block_migration)
def _live_migration_dest_check(self, context, instance_ref, dest, block_migration, disk_over_commit): """Live migration check routine (for destination host). :param context: security context :param instance_ref: nova.db.sqlalchemy.models.Instance object :param dest: destination host :param block_migration: if true, block_migration. :param disk_over_commit: if True, consider real(not virtual) disk size. """ # Checking dest exists and compute node. dservice_refs = db.service_get_all_compute_by_host(context, dest) dservice_ref = dservice_refs[0] # Checking dest host is alive. if not utils.service_is_up(dservice_ref): raise exception.ComputeServiceUnavailable(host=dest) # Checking whether The host where instance is running # and dest is not same. src = instance_ref['host'] if dest == src: raise exception.UnableToMigrateToSelf( instance_id=instance_ref['uuid'], host=dest) # Checking dst host still has enough capacities. self.assert_compute_node_has_enough_resources(context, instance_ref, dest, block_migration, disk_over_commit)
def schedule_run_instance(self, context, instance_id, *_args, **_kwargs): """Picks a host that is up and has the fewest running instances.""" instance_ref = db.instance_get(context, instance_id) if (instance_ref['availability_zone'] and ':' in instance_ref['availability_zone'] and context.is_admin): zone, _x, host = instance_ref['availability_zone'].partition(':') service = db.service_get_by_args(context.elevated(), host, 'nova-compute') if not self.service_is_up(service): raise driver.WillNotSchedule(_("Host %s is not alive") % host) # TODO(vish): this probably belongs in the manager, if we # can generalize this somehow now = datetime.datetime.utcnow() db.instance_update(context, instance_id, { 'host': host, 'scheduled_at': now }) return host results = db.service_get_all_compute_sorted(context) for result in results: (service, instance_cores) = result compute_ref = db.service_get_all_compute_by_host( context, service['host'])[0] compute_node_ref = compute_ref['compute_node'][0] if (instance_ref['vcpus'] + instance_cores > compute_node_ref['vcpus'] * FLAGS.max_cores): raise driver.NoValidHost(_("All hosts have too many cores")) LOG.debug( _("requested instance cores = %s + used compute node cores = %s < total compute node cores = %s * max cores = %s" ) % (instance_ref['vcpus'], instance_cores, compute_node_ref['vcpus'], FLAGS.max_cores)) if self.service_is_up(service): # NOTE(vish): this probably belongs in the manager, if we # can generalize this somehow now = datetime.datetime.utcnow() db.instance_update(context, instance_id, { 'host': service['host'], 'scheduled_at': now }) LOG.debug( _("instance = %s scheduled to host = %s") % (instance_id, service['host'])) return service['host'] raise driver.NoValidHost( _("Scheduler was unable to locate a host" " for this request. Is the appropriate" " service running?"))
def _live_migration_dest_check(self, context, instance_ref, dest): """Live migration check routine (for destination host). :param context: security context :param instance_ref: nova.db.sqlalchemy.models.Instance object :param dest: destination host """ # Checking dest exists and compute node. dservice_refs = db.service_get_all_compute_by_host(context, dest) dservice_ref = dservice_refs[0] # Checking dest host is alive. if not self.servicegroup_api.service_is_up(dservice_ref): raise exception.ComputeServiceUnavailable(host=dest) # Checking whether The host where instance is running # and dest is not same. src = instance_ref['host'] if dest == src: raise exception.UnableToMigrateToSelf( instance_id=instance_ref['uuid'], host=dest) # Check memory requirements self._assert_compute_node_has_enough_memory(context, instance_ref, dest)
def _live_migration_dest_check(self, context, instance_ref, dest): """Live migration check routine (for destination host). :param context: security context :param instance_ref: nova.db.sqlalchemy.models.Instance object :param dest: destination host """ # Checking dest exists and compute node. dservice_refs = db.service_get_all_compute_by_host(context, dest) dservice_ref = dservice_refs[0] # Checking dest host is alive. if not utils.service_is_up(dservice_ref): raise exception.ComputeServiceUnavailable(host=dest) # Checking whether The host where instance is running # and dest is not same. src = instance_ref['host'] if dest == src: raise exception.UnableToMigrateToSelf( instance_id=instance_ref['uuid'], host=dest) # Check memory requirements self._assert_compute_node_has_enough_memory(context, instance_ref, dest)
def update_available_resource(self, ctxt, host): """Updates compute manager resource info on ComputeNode table. Since we don't have a real hypervisor, pretend we have lots of disk and ram. """ try: service_ref = db.service_get_all_compute_by_host(ctxt, host)[0] except exception.NotFound: raise exception.ComputeServiceUnavailable(host=host) # Updating host information dic = { 'vcpus': 1, 'memory_mb': 4096, 'local_gb': 1028, 'vcpus_used': 0, 'memory_mb_used': 0, 'local_gb_used': 0, 'hypervisor_type': 'fake', 'hypervisor_version': '1.0', 'service_id': service_ref['id'], 'cpu_info': '?' } compute_node_ref = service_ref['compute_node'] if not compute_node_ref: LOG.info(_('Compute_service record created for %s ') % host) db.compute_node_create(ctxt, dic) else: LOG.info(_('Compute_service record updated for %s ') % host) db.compute_node_update(ctxt, compute_node_ref[0]['id'], dic)
def _live_migration_dest_check(self, context, instance_ref, dest, block_migration): """Live migration check routine (for destination host). :param context: security context :param instance_ref: nova.db.sqlalchemy.models.Instance object :param dest: destination host """ # Checking dest exists and compute node. dservice_refs = db.service_get_all_compute_by_host(context, dest) dservice_ref = dservice_refs[0] # Checking dest host is alive. if not self.service_is_up(dservice_ref): raise exception.ComputeServiceUnavailable(host=dest) # Checking whether The host where instance is running # and dest is not same. src = instance_ref['host'] if dest == src: instance_id = ec2utils.id_to_ec2_id(instance_ref['id']) raise exception.UnableToMigrateToSelf(instance_id=instance_id, host=dest) # Checking dst host still has enough capacities. self.assert_compute_node_has_enough_resources(context, instance_ref, dest, block_migration)
def _live_migration_src_check(self, context, instance_ref): """Live migration check routine (for src host). :param context: security context :param instance_ref: nova.db.sqlalchemy.models.Instance object """ # Checking instance is running. if instance_ref['power_state'] != power_state.RUNNING: instance_id = ec2utils.id_to_ec2_id(instance_ref['id']) raise exception.InstanceNotRunning(instance_id=instance_id) # Checing volume node is running when any volumes are mounted # to the instance. if len(instance_ref['volumes']) != 0: services = db.service_get_all_by_topic(context, 'volume') if len(services) < 1 or not self.service_is_up(services[0]): raise exception.VolumeServiceUnavailable() # Checking src host exists and compute node src = instance_ref['host'] services = db.service_get_all_compute_by_host(context, src) # Checking src host is alive. if not self.service_is_up(services[0]): raise exception.ComputeServiceUnavailable(host=src)
def _live_migration_src_check(self, context, instance_ref): """Live migration check routine (for src host). :param context: security context :param instance_ref: nova.db.sqlalchemy.models.Instance object """ # Checking instance is running. if instance_ref["power_state"] != power_state.RUNNING: instance_id = ec2utils.id_to_ec2_id(instance_ref["id"]) raise exception.InstanceNotRunning(instance_id=instance_id) # Checing volume node is running when any volumes are mounted # to the instance. if len(instance_ref["volumes"]) != 0: services = db.service_get_all_by_topic(context, "volume") if len(services) < 1 or not utils.service_is_up(services[0]): raise exception.VolumeServiceUnavailable() # Checking src host exists and compute node src = instance_ref["host"] services = db.service_get_all_compute_by_host(context, src) # Checking src host is alive. if not utils.service_is_up(services[0]): raise exception.ComputeServiceUnavailable(host=src)
def update_available_resource(self, ctxt, host): """Updates compute manager resource info on ComputeNode table. This method is called when nova-coompute launches, and whenever admin executes "nova-manage service update_resource". :param ctxt: security context :param host: hostname that compute manager is currently running """ dic = self._max_phy_resouces(ctxt) #dic = self._sum_phy_hosts(ctxt) dic['hypervisor_type'] = 'physical' dic['hypervisor_version'] = 1 dic['cpu_info'] = 'physical cpu' try: service_ref = db.service_get_all_compute_by_host(ctxt, host)[0] except exception.NotFound: raise exception.ComputeServiceUnavailable(host=host) dic['service_id'] = service_ref['id'] compute_node_ref = service_ref['compute_node'] if not compute_node_ref: LOG.info(_('Compute_service record created for %s ') % host) db.compute_node_create(ctxt, dic) else: LOG.info(_('Compute_service record updated for %s ') % host) db.compute_node_update(ctxt, compute_node_ref[0]['id'], dic)
def test_show_host_resources(self): host = "fake_host" computes = [ { "host": host, "compute_node": [ { "vcpus": 4, "vcpus_used": 2, "memory_mb": 1024, "memory_mb_used": 512, "local_gb": 1024, "local_gb_used": 512, } ], } ] instances = [ {"project_id": "project1", "vcpus": 1, "memory_mb": 128, "root_gb": 128, "ephemeral_gb": 0}, {"project_id": "project1", "vcpus": 2, "memory_mb": 256, "root_gb": 384, "ephemeral_gb": 0}, {"project_id": "project2", "vcpus": 2, "memory_mb": 256, "root_gb": 256, "ephemeral_gb": 0}, ] self.mox.StubOutWithMock(db, "service_get_all_compute_by_host") self.mox.StubOutWithMock(db, "instance_get_all_by_host") db.service_get_all_compute_by_host(self.context, host).AndReturn(computes) db.instance_get_all_by_host(self.context, host).AndReturn(instances) self.mox.ReplayAll() result = self.manager.show_host_resources(self.context, host) expected = { "usage": { "project1": {"memory_mb": 384, "vcpus": 3, "root_gb": 512, "ephemeral_gb": 0}, "project2": {"memory_mb": 256, "vcpus": 2, "root_gb": 256, "ephemeral_gb": 0}, }, "resource": { "vcpus": 4, "vcpus_used": 2, "local_gb": 1024, "local_gb_used": 512, "memory_mb": 1024, "memory_mb_used": 512, }, } self.assertDictMatch(result, expected)
def schedule_create_volume(self, context, volume_id, *_args, **_kwargs): """Picks a host that is up and has the fewest volumes.""" volume_ref = db.volume_get(context, volume_id) if (volume_ref['availability_zone'] and ':' in volume_ref['availability_zone'] and context.is_admin): zone, _x, host = volume_ref['availability_zone'].partition(':') service = db.service_get_by_args(context.elevated(), host, 'nova-volume') if not self.service_is_up(service): raise driver.WillNotSchedule(_("Host %s not available") % host) # TODO(vish): this probably belongs in the manager, if we # can generalize this somehow now = datetime.datetime.utcnow() db.volume_update(context, volume_id, { 'host': host, 'scheduled_at': now }) return host results = db.service_get_all_volume_sorted(context) for result in results: (service, volume_gigabytes) = result compute_ref = db.service_get_all_compute_by_host( context, service['host'])[0] compute_node_ref = compute_ref['compute_node'][0] if volume_ref['size'] + volume_gigabytes > compute_node_ref[ 'local_gb']: raise driver.NoValidHost( _("All hosts have too many " "gigabytes")) LOG.debug( _("requested volume GBs = %s + used compute node GBs = %s < total compute node GBs = %s" ) % (volume_ref['size'], volume_gigabytes, compute_node_ref['local_gb'])) if self.service_is_up(service): # NOTE(vish): this probably belongs in the manager, if we # can generalize this somehow now = datetime.datetime.utcnow() db.volume_update(context, volume_id, { 'host': service['host'], 'scheduled_at': now }) LOG.debug( _("volume = %s scheduled to host = %s") % (volume_id, service['host'])) return service['host'] raise driver.NoValidHost( _("Scheduler was unable to locate a host" " for this request. Is the appropriate" " service running?"))
def show_host_resources(self, context, host): """Shows the physical/usage resource given by hosts. :param context: security context :param host: hostname :returns: example format is below. {'resource':D, 'usage':{proj_id1:D, proj_id2:D}} D: {'vcpus': 3, 'memory_mb': 2048, 'local_gb': 2048, 'vcpus_used': 12, 'memory_mb_used': 10240, 'local_gb_used': 64} """ # Update latest compute_node table topic = db.queue_get_for(context, FLAGS.compute_topic, host) rpc.call(context, topic, {"method": "update_available_resource"}) # Getting compute node info and related instances info compute_ref = db.service_get_all_compute_by_host(context, host) compute_ref = compute_ref[0] instance_refs = db.instance_get_all_by_host(context, compute_ref['host']) # Getting total available/used resource compute_ref = compute_ref['compute_node'][0] resource = {'vcpus': compute_ref['vcpus'], 'memory_mb': compute_ref['memory_mb'], 'local_gb': compute_ref['local_gb'], 'vcpus_used': compute_ref['vcpus_used'], 'memory_mb_used': compute_ref['memory_mb_used'], 'local_gb_used': compute_ref['local_gb_used']} usage = dict() if not instance_refs: return {'resource': resource, 'usage': usage} # Getting usage resource per project project_ids = [i['project_id'] for i in instance_refs] project_ids = list(set(project_ids)) for project_id in project_ids: vcpus = [i['vcpus'] for i in instance_refs if i['project_id'] == project_id] mem = [i['memory_mb'] for i in instance_refs if i['project_id'] == project_id] root = [i['root_gb'] for i in instance_refs if i['project_id'] == project_id] ephemeral = [i['ephemeral_gb'] for i in instance_refs if i['project_id'] == project_id] usage[project_id] = {'vcpus': sum(vcpus), 'memory_mb': sum(mem), 'root_gb': sum(root), 'ephemeral_gb': sum(ephemeral)} return {'resource': resource, 'usage': usage}
def show_host_resources(self, context, host): """Shows the physical/usage resource given by hosts. :param context: security context :param host: hostname :returns: example format is below. {'resource':D, 'usage':{proj_id1:D, proj_id2:D}} D: {'vcpus': 3, 'memory_mb': 2048, 'local_gb': 2048, 'vcpus_used': 12, 'memory_mb_used': 10240, 'local_gb_used': 64} """ # Update latest compute_node table topic = db.queue_get_for(context, FLAGS.compute_topic, host) rpc.call(context, topic, {"method": "update_available_resource"}) # Getting compute node info and related instances info compute_ref = db.service_get_all_compute_by_host(context, host) compute_ref = compute_ref[0] instance_refs = db.instance_get_all_by_host(context, compute_ref['host']) # Getting total available/used resource compute_ref = compute_ref['compute_node'][0] resource = { 'vcpus': compute_ref['vcpus'], 'memory_mb': compute_ref['memory_mb'], 'local_gb': compute_ref['local_gb'], 'vcpus_used': compute_ref['vcpus_used'], 'memory_mb_used': compute_ref['memory_mb_used'], 'local_gb_used': compute_ref['local_gb_used'] } usage = dict() if not instance_refs: return {'resource': resource, 'usage': usage} # Getting usage resource per project project_ids = [i['project_id'] for i in instance_refs] project_ids = list(set(project_ids)) for project_id in project_ids: vcpus = [i['vcpus'] for i in instance_refs \ if i['project_id'] == project_id] mem = [i['memory_mb'] for i in instance_refs \ if i['project_id'] == project_id] disk = [i['local_gb'] for i in instance_refs \ if i['project_id'] == project_id] usage[project_id] = { 'vcpus': reduce(lambda x, y: x + y, vcpus), 'memory_mb': reduce(lambda x, y: x + y, mem), 'local_gb': reduce(lambda x, y: x + y, disk) } return {'resource': resource, 'usage': usage}
def test_live_migration_dest_host_incompatable_cpu_raises(self): self.mox.StubOutWithMock(db, 'instance_get') 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_all_compute_by_host') dest = 'fake_host2' block_migration = False disk_over_commit = False instance = self._live_migration_instance() db.instance_get(self.context, instance['id']).AndReturn(instance) self.driver._live_migration_src_check(self.context, instance) self.driver._live_migration_dest_check(self.context, instance, dest, block_migration, disk_over_commit) self._check_shared_storage(dest, instance, True) db.service_get_all_compute_by_host(self.context, dest).AndReturn( [{'compute_node': [{'hypervisor_type': 'xen', 'hypervisor_version': 1}]}]) db.service_get_all_compute_by_host(self.context, instance['host']).AndReturn( [{'compute_node': [{'hypervisor_type': 'xen', 'hypervisor_version': 1, 'cpu_info': 'fake_cpu_info'}]}]) rpc.queue_get_for(self.context, FLAGS.compute_topic, dest).AndReturn('dest_queue') rpc.call(self.context, 'dest_queue', {'method': 'compare_cpu', 'args': {'cpu_info': 'fake_cpu_info'}, 'version': compute_rpcapi.ComputeAPI.RPC_API_VERSION}, None ).AndRaise(rpc_common.RemoteError()) self.mox.ReplayAll() self.assertRaises(rpc_common.RemoteError, self.driver.schedule_live_migration, self.context, instance_id=instance['id'], dest=dest, block_migration=block_migration)
def _get_compute_info(self, context, host): """get compute node's information specified by key :param context: security context :param host: hostname(must be compute node) :param key: column name of compute_nodes :return: value specified by key """ compute_node_ref = db.service_get_all_compute_by_host(context, host) return compute_node_ref[0]['compute_node'][0]
def show_host_resources(self, context, host): """Shows the physical/usage resource given by hosts. :param context: security context :param host: hostname :returns: example format is below:: {'resource':D, 'usage':{proj_id1:D, proj_id2:D}} D: {'vcpus': 3, 'memory_mb': 2048, 'local_gb': 2048, 'vcpus_used': 12, 'memory_mb_used': 10240, 'local_gb_used': 64} """ # Getting compute node info and related instances info compute_ref = db.service_get_all_compute_by_host(context, host) compute_ref = compute_ref[0] instance_refs = db.instance_get_all_by_host(context, compute_ref['host']) # Getting total available/used resource compute_ref = compute_ref['compute_node'][0] resource = {'vcpus': compute_ref['vcpus'], 'memory_mb': compute_ref['memory_mb'], 'local_gb': compute_ref['local_gb'], 'vcpus_used': compute_ref['vcpus_used'], 'memory_mb_used': compute_ref['memory_mb_used'], 'local_gb_used': compute_ref['local_gb_used']} usage = dict() if not instance_refs: return {'resource': resource, 'usage': usage} # Getting usage resource per project project_ids = [i['project_id'] for i in instance_refs] project_ids = list(set(project_ids)) for project_id in project_ids: vcpus = [i['vcpus'] for i in instance_refs if i['project_id'] == project_id] mem = [i['memory_mb'] for i in instance_refs if i['project_id'] == project_id] root = [i['root_gb'] for i in instance_refs if i['project_id'] == project_id] ephemeral = [i['ephemeral_gb'] for i in instance_refs if i['project_id'] == project_id] usage[project_id] = {'vcpus': sum(vcpus), 'memory_mb': sum(mem), 'root_gb': sum(root), 'ephemeral_gb': sum(ephemeral)} return {'resource': resource, 'usage': usage}
def test_live_migration_compute_src_not_exist(self): """Raise exception when src compute node is does not exist.""" self.mox.StubOutWithMock(utils, 'service_is_up') self.mox.StubOutWithMock(db, 'service_get_all_compute_by_host') dest = 'fake_host2' block_migration = False disk_over_commit = False instance = self._live_migration_instance() # Compute down db.service_get_all_compute_by_host(self.context, instance['host']).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_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_all_compute_by_host') dest = 'fake_host2' block_migration = False disk_over_commit = False instance = self._live_migration_instance() # Compute down db.service_get_all_compute_by_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 show_host_resources(self, context, host, *args): """Shows the physical/usage resource given by hosts. :param context: security context :param host: hostname :returns: example format is below. {'resource':D, 'usage':{proj_id1:D, proj_id2:D}} D: {'vcpus':3, 'memory_mb':2048, 'local_gb':2048} """ compute_ref = db.service_get_all_compute_by_host(context, host) compute_ref = compute_ref[0] # Getting physical resource information compute_node_ref = compute_ref['compute_node'][0] resource = { 'vcpus': compute_node_ref['vcpus'], 'memory_mb': compute_node_ref['memory_mb'], 'local_gb': compute_node_ref['local_gb'], 'vcpus_used': compute_node_ref['vcpus_used'], 'memory_mb_used': compute_node_ref['memory_mb_used'], 'local_gb_used': compute_node_ref['local_gb_used'] } # Getting usage resource information usage = {} instance_refs = db.instance_get_all_by_host(context, compute_ref['host']) if not instance_refs: return {'resource': resource, 'usage': usage} project_ids = [i['project_id'] for i in instance_refs] project_ids = list(set(project_ids)) for project_id in project_ids: vcpus = db.instance_get_vcpu_sum_by_host_and_project( context, host, project_id) mem = db.instance_get_memory_sum_by_host_and_project( context, host, project_id) hdd = db.instance_get_disk_sum_by_host_and_project( context, host, project_id) usage[project_id] = { 'vcpus': int(vcpus), 'memory_mb': int(mem), 'local_gb': int(hdd) } return {'resource': resource, 'usage': usage}
def update_available_resource(self, ctxt, host): """Updates compute manager resource info on ComputeNode table. This method is called when nova-coompute launches, and whenever admin executes "nova-manage service update_resource". :param ctxt: security context :param host: hostname that compute manager is currently running """ try: service_ref = db.service_get_all_compute_by_host(ctxt, host)[0] except exception.NotFound: raise exception.ComputeServiceUnavailable(host=host) # Updating host information dic = { 'vcpus': self.get_vcpu_total(), 'memory_mb': self.get_memory_mb_total(), 'local_gb': self.get_local_gb_total(), 'vcpus_used': self.get_vcpu_used(), 'memory_mb_used': self.get_memory_mb_used(), 'local_gb_used': self.get_local_gb_used(), 'hypervisor_type': self.get_hypervisor_type(), 'hypervisor_version': self.get_hypervisor_version(), 'cpu_info': self.get_cpu_info(), 'cpu_arch': FLAGS.cpu_arch, 'xpu_arch': FLAGS.xpu_arch, 'xpus': FLAGS.xpus, 'xpu_info': FLAGS.xpu_info, 'net_arch': FLAGS.net_arch, 'net_info': FLAGS.net_info, 'net_mbps': FLAGS.net_mbps, 'service_id': service_ref['id'] } compute_node_ref = service_ref['compute_node'] LOG.info(_('#### RLK: cpu_arch = %s ') % FLAGS.cpu_arch) if not compute_node_ref: LOG.info(_('Compute_service record created for %s ') % host) dic['service_id'] = service_ref['id'] db.compute_node_create(ctxt, dic) else: LOG.info(_('Compute_service record updated for %s ') % host) db.compute_node_update(ctxt, compute_node_ref[0]['id'], dic)
def update_available_resource(self, ctxt, host): """Updates compute manager resource info on ComputeNode table. This method is called when nova-compute launches, and whenever admin executes "nova-manage service update_resource". :param ctxt: security context :param host: hostname that compute manager is currently running """ try: service_ref = db.service_get_all_compute_by_host(ctxt, host)[0] except exception.NotFound: raise exception.ComputeServiceUnavailable(host=host) host_stats = self.get_host_stats(refresh=True) # Updating host information total_ram_mb = host_stats['host_memory_total'] / (1024 * 1024) free_ram_mb = host_stats['host_memory_free'] / (1024 * 1024) total_disk_gb = host_stats['disk_total'] / (1024 * 1024 * 1024) used_disk_gb = host_stats['disk_used'] / (1024 * 1024 * 1024) dic = { 'vcpus': 0, 'memory_mb': total_ram_mb, 'local_gb': total_disk_gb, 'vcpus_used': 0, 'memory_mb_used': total_ram_mb - free_ram_mb, 'local_gb_used': used_disk_gb, 'hypervisor_type': 'xen', 'hypervisor_version': 0, 'cpu_info': host_stats['host_cpu_info']['cpu_count'] } compute_node_ref = service_ref['compute_node'] if not compute_node_ref: LOG.info(_('Compute_service record created for %s ') % host) dic['service_id'] = service_ref['id'] db.compute_node_create(ctxt, dic) else: LOG.info(_('Compute_service record updated for %s ') % host) db.compute_node_update(ctxt, compute_node_ref[0]['id'], dic)
def _live_migration_src_check(self, context, instance_ref): """Live migration check routine (for src host). :param context: security context :param instance_ref: nova.db.sqlalchemy.models.Instance object """ # Checking instance is running. if instance_ref['power_state'] != power_state.RUNNING: raise exception.InstanceNotRunning( instance_id=instance_ref['uuid']) # Checking src host exists and compute node src = instance_ref['host'] services = db.service_get_all_compute_by_host(context, src) # Checking src host is alive. if not utils.service_is_up(services[0]): raise exception.ComputeServiceUnavailable(host=src)