def _check_requested_destination(self): """Performs basic pre-live migration checks for the forced host.
:returns: tuple of (source ComputeNode, destination ComputeNode) """ # 确保源主机和宿主机不是同一物理主机 self._check_destination_is_not_source() # 检查目的主机是否可用 self._check_host_is_up(self.destination) # 检查目的主机是否有足够的内存 self._check_destination_has_enough_memory() # 检查两个源主机和宿主机之间是否兼容 source_node, dest_node = self._check_compatible_with_source_hypervisor( self.destination) # 检查下是否可以对目的主机执行热迁移操作 self._call_livem_checks_on_host(self.destination) # Make sure the forced destination host is in the same cell that the # instance currently lives in. # NOTE(mriedem): This can go away if/when the forced destination host # case calls select_destinations. source_cell_mapping = self._get_source_cell_mapping() dest_cell_mapping = self._get_destination_cell_mapping() if source_cell_mapping.uuid != dest_cell_mapping.uuid: raise exception.MigrationPreCheckError( reason=(_('Unable to force live migrate instance %s ' 'across cells.') % self.instance.uuid)) return source_node, dest_node
def check_can_live_migrate_destination(self, ctxt, instance, block_migration, disk_over_commit, migration=None, limits=None): """Check if it is possible to execute live migration.
This runs checks on the destination host, and then calls back to the source host to check the results.
:param context: security context :param instance: dict of instance data :param block_migration: if true, prepare for block migration if None, calculate it in driver :param disk_over_commit: if true, allow disk over commit if None, ignore disk usage checking :param migration: objects.Migration object for this live migration. :param limits: objects.SchedulerLimits object for this live migration. :returns: a LiveMigrateData object (hypervisor-dependent) """ src_compute_info = obj_base.obj_to_primitive( self._get_compute_info(ctxt, instance.host)) dst_compute_info = obj_base.obj_to_primitive( self._get_compute_info(ctxt, CONF.host)) dest_check_data = self.driver.check_can_live_migrate_destination(ctxt, instance, src_compute_info, dst_compute_info, block_migration, disk_over_commit) dest_check_data = self._dest_can_numa_live_migrate(dest_check_data, migration) LOG.debug('destination check data is %s', dest_check_data) try: migrate_data = self.compute_rpcapi.check_can_live_migrate_source( ctxt, instance, dest_check_data) LOG.debug('migrate_data:%s' % migrate_data) if ('src_supports_numa_live_migration' in migrate_data and migrate_data.src_supports_numa_live_migration): migrate_data = self._live_migration_claim( ctxt, instance, migrate_data, migration, limits) LOG.debug('migrate_data:%s' % migrate_data) elif 'dst_supports_numa_live_migration' in dest_check_data: LOG.info('Destination was ready for NUMA live migration, ' 'but source is either too old, or is set to an ' 'older upgrade level.', instance=instance) ''' # Create migrate_data vifs migrate_data.vifs = \ migrate_data_obj.VIFMigrateData.create_skeleton_migrate_vifs( instance.get_network_info()) # Claim PCI devices for VIFs on destination (if needed) port_id_to_pci = self._claim_pci_for_instance_vifs(ctxt, instance) # Update migrate VIFs with the newly claimed PCI devices self._update_migrate_vifs_profile_with_pci(migrate_data.vifs, port_id_to_pci) ''' finally: self.driver.cleanup_live_migration_destination_check(ctxt, dest_check_data) return migrate_data
connector = self.driver.get_volume_connector(instance) try: for bdm in bdms: if bdm.is_volume and bdm.attachment_id is not None: attach_ref = self.volume_api.attachment_create( context, bdm.volume_id, bdm.instance_uuid, connector=connector, mountpoint=bdm.device_name) migrate_data.old_vol_attachment_ids[bdm.volume_id] = \ bdm.attachment_id
# update the bdm with the new attachment_id. bdm.attachment_id = attach_ref['id'] bdm.save()
def pre_live_migration(self, context, instance, block_device_info, network_info, disk_info, migrate_data): """Preparation live migration.""" *************************************** #创建libvirt以及nova相关本地目录,以及根据是否云盘做镜像相关fetch操作 #连接cinder volume server # Establishing connection to volume server. block_device_mapping = driver.block_device_info_get_mapping( block_device_info)
if len(block_device_mapping): LOG.debug('Connecting volumes before live migration.', instance=instance) #plug vif初始化网卡信息 self._pre_live_migration_plug_vifs( instance, network_info, migrate_data)
def _do_live_migration(self, context, dest, instance, block_migration, migration, migrate_data): try: self.driver.live_migration(context, instance, dest, post_live_migration, rollback_live_migration, block_migration, migrate_data) except Exception: LOG.exception('Live migration failed.', instance=instance) with excutils.save_and_reraise_exception(): # Put instance and migration into error state, # as its almost certainly too late to rollback self._set_migration_status(migration, 'error') # first refresh instance as it may have got updated by # post_live_migration_at_destination instance.refresh() self._set_instance_obj_error_state(context, instance, clean_task_state=True)