OpenStack-Cinder创卷代码走读(Grizzly)

http://blog.csdn.net/sxmatch/article/details/8839892

刚开始学习OpenStack,第一次走读代码,有很多不懂的地方,欢迎大家指正。

这块也是在看代码过程中写下的笔记,记录在这里:
1.  api-paste.ini中定义了请求消息的路由路径,分为V1,V2两个版本的API。

2.  [composite:openstack_volume_api_v1]

3.  [composite:openstack_volume_api_v2]

4.  以V2中走keystone鉴权路径为例,分别要走 faultwrap sizelimit authtoken keystonecontext apiv2 这个步骤。

5.  消息经过前4个步骤处理后,走到apiv2这个应用步骤,该应用的定义为
      [app:apiv2] paste.app_factory =cinder.api.v2.router:APIRouter.factory

6.  cinder.api.v2.router:APIRouter类继承自cinder.api.openstack.APIRouter,因此会调用父类的factory方法。该父类在init时会初始化一系列的变量,包括ExtensionManager和ProjectMapper.现在还不太明白这两个变量起什么作用,但是感觉是重要的变量。还会调用三个方法:
        self._setup_routes(mapper,ext_mgr)
        self._setup_ext_routes(mapper,ext_mgr)
        self._setup_extensions(ext_mgr)

7.  最后cinder.api.openstack.APIRouter在init方法最后又会调用其父类wsgi.Router的init方法,将mapper: ProjectMapper传入, wsgi.Router中会创建用于URL映射控制的routes库的routes.middleware.RoutesMiddleware类。

8.  通过routes的URL映射,创建卷的请求被dispatch到了volumes.py中的VolumeController类,并调用创建卷的方法defcreate(self, req, body):

9.  Create方法中,首先进行请求格式的校验,判断post的body中是否有volume参数存在。
10.然后,从body的请求中获取name,description参数,由于在V1接口中这两个参数为display_name和display_description,因此在V2接口中还专门对这两个参数进行了重名称,保持和V1一致。

11.除了name和description外,然后根据参数中volume_type的ID,从数据库中获取对应的volume_type的值,放入kwargs中,如果volumeType未找到,则会报异常。

12.取metadata参数,放入kwargs中

13.如果参数中有snapshot ID参数,则从数据库中取快照的信息放入kwargs中,否则置为none;

14.取source_volid参数,如果有则从数据库中取source voulme的信息,如果没有则置为null.

15.取size参数,如果用户没有指定该参数但是snapshot的信息时,size以snapshot中volume_size为准;另一种情况,如果没有指定该参数但是有source_volume信息时,以source_volume中的size为准,由此可以看出,openstack至少支持3种创建方式:基本创建;根据卷快照创建;根据另一个卷创建(克隆卷?)。

16.如果ext_mgr (什么作用?)中指定了'os-image-create',则从请求中还要获取imageRef参数,并且这个参数和snapshot_id参数不能同时指定。并从imageRef中获取image_uuid参数,放入kwargs中。这样Cinder就又多了一种创卷方式:从镜像创建卷。

17.取请求中的availability_zone参数,放入kwargs中。

18.调用volume_api.create(为volume包下的api.py中的API类方法)方法,创建卷。该方法的入参为:(context,size, name, description, snapshot=None,
    image_id=None, volume_type=None, metadata=None, availability_zone=None, source_volume=None)

19.该方法首先进行参数校验,1.不允许snapshot和source_volume参数同时指定。2.验证该用户是否有权限进程创卷操作。3.如果snapshot参数不是空,判断snapshot的状态是否为available,否则抛出异常,同时如果size参数也为空,则从snapshot中取volume_size作为要创建卷的size,并取snapshot id。4.如果source_volume参数不是空,则判断source_volume状态是否为error,如果是则抛出异常。同时取source_volume的size作为卷的size,如果用户指定的size小于source_volume的size,则抛出异常,并取source_volume的id。5.校验size如果不是integer或者小于等于0,则抛出异常。6,参数中如果只有image_id,则调用glance接口查询image的metadata,并计算镜像的GB大小,如果镜像大于指定卷的size,则抛异常。

20.调用Quita的方法创建reservations(应该是资源的预留).这块如果有异常,会分为volume size不足和volume个数不足抛异常。


21.获取availability_zone参数,如果为null,则取默认值。如果请求中没有volume_type和source_volume,则volume_type去默认值,如果请求中没有volume_type,但是有source_volume,则取source_volume的volume_type_id值。否则从volume_type取volume_type_id的值。

22.检查请求中的metadata

23.组装options,包括了各种校验后的参数,然后将创卷数据插入数据库,插入数据库时会生成卷ID(uuid),QUTAS也提交资源预留值。失败则都回归

24.组装request_spec,并调用私有方法_cast_create_volume,该方法做以下几个判断:
     1.  如果请求request_spec中有snapshot_id(从快照创建卷)并且snapshot_same_host开关是true,则取该快照的源卷所在的主机作为新创建卷的主机,scheduled_at选取为now,并更新数据库,然后调用volume_rpcapi.create_volume开始创卷。
     2.  如果请求中指定了源卷(从卷创建卷),则从数据库中取源卷的主机,scheduled_at选取为now,并更新数据库,然后调用volume_rpcapi.create_volume开始创卷
     3.  其他情况则调用scheduler_rpcapi.create_volume方法开始创卷。


25.volume_rpcapi.create_volume是调用manager.py中的create_volume方法,   该方法先从数据库中取出volume的信息,然后调用  volume_utils.notify_about_volume_usage方法(是不是通知RabbitMQ?)。然后继续从volume信息中取vol_name,vol_size,并且如果入参中有snapshot_id,说明从快照创建卷,则从DB中取该snapshot的信息,如果入参中有source_volID,说明是从已有卷创建卷,则从DB中取该源卷信息,如果入参中有image_id,说明是从镜像创建卷,则从glance中获取镜像服务器信息,镜像ID,镜像位置,镜像的metadata.然后调用该类的私有方法_create_volume,该方法首先判断如果snapshot_ref,imag_id,srcvol_ref都是空,则说明是创建一个空卷,就调用driver.create_volume去创卷,如果有snapshot_ref参数,则调用driver.create_volume_from_snapshot方法去创卷,如果请求中有源卷的参数,则调用driver.create_cloned_volume去创卷(实际上就是克隆一个卷)。如果请求中有镜像参数,则调用driver.clone_image方法去创卷,如果clone_image失败,则调用普通创卷方法先创建个空卷,然后将卷状态置为downloading,然后调用_copy_image_to_volume方法把镜像内容拷贝入卷中。

26._create_volume方法会有两个返回值,model_update和cloned.如果有创卷中有异常,会判断如果是根据源卷创建的话,则回滚源卷的状态。同时从新进行调度。

27.如果返回值model_update为true,会在数据库中更新创建好的卷,同时如果是从卷创建卷的方式时,还有把源卷的Glance metadata拷贝一份给新的卷,也就是说新卷将保留源卷的metadata.

28.然后会调用driver.create_export方法,这个方式似乎是根据不同的存储返回卷的位置,例如huawei iscsi driver中返回的是lun_id.

29.流程继续,会根据请求如果有snapshot_id,也会拷贝Glance metadata(应该是这个快照对应的卷的metadata)给新卷。如果是从image创建卷的方式,如果image有metadata,也会拷贝镜像的属性到volume_glance_metadata表中。会写入这个卷对应镜像的ID,名称及其他属性。

30.最后更新数据库中的卷状态和创建时间,并调用_notify_about_volume_usage方法通知“create.end”,并返回卷ID。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值