分享

OpenStack Cinder代码(H版)create等流程简析

xioaxu790 发表于 2014-9-16 21:19:18 [显示全部楼层] 回帖奖励 阅读模式 关闭右栏 0 10710
问题导读
1、你是如何理解OpenStack各个模块的作用?
2、cinder中create snapshot的流程有哪些?
3、cinder中create volume的流程是怎样的?





一、概况
OpenStack的各个模块都有相应的客户端模块实现,其作用是为用户访问具体模块提供了接口,同时也作为模块之间相互访问的途径。

相应的,OpenStack的Cinder模块分为两个组件:cinderclient和cinder,其代码分别参见如下:
https://github.com/openstack/python-cinderclient
https://github.com/openstack/cinder

在OpenStack环境中,使用cinder create命令创建volume等,cinderclient会对命令行参数进行解析和封装,处理完成后发送给cinder,cinder收到请求后,会解析、执行请求并响应创建消息。

下面来根据源码具体分析。


二、cinder服务启动流程
1. 脚本cinder.bin.cinder-all('osapi_volume'初始化了一个服务类的对象cinder.service.WSGIService object)

2. cinder.service:WSGIService(调用wsgi.Server,管理WSGI服务的类)

3. cinder.wsgi:Server(wsgi.Server类的对象初始化操作,但并不启动WSGI服务)

4. 脚本cinder.bin.cinder-all('cinder-volume'和'cinder-scheduler'初始化了两个服务类的对象cinder.service.Service object)

5. cinder.service:Service.create(进行了一系列变量的初始化操作后,初始化对象获取操作)

6. 脚本cinder.bin.cinder-all(service.serve(*servers)会启动三个服务)

7. cinder.service:serve(循环调用_launcher.launch_server)

8. cinder.service:Launcher.launch_server(调用eventlet.spawn,建立一个新的绿色线程用来运行变量func所指定的方法;调用self.run_server)

9. cinder.service:Launcher.run_server(调用server.start和server.wait)

① cinder.service.WSGIService所对应的start方法的实现

a) cinder.service:WSGIService.start(调用self.server.start)

b) cinder.wsgi:Server.start(调用self._start,在_start中又调用eventlet.wsgi.server,启动了'osapi_volume'所指定的阻塞式eventlet WSGI服务)

② cinder.service.Service所对应的start方法的实现

a) cinder.service:Service.start(主要实现了获取所有服务、创建到RPC的连接,创建不同类型的消息消费者,启动消费者线程用来执行未来服务运行过程中所要获取到的消息)

10. 脚本cinder.bin.cinder-all(最后一句service.wait()调用了方法wait)

11. cinder.service:wait(实现了等待所有服务运行结束或停止,然后关闭RPC协议框架)


三、cinderclient部分create流程
1. cinderclient部分create volume流程

① cinderclient.shell:main(调用OpenStackCinderShell().main)

② cinderclient.shell:OpenStackCinderShell.main(对命令行参数进行解析等一系列操作;方法main的最后一句args.func(self.cs, args)解析之后为do_create)

③ cinderclient.v1.shell:do_create或cinderclient.v2.shell:do_create(调用cs.volumes.create)

④ cinderclient.v1.volumes:VolumeManager.create或cinderclient.v2.volumes:VolumeManager.create(对body进行赋值,最后调用self._create)

⑤ cinderclient.base:Manager._create(通过self.api.client.post把url和body内容传递下去)

⑥ cinderclient.client:HTTPClient.post(调用self._cs_request,在_cs_request中又调用self.request)

⑦ cinderclient.client:HTTPClient.request(调用requests.request,requests库遵循HTTP协议,实现了访问远程服务器并等待响应的功能)

2. cinderclient部分create snapshot流程

① cinderclient.shell:main(调用OpenStackCinderShell().main)

② cinderclient.shell:OpenStackCinderShell.main(对命令行参数进行解析等一系列操作;方法main的最后一句args.func(self.cs, args)解析之后为do_snapshot_create)

③ cinderclient.v1.shell:do_snapshot_create或cinderclient.v2.shell:do_snapshot_create(调用cs.volume_snapshots.create)

