本文以kilo版本的cinder為例
代碼整體流程如下:

如整體架構圖所示,創建卷涉及的大體步驟主要有以下幾步:
a. Client發送請求,通過RESTFUL接口訪問cinder-api。
b. Api解析響應請求,api解析由Client發送來的請求,并通過rpc進一步調用cinder-scheduler。
c. Scheduler對資源進行調度,scheduler選擇合適的節點進行。
d. Volume調用Driver創建卷,volume通過指定Driver進行卷的創建。
cinder api
cinder client
POST /v2/{tenant_id}/volumes
↓
cinder.api.v2.volumes.VolumeController.create:
# 對volume_type、metadata、snapshot等信息進行檢查
new_volume = self.volume_api.create(context,
size,
volume.get('display_name'),
volume.get('display_description'),
**kwargs)
↓
cinder.volume.api.API.create:
# 對source_volume、volume_type等參數進行進一步檢查
flow_engine = create_volume.get_flow()
↓
cinder.volume.flows.api.create_volume.get_flow:
api_flow.add(ExtractVolumeRequestTask())
api_flow.add(QuotaReserveTask(),
EntryCreateTask(db_api),
QuotaCommitTask())
api_flow.add(VolumeCastTask())
↓
cinder.volume.api.API.create:
flow_engine.run()
↓
cinder.volume.flows.api.create_volume.ExtractVolumeRequestTask.execute:
# 獲取 request 信息并返回
cinder.volume.flows.api.create_volume.QuotaReserveTask.execute:
# 預留配額
cinder.volume.flows.api.create_volume.EntryCreateTask.execute:
# 在數據庫中創建 volume 條目,此時卷的狀態為”creating”
cinder.volume.flows.api.create_volume.QuotaCommitTask.execute:
# 確認配額
cinder.volume.flows.api.create_volume.VolumeCastTask.execute:
self._cast_create_volume(context, request_spec, filter_properties)
↓
cinder.volume.flows.api.create_volume.VolumeCastTask._cast_create_volume:
if not host: # 如果未傳入host,則會經過調度進行創建卷
self.scheduler_rpcapi.create_volume()
else: # 如果傳入host,直接交由Volume Manager去創建卷
self.volume_rpcapi.create_volume()
↓
cinder.scheduler.rpcapi.SchedulerAPI.create_volume: # 以未傳入host為例
return cctxt.cast(ctxt, 'create_volume', ···)
cinder scheduler
cinder.scheduler.manager.SchedulerManager.create_volume:
flow_engine = create_volume.get_flow(context,···)
↓
cinder.scheduler.flows.create_volume.get_flow:
scheduler_flow.add(ExtractSchedulerSpecTask())
scheduler_flow.add(ScheduleCreateVolumeTask())
↓
cinder.scheduler.manager.SchedulerManager.create_volume:
flow_engine.run()
↓
cinder.scheduler.flows.create_volume.ExtractSchedulerSpecTask.execute:
# 獲取用于調度的信息
↓
cinder.scheduler.flows.create_volume.ScheduleCreateVolumeTask.execute:
self.driver_api.schedule_create_volume()
↓
cinder.scheduler.filter_scheduler.FilterScheduler.schedule_create_volume:
weighed_host = self._schedule()
# 更新數據庫
updated_volume = driver.volume_update_db(context, volume_id, host)
self.volume_rpcapi.create_volume()
↓
cinder.volume.rpcapi.VolumeAPI.create_volume:
cctxt.cast(ctxt, 'create_volume',···)
cinder volume
cinder.volume.manager.VolumeManage.create_volume:
flow_engine = create_volume.get_flow()
↓
cinder.volume.flows.manager.create_volume.get_flow:
volume_flow.add(ExtractVolumeRefTask(db, host))
if allow_reschedule and request_spec: # 如果允許重新調度
volume_flow.add(OnFailureRescheduleTask())
volume_flow.add(ExtractVolumeSpecTask(db),
NotifyVolumeActionTask(db, "create.start"),
CreateVolumeFromSpecTask(db, driver),
CreateVolumeOnFinishTask(db, "create.end"))
↓
cinder.volume.manager.VolumeManage.create_volume:
flow_engine.run()
↓
cinder.volume.flows.manager.create_volume.ExtractVolumeRefTask.execute:
#從數據庫中獲得volume信息
volume_ref = self.db.volume_get(context, volume_id)
return volume_ref
↓
cinder.volume.flows.manager.create_volume.OnFailureRescheduleTask.execute:
# 當進行task恢復回滾操作的時候,觸發一個發送進行重新調度的請求
↓
cinder.volume.flows.manager.create_volume.ExtractVolumeSpecTask.execute:
# 返回要創建volume的通用結構規范
return specs
#
↓
cinder.volume.flows.manager.create_volume.NotifyVolumeActionTask.execute:
# 執行關于給定卷的相關通知操作,獲取指定卷的使用率信息,并進行通知操作
↓
cinder.volume.flows.manager.create_volume.CreateVolumeFromSpecTask.execute:
# 根據創建的不同類別,去創建卷
create_type = volume_spec.pop('type', None)
if create_type == 'raw':
model_update = self._create_raw_volume(context,···)
elif create_type == 'snap':
model_update = self._create_from_snapshot(context,···)
elif create_type == 'source_vol':
model_update = self._create_from_source_volume(···)
elif create_type == 'source_replica':
model_update = self._create_from_source_replica(···)
elif create_type == 'image':
model_update = self._create_from_image(context,···)
↓
cinder.volume.flows.manager.create_volume.CreateVolumeFromSpecTask._create_raw_volume:
# 以原始創建方式為例
return self.driver.create_volume(volume_ref)
↓
cinder.volume.flows.manager.create_volume.CreateVolumeOnFinishTask.execute:
# 當成功的建立卷之后,完成卷建立之后的通知操作,啟動更新數據庫,將卷更新為available狀態。