openstack ice resize 详解(三)

来源:互联网 发布:微博怎么链接淘宝商品 编辑:程序博客网 时间:2024/05/05 17:50

感谢朋友支持本博客,欢迎共同探讨交流,由于能力和时间有限,错误之处在所难免,欢迎指正!

如有转载,请保留源作者博客信息。

Better Me的博客:blog.csdn.net/tantexian

如需交流,欢迎大家博客留言。



由于篇幅较长:上接之前博文:openstack ice resize 详解(二)

三、resize完毕后的确认confirm_resize代码详解分析
1、/nova/api/openstack/compute/servers.py
@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()

2、/nova/compute/api.py
    @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 [])

3、/nova/compute/rpcapi.py
    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)

4、/nova/compute/manage.py
    @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)#调用自身函数

5、/nova/compute/manage.py
    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)#更新配额信息


6、/nova/virt/libvirt/driver.py
    def confirm_migration(self, migration, instance, network_info):
        """Confirms a resize, destroying the source VM."""
        self._cleanup_resize(instance, network_info)#代码跟进到7


7、/nova/virt/libvirt/driver.py
    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)
确认confirm_resize完成。


四、resize完毕后的确认revert_resize代码详解分析
1、/nova/api/openstack/compute/servers.py
    @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)

2、/nova/compute/api.py
    @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 [])

3、/nova/compute/rpcapi.py
    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)

4、/nova/compute/manage.py
    @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)

5、/nova/compute/rpcapi.py
    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)

6、/nova/compute/manage.py
    @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)#配额更新

7、/nova/compute/virt/libvirt/driver.py
    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()
至此回滚resize分析结束。

0 0
原创粉丝点击