④ cinderclient.v1.volume_snapshots:SnapshotManager.create或cinderclient.v2.volume_snapshots:SnapshotManager.create(对body进行赋值,最后调用self._create)

⑤ cinderclient.base:Manager._create(通过self.api.client.post把url和body内容传递下去)

⑥ cinderclient.client:HTTPClient.post(调用self._cs_request,在_cs_request中又调用self.request)

⑦ cinderclient.client:HTTPClient.request(调用requests.request,requests库遵循HTTP协议,实现了访问远程服务器并等待响应的功能)

3. cinderclient部分create backup流程

① cinderclient.shell:main(调用OpenStackCinderShell().main)

② cinderclient.shell:OpenStackCinderShell.main(对命令行参数进行解析等一系列操作;方法main的最后一句args.func(self.cs, args)解析之后为do_backup_create)

③ cinderclient.v1.shell:do_backup_create或cinderclient.v2.shell:do_backup_create(调用cs.backups.create)

④ cinderclient.v1.volume_backups:VolumeBackupManager.create或cinderclient.v2.volume_backups:VolumeBackupManager.create(对body进行赋值,最后调用self._create)

⑤ cinderclient.base:Manager._create(通过self.api.client.post把url和body内容传递下去)

⑥ cinderclient.client:HTTPClient.post(调用self._cs_request,在_cs_request中又调用self.request)

⑦ cinderclient.client:HTTPClient.request(调用requests.request,requests库遵循HTTP协议,实现了访问远程服务器并等待响应的功能)


四、cinder部分通用create流程
1. 使用若干中间件对客户端发送过来的请求消息进行过滤(解封和封装)处理

① 配置文件api-paste.ini的解析

a) 配置文件/etc/cinder/api-paste.ini中的[composite:osapi_volume](XXXX/XXXX形式的API交给apiversions来处理,XXXX/V1/XXXX形式的API交给openstack_volume_api_v1来处理,XXXX/V2/XXXX形式的API交给openstack_volume_api_v2来处理)

b) 配置文件/etc/cinder/api-paste.ini中的[pipeline:apiversions](使用pipeline section实现faultwrap对osvolumeversionapp的过滤操作)

c) 配置文件/etc/cinder/api-paste.ini中的[composite:openstack_volume_api_v1]或[composite:openstack_volume_api_v2](在参数noauth,keystone和keystone_nolimit中,分别集成了多个过滤器faultwrap、sizelimit等,以及应用apiv1或apiv2)

② FaultWrapper(关于错误异常的处理)

a) 配置文件/etc/cinder/api-paste.ini中的[filter:faultwrap](通过此过滤器,调用类FaultWrapper)

b) cinder.api.middleware.fault:FaultWrapper.__call__(调用self._error进行错误检测)

c) cinder.api.middleware.fault:FaultWrapper._error(关于错误异常的处理)

③ RequestBodySizeLimiter(对请求消息中body部分长度的检测)

a) 配置文件/etc/cinder/api-paste.ini中的[filter:sizelimit](通过此过滤器,调用类RequestBodySizeLimiter)

b) cinder.api.middleware.sizelimit:RequestBodySizeLimiter.__call__(对请求消息中body部分长度的检测)

④ 身份认证处理

a) 配置文件/etc/cinder/api-paste.ini中的[filter:noauth](通过此过滤器,调用类NoAuthMiddleware)或[filter:keystonecontext](通过此过滤器,调用类CinderKeystoneContext)

b) cinder.api.middleware.auth:NoAuthMiddleware.__call__或cinder.api.middleware.auth:CinderKeystoneContext.__call__

⑤ APIRouter(对请求消息的路由处理)

a) 配置文件/etc/cinder/api-paste.ini中的[app:apiv1]或[app:apiv2](通过此过滤器,调用类APIRouter)

b) cinder.api.v1.Router:APIRouter或cinder.api.v2.Router:APIRouter(对请求消息的路由处理)

c) cinder.api.openstack.__init__:APIRouter.__init__

d) cinder.api.extensions:ExtensionManager

e) cinder.api.v1.Router:APIRouter._setup_routes

f) cinder.api.openstack.__init__:APIRouter._setup_ext_routes(在一个控制器中单纯地实现新的Restful资源功能,调用wsgi.Resource)

