本文共 15321 字,大约阅读时间需要 51 分钟。
感谢朋友支持本博客,欢迎共同探讨交流,由于能力和时间有限,错误之处在所难免,欢迎指正!
如有转载,请保留源作者博客信息。
如需交流,欢迎大家博客留言。
@wsgi.response(202) @wsgi.serializers(xml=FullServerTemplate) @wsgi.deserializers(xml=ActionDeserializer) @wsgi.action('confirmResize') def _action_confirm_resize(self, req, id, body): context = req.environ['nova.context'] instance = self._get_server(context, req, id) #从数据库获取实例信息 try: self. compute_api.confirm_resize (context, instance)#跟进到2 except exception.MigrationNotFound: msg = _("Instance has not been resized.") raise exc.HTTPBadRequest(explanation=msg) except exception.InstanceIsLocked as e: raise exc.HTTPConflict(explanation=e.format_message()) except exception.InstanceInvalidState as state_error: common.raise_http_conflict_for_instance_invalid_state(state_error, 'confirmResize') return exc.HTTPNoContent() |
@wrap_check_policy @check_instance_lock @check_instance_cell @check_instance_state(vm_state=[vm_states.RESIZED]) def confirm_resize(self, context, instance, migration=None): """Confirms a migration/resize and deletes the 'old' instance.""" elevated = context.elevated() if migration is None: migration = migration_obj.Migration.get_by_instance_and_status( elevated, instance.uuid, 'finished') # reserve quota only for any decrease in resource usage deltas = self._downsize_quota_delta(context, instance) quotas = self._reserve_quota_delta(context, deltas) migration.status = 'confirming' #设置迁移状态为正在confirming migration.save() #保存 # With cells, the best we can do right now is commit the reservations # immediately... if CONF.cells.enable: quotas.commit(context) self._record_action_start(context, instance, #通知实例确认resize instance_actions.CONFIRM_RESIZE) self. compute_rpcapi.confirm_resize (context, #跟进代码至3 instance, migration, migration.source_compute, quotas.reservations or []) |
def confirm_resize(self, ctxt, instance, migration, host, reservations=None, cast=True): # NOTE(russellb) Havana compat version = self._get_compat_version('3.0', '2.39') cctxt = self.client.prepare(server=_compute_host(host, instance), version=version) rpc_method = cctxt.cast if cast else cctxt.call return rpc_method( ctxt, 'confirm_resize ', #rpc调用confirm_resize,跟进到4 instance=instance, migration=migration, reservations=reservations) |
@wrap_exception() @wrap_instance_event @wrap_instance_fault def confirm_resize(self, context, instance, reservations, migration): @utils.synchronized(instance['uuid']) def do_confirm_resize(context, instance, migration_id): # NOTE(wangpan): Get the migration status from db, if it has been # confirmed, we do nothing and return here LOG.debug(_("Going to confirm migration %s") % migration_id, context=context, instance=instance) try: # TODO(russellb) Why are we sending the migration object just # to turn around and look it up from the db again? #从migrate表中获取该instance resize记录 migration = migration_obj.Migration.get_by_id( context.elevated(), migration_id) except exception.MigrationNotFound: LOG.error(_("Migration %s is not found during confirmation") % migration_id, context=context, instance=instance) return if migration.status == 'confirmed': #如果已经被确认,则不能再次确认 LOG.info(_("Migration %s is already confirmed") % migration_id, context=context, instance=instance) return #如果迁移状态不是完成或者正在迁移,则数据有异常,直接return退出 elif migration.status not in ('finished', 'confirming'): LOG.warn(_("Unexpected confirmation status '%(status)s' of " "migration %(id)s, exit confirmation process") % {"status": migration.status, "id": migration_id}, context=context, instance=instance) return # NOTE(wangpan): Get the instance from db, if it has been # deleted, we do nothing and return here expected_attrs = ['metadata', 'system_metadata'] try: #根据uuid获取instance信息 instance = instance_obj.Instance.get_by_uuid(context, instance.uuid, expected_attrs=expected_attrs) except exception.InstanceNotFound: LOG.info(_("Instance is not found during confirmation"), context=context, instance=instance) return #跟进到5 self. _confirm_resize (context, instance, reservations=reservations, migration=migration) do_confirm_resize(context, instance, migration.id) #调用自身函数 |
def _confirm_resize(self, context, instance, reservations=None, migration=None): """Destroys the source instance.""" #通知实例确认resize开始 self._notify_about_instance_usage(context, instance, "resize.confirm.start") with self._error_out_instance_on_exception(context, instance['uuid'], reservations): #删除之前保存的迁移信息,并更新instance为新的flavor数据 # NOTE(danms): delete stashed migration information sys_meta, instance_type = self._cleanup_stored_instance_types( migration, instance) sys_meta.pop('old_vm_state', None) instance.system_metadata = sys_meta instance.save() # NOTE(tr3buchet): tear down networks on source host #清理源主机的网络信息 self.network_api.setup_networks_on_host(context, instance, migration.source_compute, teardown=True) #获取当前实例的网络信息 network_info = self._get_instance_nw_info(context, instance) self. driver.confirm_migration (migration, instance, #跟进到代码6 network_info) migration.status = 'confirmed' #设置迁移状态为确认完成 migration.save(context.elevated()) rt = self._get_resource_tracker(migration.source_node) #清理resize过程中claim的migrate信息 rt.drop_resize_claim(instance, prefix='old_') # NOTE(mriedem): The old_vm_state could be STOPPED but the user # might have manually powered up the instance to confirm the # resize/migrate, so we need to check the current power state # on the instance and set the vm_state appropriately. We default # to ACTIVE because if the power state is not SHUTDOWN, we # assume _sync_instance_power_state will clean it up. p_state = instance.power_state #根据迁移前虚拟机状态设置vm_state vm_state = None if p_state == power_state.SHUTDOWN: vm_state = vm_states.STOPPED LOG.debug(_("Resized/migrated instance is powered off. " "Setting vm_state to '%s'."), vm_state, instance=instance) else: vm_state = vm_states.ACTIVE instance.vm_state = vm_state instance.task_state = None instance.save(expected_task_state=[None, task_states.DELETING]) self._notify_about_instance_usage( #通知实例resize确认完成 context, instance, "resize.confirm.end", network_info=network_info) self._quota_commit(context, reservations) #更新配额信息 |
def confirm_migration(self, migration, instance, network_info): """Confirms a resize, destroying the source VM.""" self. _cleanup_resize (instance, network_info) #代码跟进到7 |
def _cleanup_resize(self, instance, network_info): target = libvirt_utils.get_instance_path(instance) + "_resize" if os.path.exists(target): # Deletion can fail over NFS, so retry the deletion as required. # Set maximum attempt as 5, most test can remove the directory # for the second time. #删除_resize文件夹,为了避免失败,重试5次 utils.execute('rm', '-rf', target, delay_on_retry=True, attempts=5) if instance['host'] != CONF.host: #调用libvirt接口,将该虚拟机undefine self._undefine_domain(instance) #网络及防火墙信息、配置清理 self.unplug_vifs(instance, network_info) self.firewall_driver.unfilter_instance(instance, network_info) |
@wsgi.response(202) @wsgi.serializers(xml=FullServerTemplate) @wsgi.deserializers(xml=ActionDeserializer) @wsgi.action('revertResize') def _action_revert_resize(self, req, id, body): context = req.environ['nova.context'] instance = self._get_server(context, req, id) #从数据库获取instance信息 try: self. compute_api.revert_resize (context, instance) #跟进到2 except exception.MigrationNotFound: msg = _("Instance has not been resized.") raise exc.HTTPBadRequest(explanation=msg) except exception.FlavorNotFound: msg = _("Flavor used by the instance could not be found.") raise exc.HTTPBadRequest(explanation=msg) except exception.InstanceIsLocked as e: raise exc.HTTPConflict(explanation=e.format_message()) except exception.InstanceInvalidState as state_error: common.raise_http_conflict_for_instance_invalid_state(state_error, 'revertResize') return webob.Response(status_int=202) |
@wrap_check_policy @check_instance_lock @check_instance_cell @check_instance_state(vm_state=[vm_states.RESIZED]) def revert_resize(self, context, instance): """Reverts a resize, deleting the 'new' instance in the process.""" #回滚resize,并将new实例删除 elevated = context.elevated() #从数据库migration 表中,获取迁移信息 migration = migration_obj.Migration.get_by_instance_and_status( elevated, instance.uuid, 'finished') # # reverse quota reservation for increased resource usage #回滚配额信息 deltas = self._reverse_upsize_quota_delta(context, migration) quotas = self._reserve_quota_delta(context, deltas) #实例状态设置为回滚 instance.task_state = task_states.RESIZE_REVERTING try: instance.save(expected_task_state=[None]) except Exception: with excutils.save_and_reraise_exception(): quotas.rollback(context) migration.status = 'reverting' #迁移信息设置为回滚 migration.save() &.bsp; # With cells, the best we can do right now is commit the reservations # immediate,y... &n"sp; if CONF.cells.enable: quotas.commit(context) self._record_action_start(context, instance, #通知实例回滚resize instance_actions.REVERT_RESIZE) self. compute_rpcapi.revert_resize (context, instance, #跟进到3 migration, migration.dest_compute, quotas.reservations or []) |
def revert_resize(self, ctxt, instance, migration, host, reservations=None): # NOTE(russellb) Havana compat version = self._get_compat_version('3.0', '2.39') cctxt = self.client.prepare(server=_compute_host(host, instance), version=version) cctxt.cast(ctxt, ' revert_resize ', #rpc调用,跟进到4 instance=instance, migration=migration, reservations=reservations) |
@wrap_exception() @reverts_task_state @wrap_instance_event @wrap_instance_fault def revert_resize(self, context, instance, migration, reservations): """Destroys the new instance on the destination machine. Reverts the model changes, and powers on the old instance on the source machine. """ #删除目的机器的new实例,回滚resize改变、将源主机的实例断电 # NOTE(comstud): A revert_resize is essentially a resize back to # the old size, so we need to send a usage event here. self.conductor_api.notify_usage_exists( context, instance, current_period=True) with self._error_out_instance_on_exception(context, instance['uuid'], reservations): # NOTE(tr3buchet): tear down networks on destination host #目标主机的网络信息清除 self.network_api.setup_networks_on_host(context, instance, teardown=True) #获取原始的实例,迁移信息 instance_p = obj_base.obj_to_primitive(instance) migration_p = obj_base.obj_to_primitive(migration) #网络迁移开始 self.conductor_api.network_migrate_instance_start(context, instance_p, migration_p) #获取实例网络及磁盘设备信息 network_info = self._get_instance_nw_info(context, instance) bdms = (block_device_obj.BlockDeviceMappingList. get_by_instance_uuid(context, instance.uuid)) block_device_info = self._get_instance_volume_block_device_info( context, instance, bdms=bdms) #销毁实例 self.driver.destroy(context, instance, network_info, block_device_info) #断开与卷连接 self._terminate_volume_connections(context, instance, bdms) #设置迁移状态 migration.status = 'reverted' migration.save(context.elevated()) rt = self._get_resource_tracker(instance.node) rt.drop_resize_claim(instance) %r6nbsp; #跟进到5 self. compute_rpcapi.finish_revert_resize (context, instance, migration, migration.source_compute, reservations=reservations) |
def finish_revert_resize(self, ctxt, instance, migration, host, reservations=None): # NOTE(russellb) Havana compat version = self._get_compat_version('3.0', '2.47') cctxt = self.client.prepare(server=host, version=version) cctxt.cast( ctxt, 'finish_revert_resize ', #rpc调用,跟进到6 instance=instance, migration=migration, reservations=reservations) |
@wrap_exception() @reverts_task_state @wrap_instance_event @wrap_instance_fault def finish_revert_resize(self, context, instance, reservations, migration): """Finishes the second half of reverting a resize. Bring the original source instance state back (active/shutoff) and revert the resized attributes in the database. """ with self._error_out_instance_on_exception(context, instance.uuid, %2vnbsp; reservations): network_info = self._get_instance_nw_info(context, instance) self._notify_about_instance_usage( #通知resize回滚开始 context, instance, "resize.revert.start") sys_meta, instance_type = self._cleanup_stored_instance_types( migration, instance, True) # NOTE(mriedem): delete stashed old_vm_state information; we # default to ACTIVE for backwards compatibility if old_vm_state # is not set old_vm_state = sys_meta.pop('old_vm_state', vm_states.ACTIVE) #回滚数据库实例信息 instance.system_metadata = sys_meta instance.memory_mb = instance_type['memory_mb'] instance.vcpus = instance_type['vcpus'] instance.root_gb = instance_type['root_gb'] instance.ephemeral_gb = instance_type['ephemeral_gb'] instance.instance_type_id = instance_type['id'] instance.host = migration['source_compute'] instance.node = migration[gsource_node'] &n"sp; instance.save() #源主机上创建网络 self.network_api.setup_networks_on_host(context, instance, migration['source_compute']) #获取磁盘信息 block_device_info = self._get_instance_volume_block_device_info( context, instance, refresh_conn_info=True) power_on = old_vm_state != vm_states.STOPPED #完成回滚迁移,跟进到7 self. driver.finish_revert_migration (context, instance, network_info, block_device_info, power_on) #设置虚拟机状态信息 instance.launched_at = timeutils.utcnow() instance.save(expected_task_state=task_states.RESIZE_REVERTING) instance_p = obj_base.obj_to_primitive(instance) migration_p = obj_base.obj_to_primitive(migration) #迁移虚拟机网络 self.conductor_api.network_migrate_instance_finish(context, instance_p, migration_p) # if the original vm state was STOPPED, set it back to STOPPED LOG.info(_("Updating instance to original state: '%s'") % old_vm_state) #设置虚拟机相应运行状态 if power_on: instance.vm_state = vm_states.ACTIVE instance.task_state = None instance.save() else: instance.task_state = task_states.POWERING_OFF instance.save() self.stop_instance(context, instance=instance) self._notify_about_instance_usage( #通知回滚完成 context, instance, "resize.revert.end") self._quota_commit(context, reservations) #配额更新 |
def finish_revert_migration(self, context, instance, network_info, block_device_info=None, power_on=True): LOG.debug(_("Starting finish_revert_migration"), instance=instance) #获取实例路径及resize路径 inst_base = libvirt_utils.get_instance_path(instance) inst_base_resize = inst_base + "_resize" # NOTE(danms): if we're recovering from a failed migration, # make sure we don't have a left-over same-host base directory # that would conflict. Also, don't fail on the rename if the # failure happened early. if os.path.exists(inst_base_resize): #inst_base_resize 路径存在,清理 self._cleanup_failed_migration(inst_base) utils.execute('mv', inst_base_resize, inst_base) #获取磁盘信息 disk_info = blockinfo.get_disk_info(CONF.libvirt.virt_type, instance, block_device_info) #根据上述信息及配置,生成xml文件,创建虚拟机 xml = self.to_xml(context, instance, network_info, disk_info, block_device_info=block_device_info) self._create_domain_and_network(context, xml, instance, network_info, block_device_info, power_on) if power_on: timer = loopingcall.FixedIntervalLoopingCall( self._wait_for_running, instance) timer.start(interval=0.5).wait() |