Volume创建过程源码解读
程序员文章站
2022-05-11 15:42:53
...
完成volume创建的入口在VolumeManager类的create_volume()函数
#cinder/volume/manager.py
class VolumeManager(manager.SchedulerDependentManager):
"""Manages attachable block storage devices."""
def create_volume(self, context, volume_id, request_spec=None,
filter_properties=None, allow_reschedule=True,
snapshot_id=None, image_id=None, source_volid=None,
source_replicaid=None, consistencygroup_id=None):
try:
# NOTE(flaper87): Driver initialization is
# verified by the task itself.
flow_engine = create_volume.get_flow(
context,
self.db,
self.driver,
self.scheduler_rpcapi,
self.host,
volume_id,
snapshot_id=snapshot_id,
image_id=image_id,
source_volid=source_volid,
source_replicaid=source_replicaid,
consistencygroup_id=consistencygroup_id,
allow_reschedule=allow_reschedule,
reschedule_context=context_saved,
request_spec=request_spec,
filter_properties=filter_properties)
create_volume()函数主要工作就是利用TaskFlow库构建卷的flow并执行。
# cinder/volume/flows/manager/create_volume.py
def get_flow(context, db, driver, scheduler_rpcapi, host, volume_id,
allow_reschedule, reschedule_context, request_spec,
filter_properties, snapshot_id=None, image_id=None,
source_volid=None, source_replicaid=None,
consistencygroup_id=None):
volume_flow.add(ExtractVolumeSpecTask(db),
NotifyVolumeActionTask(db, "create.start"),
CreateVolumeFromSpecTask(db, driver),
CreateVolumeOnFinishTask(db, "create.end"))
return taskflow.engines.load(volume_flow, store=create_what)
创建Volume的flow共添加了4个task:ExtractVolumeSpecTask、NotifyVolumeActionTask、CreateVolumeFromSpecTask、CreateVolumeOnFinishTask。
其中最重要的是CreateVolumeFromSpecTask,它根据要求实现卷的创建。
# cinder/volume/flows/manager/create_volume.py
class CreateVolumeFromSpecTask(flow_utils.CinderTask):
"""Creates a volume from a provided specification.
def execute(self, context, volume_ref, volume_spec):
if create_type == 'raw':
model_update = self._create_raw_volume(context,
volume_ref=volume_ref,
**volume_spec)
elif create_type == 'snap':
model_update = self._create_from_snapshot(context,
volume_ref=volume_ref,
**volume_spec)
elif create_type == 'source_vol':
model_update = self._create_from_source_volume(
context, volume_ref=volume_ref, **volume_spec)
elif create_type == 'source_replica':
model_update = self._create_from_source_replica(
context, volume_ref=volume_ref, **volume_spec)
elif create_type == 'image':
model_update = self._create_from_image(context,
volume_ref=volume_ref,
**volume_spec)
raise
return volume_ref
CreateVolumeFromSpecTask区分了5种创建Volume的方式:建立raw格式的新卷,从快照建立新卷,从已有卷建立新卷,从副本建立新卷,从镜像建立新卷。
对于建立raw格式新卷的情况,将直接调用指定Driver的create_volume()函数进行创建。
def _create_raw_volume(self, context, volume_ref, **kwargs):
return self.driver.create_volume(volume_ref)
对于默认的LVMISCSIDriver,就是直接调用”lvcreate”命令创建Volume。
# cinder/volume/drivers/lvm.py
class LVMVolumeDriver(driver.VolumeDriver):
def _create_volume(self, name, size, lvm_type, mirror_count, vg=None):
vg_ref = self.vg
if vg is not None:
vg_ref = vg
vg_ref.create_volume(name, size, lvm_type, mirror_count)
def create_volume(self, volume):
"""Creates a logical volume."""
mirror_count = 0
if self.configuration.lvm_mirrors:
mirror_count = self.configuration.lvm_mirrors
self._create_volume(volume['name'],
self._sizestr(volume['size']),
self.configuration.lvm_type,
mirror_count)
到此,一个新的Volume被创建成功,此后,Nova会根据这个Volume的ID调用cinder.volume.manager.VolumeManager.initialize_conneion(),该函数会根据指定的方式(比如默认TGT)创建iSCSI Target,并返回Target的相关信息,比如iSCSI的iqn,之后Nova就可以通过该存储节点的IP地址和iqn来连接并且挂载这个Volume。
推荐阅读
-
jQuery选择器源码解读(五):tokenize的解析过程
-
Mybaits 源码解析 (二)----- 根据配置文件创建SqlSessionFactory(Configuration的创建过程)
-
MyBatis源码分析之——配置解析创建SqlSessionFactory的过程
-
源码解读Spring-Integration执行过程
-
Mybaits 源码解析 (四)----- SqlSession的创建过程(看懂框架源码再也不用死记硬背面试题)
-
jQuery选择器源码解读(五):tokenize的解析过程
-
Mybaits 源码解析 (二)----- 根据配置文件创建SqlSessionFactory(Configuration的创建过程)
-
Spring 源码解析 - bean 的创建过程
-
Spring容器的创建过程源码解析
-
21--Spring创建Bean的过程(三),构造函数实例化源码解析