g) cinder.api.openstack.__init__:APIRouter._setup_extensions

h) cinder.wsgi:Router.__init__

⑥ Resource(action执行前的一些预处理)

a) cinder.api.openstack.wsgi:Resource.__call__(对获取到的响应信息进行若干格式化上的转换和处理)

b) cinder.api.openstack.wsgi:Resource._process_stack(主要完成了请求信息完整的执行过程)

2. 获取要执行的方法及其相关的扩展方法

cinder.api.openstack.wsgi:Resource.get_method(获取要执行的action方法及相关的扩展方法)

3. 请求中body部分的反序列化

cinder.api.openstack.wsgi:Resource.deserialize(确定反序列化的方法,实现对body的反序列化操作)

4. 所获取的action相关的扩展方法的执行

cinder.api.openstack.wsgi:Resource.pre_process_extensions(执行之前获取的扩展方法)

5. 执行具体的方法(如卷的创建方法create)

cinder.api.openstack.wsgi:Resource.dispatch(执行之前获取的action方法,获取并返回方法执行的结果)

6. 响应信息的生成
① cinder.api.openstack.wsgi:Resource.preserialize(根据accept确定相应对象所要使用的序列化方法或类,进行类的初始化操作)

② cinder.api.openstack.wsgi:Resource.serialize(进行序列化操作,从而形成响应信息中的body部分)


五、cinder部分create volume流程
1. cinder.api.v1.volumes:VolumeController.create或cinder.api.v2.volumes:VolumeController.create(通过req和body获取创建卷所需的相关参数;调用self.volume_api.create)

2. 调用方法create实现卷的创建

① cinder.volume.api:API.create(构建字典create_what,整合创建卷的具体参数;调用create_volume.get_api_flow)

② cinder.volume.flows.create_volume.__init__:get_api_flow(构建并返回用于创建卷的flow;调用linear_flow.Flow等)

a) cinder.taskflow.patterns.linear_flow:Flow.__init__(初始化一个Flow类)

b) cinder.taskflow.patterns.linear_flow:Flow.add(按顺序添加相关的task到flow中)

c) cinder.volume.flows.utils:attach_debug_listeners(返回添加task后的flow给调用者)

③ cinder.taskflow.patterns.linear_flow:Flow.run(执行用于创建卷的flow,执行获取到的task列表,执行完成后对task状态进行判断,如果不成功则进行回滚操作)

a) cinder.volume.flows.create_volume.__init__:VolumeCastTask.__call__(VolumeCastTask是创建卷最关键的一个task,我们重点分析这个;调用self._cast_create_volume)

b) cinder.volume.flows.create_volume.__init__:VolumeCastTask._cast_create_volume(远程调用创建卷的方法,实现卷的创建操作,对参数内容进行判断,确定创建卷的方式、创建卷到哪个host等;调用self.scheduler_rpcapi.create_volume)

c) cinder.scheduler.rpcapi:SchedulerAPI.create_volume(通过cast广播方式实现远程调用方法create_volume)

d) cinder.scheduler.manager:SchedulerManager.create_volume(调用create_volume.get_scheduler_flow)

e) cinder.volume.flows.create_volume.__init__:get_scheduler_flow(创建flow,并将三个task添加到该flow中,其中最重要的task是schedule_create_volume)

f) Scheduler在未指明host的情况下,有三种算法选择host(FilterScheduler、ChanceScheduler、SimpleScheduler),通过配置文件/etc/cinder/cinder.conf可知,scheduler_driver默认指定cinder.scheduler.filter_scheduler.FilterScheduler

g) cinder.scheduler.filter_scheduler:FilterScheduler.schedule_create_volume(调用self._schedule,在_schedule中又调用self._get_weighted_candidates)

h) cinder.scheduler.filter_scheduler:FilterScheduler._get_weighted_candidates(self._get_weighted_candidates对可用的host进行weight判断,过滤选择合适的主机;接着schedule_create_volume调用self.volume_rpcapi.create_volume)

i) cinder.volume.rpcapi:VolumeAPI.create_volume(通过cast广播方式实现远程调用方法create_volume)

j) cinder.volume.manager:VolumeManager.create_volume(调用create_volume.get_manager_flow)

