阅读导读:
1.如何 获取要执行的action方法及其相关的扩展方法?
2.Resource类中的__call__(self,request)方法如何实现?
3. meth的作用?
4.如何 从request.environ中获取要执行的action方法?
5.如何对body进行反序列化操作?
感谢朋友支持本博客,欢迎共同探讨交流,由于能力和时间有限,错误之处在所难免,欢迎指正!
这篇博客我们来继续解析Openstack Cinder中建立volume过程的实现源码。上篇博客中我们解析了应用若干中间件对客户端发送过来的请求信息进行过滤处理,这里我们来分析方法class Resource(wsgi.Application)----def __call__(self, request),具体深入解析cinder建立volume的过程。
来看方法class Resource(wsgi.Application)----def __call__(self, request)的源码实现:
def __call__(self, request):
"""
WSGI method that controls (de)serialization and method dispatch.
request = POST /v1/ecf0109bda814fa1a548af63f9ada370/volumes HTTP/1.0
......
{"volume": {"status": "creating",
"availability_zone": null,
"source_volid": null,
"display_description": null,
"snapshot_id": null,
"user_id": null,
"size": 1,
"display_name": "shinian01",
"imageRef": null,
"attach_status": "detached",
"volume_type": null,
"project_id": null,
"metadata": {}}}
"""
LOG.info("%(method)s %(url)s" % {"method": request.method, "url": request.url})
# Identify the action, its arguments, and the requested
# content type
# 从request.environ中获取要执行的action方法;
action_args = self.get_action_args(request.environ)
action = action_args.pop('action', None)
"""
action_args = {'action': u'create', 'project_id': u'ecf0109bda814fa1a548af63f9ada370'}
action = create
action_args = {'project_id': u'ecf0109bda814fa1a548af63f9ada370'}
"""
# get_body:通过检测header,确定request body的内容类型;获取request中的body部分;
content_type, body = self.get_body(request)
"""
content_type = application/json
body = {"volume": {"status": "creating", "availability_zone": null, "source_volid": null, "display_description": null,
"snapshot_id": null, "user_id": null, "size": 1, "display_name": "shinian01", "imageRef": null, "attach_status": "detached",
"volume_type": null, "project_id": null, "metadata": {}}}
"""
# best_match_content_type:确定请求响应的内容类型;
accept = request.best_match_content_type()
"""
accept = application/json
"""
# NOTE(Vek): Splitting the function up this way allows for
# auditing by external tools that wrap the existing
# function. If we try to audit __call__(), we can
# run into troubles due to the @webob.dec.wsgify()
# decorator.
"""
request = POST /v1/ecf0109bda814fa1a548af63f9ada370/volumes HTTP/1.0
......
action = create
action_args = {'project_id': u'ecf0109bda814fa1a548af63f9ada370'}
content_type = application/json
body = {"volume": {"status": "creating", "availability_zone": null, "source_volid": null, "display_description": null,
"snapshot_id": null, "user_id": null, "size": 1, "display_name": "shinian01", "imageRef": null, "attach_status": "detached",
"volume_type": null, "project_id": null, "metadata": {}}}
accept = application/json
"""
return self._process_stack(request, action, action_args, content_type, body, accept) 复制代码
在这个方法中,主要实现了对request的若干预处理操作。
我们来看语句content_type, body = self.get_body(request),所实现的功能是通过检测header,确定request body的内容类型;获取request中的body部分; 输出示例:
content_type = application/json
body = {"volume": {"status": "creating", "availability_zone": null, "source_volid": null, "display_description": null, "snapshot_id": null, "user_id": null, "size": 1, "display_name": "shinian01", "imageRef":
null, "attach_status": "detached", "volume_type": null, "project_id": null, "metadata": {}}} 复制代码
下面我们来看方法_process_stack,这个方法主要完成了请求信息完整的执行过程。我们具体来看方法_process_stack的源码实现:
def _process_stack(self, request, action, action_args, content_type, body, accept):
"""
Implement the processing stack.
"""
# Get the implementing method
try:
# get_method:根据request确定要执行的action方法以及相关的扩展方法;
meth, extensions = self.get_method(request, action, content_type, body)
"""
request = POST /v1/ecf0109bda814fa1a548af63f9ada370/volumes HTTP/1.0
......
action = create
content_type = application/json
body = {"volume": {"status": "creating",
"availability_zone": null,
"source_volid": null,
"display_description": null,
"snapshot_id": null,
"user_id": null,
"size": 1,
"display_name": "shinian01",
"imageRef": null,
"attach_status": "detached",
"volume_type": null,
"project_id": null,
"metadata": {}}
}
<blockquote>meth = <bound method VolumeController.create of <cinder.api.v1.volumes.VolumeController object at 0x2998b10>> 复制代码
2.获取要执行的action方法及其相关的扩展方法
来看上述方法中的语句:
meth, extensions = self.get_method(request, action, content_type, body) 复制代码
这条语句实现的功能是根据request确定要执行的action方法以及相关的扩展方法;
我们来看方法get_method的源码实现:
def get_method(self, request, action, content_type, body):
"""
根据request确定要执行的action方法以及相关的扩展方法;
# request = POST /v1/ecf0109bda814fa1a548af63f9ada370/volumes HTTP/1.0
# ......
# action = create
# content_type = application/json
# body = {"volume": {"status": "creating", "availability_zone": null, "source_volid": null, "display_description": null, "snapshot_id": null, "user_id": null, "size": 1, "display_name": "shinian01", "imageRef": null, "attach_status": "detached", "volume_type": null, "project_id": null, "metadata": {}}}
"""
# Look up the method
try:
if not self.controller:
meth = getattr(self, action)
else:
meth = getattr(self.controller, action)
except AttributeError:
if (not self.wsgi_actions or action not in ['action', 'create', 'delete']):
# Propagate the error
raise
else:
return meth, self.wsgi_extensions.get(action, [])
if action == 'action':
# OK, it's an action; figure out which action...
mtype = _MEDIA_TYPE_MAP.get(content_type)
action_name = self.action_peek[mtype](body)
LOG.debug("Action body: %s" % body)
else:
action_name = action
# Look up the action method
return (self.wsgi_actions[action_name],
self.wsgi_action_extensions.get(action_name, [])) 复制代码
这个方法的实现主要分为两部分,分别是获取请求信息中action方法的具体路径和获取action方法相关的扩展方法及其具体路径。
首先来看语句:
try:
if not self.controller:
meth = getattr(self, action)
else:
meth = getattr(self.controller, action) 复制代码
实现了获取请求信息中action方法的具体路径。在这里self.controller = <cinder.api.v1.volumes.VolumeController object at 0x29cdb50>,在方法__call__调用之前就进行了初始化操作,指定了匹配于请求信息的action方法所在的控制器类。此时的输出示例:meth = <bound method VolumeController.create of <cinder.api.v1.volumes.VolumeController object at 0x29cdb50>> 复制代码
从而指定了匹配于请求信息的action方法的具体路径。再来看语句:
self.wsgi_extensions.get(action, []) 复制代码
实现了获取action方法相关的扩展方法及其具体路径。在这里
self.wsgi_extensions = {
'create': [<bound method SchedulerHintsController.create of <cinder.api.contrib.scheduler_hints.SchedulerHintsController object at 0x29b9ad0>>],
'detail': [<bound method VolumeTenantAttributeController.detail of <cinder.api.contrib.volume_tenant_attribute.VolumeTenantAttributeController object at 0x29b9c50>>, <bound method VolumeHostAttributeController.detail of <cinder.api.contrib.volume_host_attribute.VolumeHostAttributeController object at 0x298a750>>, <bound method VolumeMigStatusAttributeController.detail of <cinder.api.contrib.volume_mig_status_attribute.VolumeMigStatusAttributeController object at 0x298a990>>, <bound method VolumeImageMetadataController.detail of <cinder.api.contrib.volume_image_metadata.VolumeImageMetadataController object at 0x298add0>>],
'show': [<bound method VolumeTenantAttributeController.show of <cinder.api.contrib.volume_tenant_attribute.VolumeTenantAttributeController object at 0x29b9c50>>,<bound method VolumeHostAttributeController.show of <cinder.api.contrib.volume_host_attribute.VolumeHostAttributeController object at 0x298a750>>,<bound method VolumeMigStatusAttributeController.show of <cinder.api.contrib.volume_mig_status_attribute.VolumeMigStatusAttributeController object at 0x298a990>>,<bound method VolumeImageMetadataController.show of <cinder.api.contrib.volume_image_metadata.VolumeImageMetadataController object at 0x298add0>>]} 复制代码
这也是在类class Resource(wsgi.Application)的初始化方法__init__执行的过程中得到的,也就是类的初始化过程中得到的。
因为action = create,所以这里self.wsgi_extensions.get(action, []) = {'create': [>]} 复制代码
这就是匹配于action = create的扩展方法的具体路径。
在这个方法中,我们获取了请求信息中action方法的具体路径和action方法相关的扩展方法及其具体路径,为实现volume的建立的后续工作做好了准备。 我们回到语句:
meth, extensions = self.get_method(request, action, content_type, body) 复制代码
输出示例:
meth = <bound method VolumeController.create of <cinder.api.v1.volumes.VolumeController object at 0x2998b10>>
extensions = [<bound method SchedulerHintsController.create of <cinder.api.contrib.scheduler_hints.SchedulerHintsController object at 0x2985a90>>] 复制代码
相关文章:
Openstack Cinder中建立volume过程的源码解析(1)
http://www.aboutyun.com/thread-10217-1-1.html
1. cinder中卷的建立的过程中,客户端传递过来的request的执行过程是怎样的?
2. __call__方法都通过什么方法封装?
3.如何调用指定中间件的__call__方法?
Openstack Cinder中建立volume过程的源码解析(3)
http://www.aboutyun.com/thread-10215-1-1.html
1.get_serializer的作用?
2.isgeneratorfunction是用来做什么的?
3.什么是特殊的generator方法?
4.进行响应信息的序列化操作的步骤?
5.简述 在cinder模块中实现客户端发送过来的请求信息操作的主要的步骤?
Openstack Cinder中建立volume过程的源码解析(4)----以及taskflow相关解析
http://www.aboutyun.com/thread-10214-1-1.html
1.简述 cinder是如何实现卷的建立的?
2.简述 taskflow库来实现卷的简历过程?
3.如何 根据给定id来检索获取单个的卷的类型?
4.如何 构建并返回用于建立卷的flow?
5.如何声明flow是否是真的?
6.简述 建立卷的flow的步骤?
Openstack Cinder中建立volume过程的源码解析(5)----以及taskflow相关解析
http://www.aboutyun.com/thread-10213-1-1.html
1. 如何实现Flow类的初始化的?
2. 用于卷的建立的flow中都添加了哪些task?
3.ExtractVolumeRequestTask类的作用是什么?
4.如何 完全或部分的重置flow的内部的状态?
5.如何 从给定的卷中提取卷的id信息?
6. OnFailureChangeStatusTask类的作用?
Openstack Cinder中建立volume过程的源码解析(6)----以及taskflow相关解析
http://www.aboutyun.com/thread-10212-1-1.html
1.如何来运行已经构建好的flow?
2.run的源码如何实现及实现过程是什么?
3.resume_it的实现过程是什么?
4.类Runner的初始化方法是什么?
5.run_it的源码如何实现?
Openstack Cinder中建立volume过程的源码解析(7)----以及taskflow相关解析
http://www.aboutyun.com/thread-10211-1-1.html
1.关于flow中task执行的重要语句的实现基本解析完成,如何实现?
2.如果卷的建立出现异常,则如何执行相关的逆转回滚操作?
Openstack Cinder中建立volume过程的源码解析(8)
http://www.aboutyun.com/thread-10219-1-1.html
1. VolumeCastTask的源码如何实现?
2. 远程调用建立新卷的操作,有哪几个步骤?
3.task类VolumeCastTask具体是如何来实现根据请求信息进行卷的建立的?
Openstack Cinder中建立volume过程的源码解析(9)
http://www.aboutyun.com/thread-10210-1-1.html
1.如何 实现create_volume的源码?
2.Cast如何实现远程调create_volume?
3.如何实现调用方法self.volume_rpcapi.create_volume来实现在目标主机上新卷的建立?
如果转载,请保留作者信息。
博客地址:http://blog.csdn.net/gaoxingnengjisuan
邮箱地址:dong.liu@siat.ac.cn