storage - cinder(1)

来源:互联网 发布:opencv java 高斯模糊 编辑:程序博客网 时间:2024/05/17 02:05

前面也说过存储,也提过cinder, 从horizon串到nova,串到ironic,中间穿着说了keystone和neutron,基本上各个openstack的module都提到了,按照我做事的风格,

我要再捋一遍,细节的地方不会像前面,从api service收到请求开始讲,会直接从重要地方开始。

和看nova代码,最首先肯定是看创建虚机的流程一样,看cinder,从创建volume开始:

当然了, 和前面说的一样,根据官网文档,很方便理解传入参数的意义:http://developer.openstack.org/api-ref-blockstorage-v2.html

创建volume传入参数中可能包含:

snapshot_id:To create a volume from an existing snapshot, specify the ID of the existing volume snapshot. The volume is

created in same availability zone and with same size as the snapshot.

source_volid: To create a volume from an existing volume, specify the ID of the existing volume. The volume is created with

the same size as the source volume.

还有可能包含source_replica,其实也可以理解,归根到底都落到:

new_volume = self.volume_api.create(context,
                                            size,volume.get('display_name'),volume.get('display_description'),
                                            **kwargs)#根据前面的参数对应不同创建volume的方式

一切都是从这里开始:self.volume_api = cinder_volume.API()

在cinder.common.config中可以看到其默认为 'cinder.volume.api.API', 

trace此类,可以看到除了做一些对参数的判断外,拿到了scheduler,rpcapi,再次create

sched_rpcapi = self.scheduler_rpcapi if not cgsnapshot else None
 volume_rpcapi = self.volume_rpcapi if not cgsnapshot else None  #
flow_engine = create_volume.get_flow(self.db,
                                                 self.image_service,
                                                 availability_zones,
                                                 create_what,
                                                 sched_rpcapi,
                                                 volume_rpcap
i)

 flow_engine.run()#执行任务流

可以看到这里用到了taskflow, 在mark link中有讲到taskflow的用法和作用。

在get_flow中,通过api_flow = linear_flow.Flow(flow_name),即一个线性顺序执行的任务流,依次执行一串动作(这种各个操作之间有紧密联系的动作,

使用work_flow是个很好的选择

api_flow.add则加入一系列的Task,每个task有execute方法,在flow_engine.run()中依次调用各个task的execute方法。

最后一个flow的task是关键:api_flow.add(VolumeCastTask(scheduler_rpcapi, volume_rpcapi, db_api))

这里在做什么,”cast“,不错,在做rpc调用!

如果指定了snapshot id或者source_volid(前面提及),则有对应的host信息,知道volume在哪里创建,也就不需要使用scheduler进行调度,

直接self.volume_rpcapi.create_volume, 否则self.scheduler_rpcapi.create_volume(调度分支如何进行,先留着), 来看看:

已知host时:

values = {'host': host, 'scheduled_at': now}
volume_ref = self.db.volume_update(context, volume_id, values)#volume_ref作为create_volume的参数传入

此处self.volume_rpcapi为cinder/volume/rpcapi.py中的VolumeAPI, create执行cast方法,其中topic为“cinder-volume”, 而在cmd包中启动cinder相关

服务时候,有对该消息队列的监听,后落到cinder/volume/manager.py中的VolumeManager,执行volume manager中的create_volume方法


需要注意的是

在volumemanager中也有:flow_engine = create_volume.get_flow,同时执行task flow,不错,这里的create_volume和前面的不同:

前面create_volume对应cinder/volume/flow/api/create_volume.py

这里是cinder/volume/flow/manager/create_volume.py

逻辑很清楚!

那么这里flow_engine中加了一串task,实际真正对应物理上volume建立的是哪儿呢?是task:CreateVolumeFromSpecTask(db,driver)

在CreateVolumeFromSpecTask的execute方法中,对不同情况执行不同的create动作:

       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)

这里分为raw,snap,source_vol, source_replica, image五种,对第一个raw:

    def _create_raw_volume(self, context, volume_ref, **kwargs):
        return self.driver.create_volume(volume_ref)

而这里的driver,在volume manager的__init__中初始化,默认为cinder.volume.drivers.lvm.LVMISCSIDriver,其他的实现在cinder/volume/drivers下,

不错,有!很!多!,事实上,对云而言,数据是最重要的,效率可以稍微差一些,数据一定不能出问题,镜像/虚机/用户数据等都可以放在存储上,做

底线报障,因此存储在云计算中的地位更加重要(相对的)

以此处的lvm driver为例,其initial过程在volumemanager中完成,执行driver.check_for_setup_error() ,得到LVM Driver中:

self.vg = lvm.LVM

最后对lvm而言,就是执行:

from cinder.openstack.common import processutils as putils

执行命令生成volume即可。


总的来说,cinder的过程和nova十分相似(事实上也不只和nova :)),


mark link:

http://docs.openstack.org/developer/taskflow/

http://blog.csdn.net/epugv/article/details/17565759taskflow的用处


0 0