k) cinder.volume.flows.create_volume.__init__:get_manager_flow(创建flow,并将若干个task添加到该flow中,其中最重要的task是CreateVolumeFromSpecTask,实现卷的创建;创建卷有四种方式:raw卷、从快照创建、克隆、从镜像创建)

l) 创建raw卷

cinder.volume.flows.create_volume.__init__:CreateVolumeFromSpecTask._create_raw_volume(调用self.driver.create_volume;Driver是底层采用的驱动,可以是LVM、GlusterFS、Ceph(RBD)等)

cinder.volume.drivers.glusterfs:GlusterfsDriver.create_volume(这里以GlusterFS为例,判断相应的目录是否挂载,然后调用self._do_create_volume)

cinder.volume.drivers.glusterfs:GlusterfsDriver._do_create_volume(有两种创建方式:qcow2和regular_file;根据配置文件/etc/cinder/cinder.conf中的glusterfs_qcow2_volumes值决定采用那种方式,默认使用_create_regular_file方式)

cinder.volume.drivers.nfs:RemoteFsDriver._create_regular_file(_create_regular_file通过dd命令创建块存储;而_create_qcow2_file通过qemu-img命令创建块存储)

m) 从快照创建卷

cinder.volume.flows.create_volume.__init__:CreateVolumeFromSpecTask._create_from_snapshot

n) 克隆

cinder.volume.flows.create_volume.__init__:CreateVolumeFromSpecTask._create_from_source_volume

o) 从镜像创建卷

cinder.volume.flows.create_volume.__init__:CreateVolumeFromSpecTask._create_from_image

④ volume = flow.results[uuid]['volume'](从flow中获取创建卷的反馈信息)

3. 获取创建卷后的反馈信息,实现格式转换,并获取其中重要的属性信息,以便上层调用生成卷创建的响应信息。


六、cinder部分create snapshot流程
1. cinder.api.v1.snapshots:SnapshotsController.create或cinder.api.v2.volumes:SnapshotsController.create(通过req和body获取创建卷所需的相关参数;调用self.volume_api.create_snapshot或self.volume_api.create_snapshot_force)

2. 调用方法create_snapshot实现快照的创建

① cinder.volume.api:API.create_snapshot或cinder.volume.api:API.create_snapshot_force(调用self._create_snapshot)

② cinder.volume.api:API._create_snapshot(整合创建快照的具体参数;先调用self.db.snapshot_create,再调用self.volume_rpcapi.create_snapshot)

③ cinder.db.api:snapshot_create(创建快照的数据库信息)

④ cinder.volume.rpcapi:VolumeAPI.create_snapshot(通过cast广播方式实现远程调用方法create_snapshot)

⑤ cinder.volume.manager:VolumeManager.create_snapshot(调用self.driver.create_snapshot;Driver是底层采用的驱动,可以是LVM、GlusterFS、Ceph(RBD)等)

⑥ cinder.volume.drivers.glusterfs:GlusterfsDriver.create_snapshot(这里以GlusterFS为例)

a) 卷被挂载的情况下:

cinder.volume.drivers.glusterfs:GlusterfsDriver._create_qcow2_snap_file(通过qemu-img命令创建快照)

cinder.compute.nova:API.create_volume_snapshot(调用nova.assisted_volume_snapshots.create,由Nova来完成快照数据写入)

b) 卷未被挂载的情况下:

cinder.volume.drivers.glusterfs:GlusterfsDriver._create_qcow2_snap_file(通过qemu-img命令创建快照)

cinder.volume.drivers.glusterfs:GlusterfsDriver._create_snapshot(先调用self._read_info_file,再调用self._write_info_file)

cinder.volume.drivers.glusterfs:GlusterfsDriver._write_info_file(将快照数据写入指定路径中)

3. 获取创建快照后的反馈信息,实现格式转换,并获取其中重要的属性信息,以便上层调用生成快照创建的响应信息。


七、cinder部分create backup流程
待补充


八、参考资料
1. 《OpenStack源码分析-Cinder》:http://blog.csdn.net/gaoxingnengjisuan/article/category/1853287

没找到任何评论,期待你打破沉寂

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关闭

推荐上一条 /2 下一条