cinder創(chuàng)建卷源碼流程分析

  1. 調(diào)用/cinder/api/v3/volumes.py文件中VolumeController類下的create方法

    # 參數(shù)驗證
    self.validate_name_and_description(volume, check_length=False)
    ...
    # 如果基于快照創(chuàng)建卷,通過下面方法獲取快照數(shù)據(jù)
    kwargs['snapshot'] = self.volume_api.get_snapshot(context, snapshot_id)
    # 如果基于卷創(chuàng)建卷,通過下面方法獲取源卷數(shù)據(jù)
    kwargs['source_volume'] = (self.volume_api.get_volume(context, ource_volid))
    # 基于一致性群組id或群組id獲取組數(shù)據(jù)
    kwargs['group'] = self.group_api.get(context, consistencygroup_id)
    或者
    kwargs['group'] = self.group_api.get(context, group_id)
    # 如果基于鏡像創(chuàng)建卷,通過下面方法獲取鏡像數(shù)據(jù)
    image_uuid = self._image_uuid_from_ref(image_ref, context)
    image_snapshot = self._get_image_snapshot(context, image_uuid)
    # 如果基于卷備份創(chuàng)建卷,通過下面方法獲取備份數(shù)據(jù)
    kwargs['backup'] = self.backup_api.get(context, backup_id=backup_id)
    # 最后調(diào)用下面方法創(chuàng)建卷
    new_volume = self.volume_api.create(...)
    # 方法指向
    from cinder import volume as cinder_volume
    self.volume_api = cinder_volume.API()
    
  2. 調(diào)用/cinder/volume/api.py文件中API類下的create方法

    # 參數(shù)驗證
    ...
    # 獲取調(diào)度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())
    # 構(gòu)建用于建立卷的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
        ->  # 調(diào)用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:這個類實現(xiàn)了注入字典信息create_what到flow中。
        ->  # 添加一個給定的task到flow: api_flow.add(ExtractVolumeRequestTask(...))。
            ->  # ExtractVolumeRequestTask:實現(xiàn)提取并驗證輸入的請求信息,并返回經(jīng)過驗證的參數(shù)信息。
        ->  # 添加給定的task到flow:   api_flow.add(QuotaReserveTask(), EntryCreateTask(), QuotaCommitTask())。
            ->  # QuotaReserveTask:根據(jù)給定的大小值和給定的卷類型信息實現(xiàn)保存單一的卷。
            ->  # EntryCreateTask:在數(shù)據(jù)庫中為給定的卷建立相關(guān)條目。
                ->  # QuotaCommitTask:提交新的資源配額的預(yù)留信息到數(shù)據(jù)庫中。
        ->  # 添加給定的task到flow:   api_flow.add(VolumeCastTask(scheduler_rpcapi, volume_rpcapi, db_api))。
            ->  # VolumeCastTask:遠(yuǎn)程調(diào)用實現(xiàn)卷的建立操作。
    # VolumeCastTask卷操作
        ->  # 首先調(diào)用`execute(...)`方法。
        ->  # 接著調(diào)用`self._cast_create_volume(...)`方法。
        ->  # 最后點(diǎn)用`self.scheduler_rpcapi.create_volume(...)`方法。
    # 運(yùn)行用于建立卷的flow
    flow_engine.run()
    # 方法指向
    from cinder.scheduler import rpcapi as scheduler_rpcapi
    scheduler_rpcapi = scheduler_rpcapi.SchedulerAPI()
    self.scheduler_rpcapi = scheduler_rpcapi
    
  3. 調(diào)用/cinder/scheduler/rpcapi.py文件中SchedulerAPI類下的create_volume方法

    cctxt.cast(ctxt, 'create_volume', **msg_args)
    # 通過rpc服務(wù)將數(shù)據(jù)發(fā)送到mq隊列中
    
  4. 調(diào)用/cinder/scheduler/manager.py文件中SchedulerManager類下的create_volume方法

    # 構(gòu)建并返回用于通過遠(yuǎn)程調(diào)度建立卷的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:實現(xiàn)了從輸入的參數(shù)中提取調(diào)度器的規(guī)范信息的操作。
      ->    # 添加一個給定的task到flow:scheduler_flow.add(ScheduleCreateVolumeTask(driver_api))。
            ->  # ScheduleCreateVolumeTask:遠(yuǎn)程調(diào)用實現(xiàn)卷的建立操作。
    # ScheduleCreateVolumeTask卷操作
        ->  # 首先調(diào)用`execute(...)`方法。
        ->  # 接著調(diào)用`self.driver_api.schedule_create_volume(...)`方法。
    # 運(yùn)行用于建立卷的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. 調(diào)用/cinder/scheduler/filter_scheduler.py文件中FilterScheduler類下的schedule_create_volume方法

    # 過濾稱重操作,獲取最優(yōu)后端
    backend = self._schedule(context, request_spec, filter_properties)
    # 數(shù)據(jù)庫卷數(shù)據(jù)更新
    updated_volume = driver.volume_update_db(...)
    # 最后調(diào)用,遠(yuǎn)程調(diào)用實現(xiàn)創(chuàng)建卷
    self.volume_rpcapi.create_volume(...)
    # 方法指向
    from cinder.volume import rpcapi as volume_rpcapi
    self.volume_rpcapi = volume_rpcapi.VolumeAPI()
    
  6. 調(diào)用/cinder/volume/rpcapi.py文件中VolumeAPI類下的create_volume方法

    cctxt.cast(ctxt, 'create_volume', ...)
    # 通過rpc服務(wù)將數(shù)據(jù)發(fā)送到mq隊列中
    
  7. 調(diào)用/cinder/volume/manager.py文件中VolumeManager類下的create_volume方法

    # 構(gòu)建并返回用于通過管理器建立卷的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:觸發(fā)一個發(fā)送進(jìn)行重新調(diào)度的請求,當(dāng)進(jìn)行task恢復(fù)回滾操作的時候。
        ->  # 添加給定的task到flow:   volume_flow.add(ExtractVolumeSpecTask(db), NotifyVolumeActionTask(db, 
            # "create.start"), CreateVolumeFromSpecTask(...), CreateVolumeOnFinishTask(db, "create.end"))。
            ->  # ExtractVolumeSpecTask:提取一個用于建立卷的通用結(jié)構(gòu)數(shù)據(jù)。
                ->  # NotifyVolumeActionTask:執(zhí)行關(guān)于給定卷的相關(guān)通知操作,獲取指定卷的使用率信息,并進(jìn)行通知操作。
                ->  # CreateVolumeFromSpecTask:根據(jù)所提供的數(shù)據(jù)實現(xiàn)卷的建立操作。
                ->  # CreateVolumeOnFinishTask:當(dāng)成功的建立卷之后,完成卷建立之后的通知操作。
    # 調(diào)用CreateVolumeFromSpecTask創(chuàng)建卷,/cinder/volume/flows/manager/create_volume.py下
        ->  # 首先調(diào)用`execute(...)`方法。
        ->  # 獲取創(chuàng)建卷的方式:create_type = volume_spec.pop('type', None)
        ->  # 根據(jù)不同的方式創(chuàng)建卷
    # 以raw原始方式創(chuàng)建卷為例說明,接著是調(diào)用self._create_raw_volume(...)方法
    # 假設(shè)以rbd方式創(chuàng)建卷,那么self.driver即為/cinder/volume/drivers/rbd.py文件下`RBDDriver`類的實例化
    self.driver.create_volume(volume)
    ....
    # 運(yùn)行用于建立卷的flow
    flow_engine.run()
    
  8. 調(diào)用/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(...)調(diào)用的是C擴(kuò)展的rbd.pyx中的create(...)方法
    

    RBD的C擴(kuò)展Github倉庫地址

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容