美文网首页
cinder创建卷源码流程分析

cinder创建卷源码流程分析

作者: 君致 | 来源:发表于2020-12-18 08:42 被阅读0次
  1. 调用/cinder/api/v3/volumes.py文件中VolumeController类下的create方法

    # 参数验证
    self.validate_name_and_description(volume, check_length=False)
    ...
    # 如果基于快照创建卷,通过下面方法获取快照数据
    kwargs['snapshot'] = self.volume_api.get_snapshot(context, snapshot_id)
    # 如果基于卷创建卷,通过下面方法获取源卷数据
    kwargs['source_volume'] = (self.volume_api.get_volume(context, ource_volid))
    # 基于一致性群组id或群组id获取组数据
    kwargs['group'] = self.group_api.get(context, consistencygroup_id)
    或者
    kwargs['group'] = self.group_api.get(context, group_id)
    # 如果基于镜像创建卷,通过下面方法获取镜像数据
    image_uuid = self._image_uuid_from_ref(image_ref, context)
    image_snapshot = self._get_image_snapshot(context, image_uuid)
    # 如果基于卷备份创建卷,通过下面方法获取备份数据
    kwargs['backup'] = self.backup_api.get(context, backup_id=backup_id)
    # 最后调用下面方法创建卷
    new_volume = self.volume_api.create(...)
    # 方法指向
    from cinder import volume as cinder_volume
    self.volume_api = cinder_volume.API()
    
  2. 调用/cinder/volume/api.py文件中API类下的create方法

    # 参数验证
    ...
    # 获取调度rpc接口
    sched_rpcapi = (self.scheduler_rpcapi if (not cgsnapshot and not source_cg and not group_snapshot and not source_group) else None)
    # 获取卷操作rpc接口
    volume_rpcapi = (self.volume_rpcapi if (not cgsnapshot and not source_cg and not group_snapshot and not source_group) else None)
    # 获取镜像操作的api接口
    self.image_service = (image_service or glance.get_default_image_service())
    # 构建用于建立卷的flow
    flow_engine = create_volume.get_flow(self.db, self.image_service, availability_zones, create_what, sched_rpcapi, volume_rpcapi)     # /cinder/volume/flows/api/create_volume.py
        ->  # 调用get_flow(...)方法。
        ->  # flow_name = ACTION.replace(":", "_") + "_api, 即为volume_create_api。
        ->  # 初始化flow类:api_flow = linear_flow.Flow(flow_name)。
        ->  # 添加一个task到flow中:api_flow.add(base.InjectTask(create_what, addons=[ACTION]))。
            ->  # InjectTask:这个类实现了注入字典信息create_what到flow中。
        ->  # 添加一个给定的task到flow: api_flow.add(ExtractVolumeRequestTask(...))。
            ->  # ExtractVolumeRequestTask:实现提取并验证输入的请求信息,并返回经过验证的参数信息。
        ->  # 添加给定的task到flow:   api_flow.add(QuotaReserveTask(), EntryCreateTask(), QuotaCommitTask())。
            ->  # QuotaReserveTask:根据给定的大小值和给定的卷类型信息实现保存单一的卷。
            ->  # EntryCreateTask:在数据库中为给定的卷建立相关条目。
                ->  # QuotaCommitTask:提交新的资源配额的预留信息到数据库中。
        ->  # 添加给定的task到flow:   api_flow.add(VolumeCastTask(scheduler_rpcapi, volume_rpcapi, db_api))。
            ->  # VolumeCastTask:远程调用实现卷的建立操作。
    # VolumeCastTask卷操作
        ->  # 首先调用`execute(...)`方法。
        ->  # 接着调用`self._cast_create_volume(...)`方法。
        ->  # 最后点用`self.scheduler_rpcapi.create_volume(...)`方法。
    # 运行用于建立卷的flow
    flow_engine.run()
    # 方法指向
    from cinder.scheduler import rpcapi as scheduler_rpcapi
    scheduler_rpcapi = scheduler_rpcapi.SchedulerAPI()
    self.scheduler_rpcapi = scheduler_rpcapi
    
  3. 调用/cinder/scheduler/rpcapi.py文件中SchedulerAPI类下的create_volume方法

    cctxt.cast(ctxt, 'create_volume', **msg_args)
    # 通过rpc服务将数据发送到mq队列中
    
  4. 调用/cinder/scheduler/manager.py文件中SchedulerManager类下的create_volume方法

    # 构建并返回用于通过远程调度建立卷的flow
    flow_engine = create_volume.get_flow()  # /cinder/scheduler/flows/create_volume.py
        ->  # flow_name = ACTION.replace(":", "_") + "_scheduler", 即为volume_create_scheduler。
      ->    # 初始化flow类:scheduler_flow = linear_flow.Flow(flow_name)。
      ->    #   添加一个给定的task到flow:scheduler_flow.add(ExtractSchedulerSpecTask(...))。
            ->  # ExtractSchedulerSpecTask:实现了从输入的参数中提取调度器的规范信息的操作。
      ->    # 添加一个给定的task到flow:scheduler_flow.add(ScheduleCreateVolumeTask(driver_api))。
            ->  # ScheduleCreateVolumeTask:远程调用实现卷的建立操作。
    # ScheduleCreateVolumeTask卷操作
        ->  # 首先调用`execute(...)`方法。
        ->  # 接着调用`self.driver_api.schedule_create_volume(...)`方法。
    # 运行用于建立卷的flow
    flow_engine.run()
    # 方法指向
    scheduler_driver = CONF.scheduler_driver        # 即为cinder.scheduler.filter_scheduler.FilterScheduler
    self.driver = importutils.import_object(scheduler_driver)   # 加载类
    driver_api = self.driver
    self.driver_api = driver_api
    
  5. 调用/cinder/scheduler/filter_scheduler.py文件中FilterScheduler类下的schedule_create_volume方法

    # 过滤称重操作,获取最优后端
    backend = self._schedule(context, request_spec, filter_properties)
    # 数据库卷数据更新
    updated_volume = driver.volume_update_db(...)
    # 最后调用,远程调用实现创建卷
    self.volume_rpcapi.create_volume(...)
    # 方法指向
    from cinder.volume import rpcapi as volume_rpcapi
    self.volume_rpcapi = volume_rpcapi.VolumeAPI()
    
  6. 调用/cinder/volume/rpcapi.py文件中VolumeAPI类下的create_volume方法

    cctxt.cast(ctxt, 'create_volume', ...)
    # 通过rpc服务将数据发送到mq队列中
    
  7. 调用/cinder/volume/manager.py文件中VolumeManager类下的create_volume方法

    # 构建并返回用于通过管理器建立卷的flow
    flow_engine = create_volume.get_flow(...) # /cinder/volume/flows/manager/create_volume.py
        ->  # flow_name = ACTION.replace(":", "_") + "_manager", 即为volume_create_manager。
        ->  # 初始化flow类:volume_flow = linear_flow.Flow(flow_name)。
        ->  # 添加一个给定的task到flow:volume_flow.add(ExtractVolumeRefTask(...))。
            ->  #   ExtractVolumeRefTask:提取给定卷的引用。
        ->  # 添加一个给定的task到flow:volume_flow.add(OnFailureRescheduleTask(...))。
            ->  # OnFailureRescheduleTask:触发一个发送进行重新调度的请求,当进行task恢复回滚操作的时候。
        ->  # 添加给定的task到flow:   volume_flow.add(ExtractVolumeSpecTask(db), NotifyVolumeActionTask(db, 
            # "create.start"), CreateVolumeFromSpecTask(...), CreateVolumeOnFinishTask(db, "create.end"))。
            ->  # ExtractVolumeSpecTask:提取一个用于建立卷的通用结构数据。
                ->  # NotifyVolumeActionTask:执行关于给定卷的相关通知操作,获取指定卷的使用率信息,并进行通知操作。
                ->  # CreateVolumeFromSpecTask:根据所提供的数据实现卷的建立操作。
                ->  # CreateVolumeOnFinishTask:当成功的建立卷之后,完成卷建立之后的通知操作。
    # 调用CreateVolumeFromSpecTask创建卷,/cinder/volume/flows/manager/create_volume.py下
        ->  # 首先调用`execute(...)`方法。
        ->  # 获取创建卷的方式:create_type = volume_spec.pop('type', None)
        ->  # 根据不同的方式创建卷
    # 以raw原始方式创建卷为例说明,接着是调用self._create_raw_volume(...)方法
    # 假设以rbd方式创建卷,那么self.driver即为/cinder/volume/drivers/rbd.py文件下`RBDDriver`类的实例化
    self.driver.create_volume(volume)
    ....
    # 运行用于建立卷的flow
    flow_engine.run()
    
  8. 调用/cinder/volume/drivers/rbd.py文件下RBDDriver类下的create_volume`方法

    # 主要该方法
    with RADOSClient(self) as client:
            self.RBDProxy().create(client.ioctx, ...)
    # 方法指向
    from eventlet import tpool
    self.RBDProxy() = tpool.Proxy(self.rbd.RBD())
    # self.RBDProxy().create(...)调用的是C扩展的rbd.pyx中的create(...)方法
    

    RBD的C扩展Github仓库地址

相关文章

网友评论

      本文标题:cinder创建卷源码流程分析

      本文链接:https://www.haomeiwen.com/subject/qbqxnktx.html