欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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。
相关标签: cinder