问题导读
1、self._setup_routes(mapper, ext_mgr)方法的具体实现是怎样的?
2、调用mapper.connect和mapper.resource方法的作用?
(2) self._setup_routes(mapper, ext_mgr)
现在我们回到类/cinder/api/openstack/__init__.py----class APIRouter中的初始化方法:
- class APIRouter(base_wsgi.Router):
- def __init__(self, ext_mgr=None):
- if ext_mgr is None:
- if self.ExtensionManager:
- ext_mgr = self.ExtensionManager() (1)
- else:
- raise Exception(_("Must specify an ExtensionManager class"))
-
- mapper = ProjectMapper()
- self.resources = {}
- self._setup_routes(mapper, ext_mgr) (2)
- self._setup_ext_routes(mapper, ext_mgr) (3)
- self._setup_extensions(ext_mgr) (4)
- super(APIRouter, self).__init__(mapper) (5)
复制代码
来看第二条比较重要的语句:self._setup_routes(mapper, ext_mgr),具体来看方法_setup_routes的实现:
- def _setup_routes(self, mapper, ext_mgr):
- """
- mapper = Route name Methods Path
- mapper.connect = <b>>
-
- # 示例:
- # map.resource("message", "messages", collection={"rss": "GET"})
- # "GET /message/rss" => ``Messages.rss()``.
- # map.resource('message', 'messages', member={'mark':'POST'})
- # "POST /message/1/mark" => ``Messages.mark(1)``
- """
- self.resources['versions'] = versions.create_resource()
- mapper.connect("versions", "/",
- controller=self.resources['versions'],
- action='show')
- """
- mapper =
- Route name Methods Path
- versions /
- """
-
- mapper.redirect("", "/")
- self.resources['volumes'] = volumes.create_resource(ext_mgr)
- mapper.resource("volume", "volumes",
- controller=self.resources['volumes'],
- collection={'detail': 'GET'},
- member={'action': 'POST'})
- """
- mapper =
- Route name Methods Path
- ...... ......
- POST /{project_id}/volumes.:(format)
- POST /{project_id}/volumes
- formatted_detail_volumes GET /{project_id}/volumes/detail.:(format)
- detail_volumes GET /{project_id}/volumes/detail
- formatted_volumes GET /{project_id}/volumes.:(format)
- volumes GET /{project_id}/volumes
- formatted_new_volume GET /{project_id}/volumes/new.:(format)
- new_volume GET /{project_id}/volumes/new
- PUT /{project_id}/volumes/:(id).:(format)
- PUT /{project_id}/volumes/:(id)
- formatted_action_volume POST /{project_id}/volumes/:(id)/action.:(format)
- action_volume POST /{project_id}/volumes/:(id)/action
- DELETE /{project_id}/volumes/:(id).:(format)
- DELETE /{project_id}/volumes/:(id)
- formatted_edit_volume GET /{project_id}/volumes/:(id)/edit.:(format)
- edit_volume GET /{project_id}/volumes/:(id)/edit
- formatted_volume GET /{project_id}/volumes/:(id).:(format)
- volume GET /{project_id}/volumes/:(id)
- """
-
- self.resources['types'] = types.create_resource()
- mapper.resource("type", "types",
- controller=self.resources['types'])
- """
- mapper =
- Route name Methods Path
- ...... ......
- POST /{project_id}/types.:(format)
- POST /{project_id}/types
- formatted_types GET /{project_id}/types.:(format)
- types GET /{project_id}/types
- formatted_new_type GET /{project_id}/types/new.:(format)
- new_type GET /{project_id}/types/new
- PUT /{project_id}/types/:(id).:(format)
- PUT /{project_id}/types/:(id)
- DELETE /{project_id}/types/:(id).:(format)
- DELETE /{project_id}/types/:(id)
- formatted_edit_type GET /{project_id}/types/:(id)/edit.:(format)
- edit_type GET /{project_id}/types/:(id)/edit
- formatted_type GET /{project_id}/types/:(id).:(format)
- type GET /{project_id}/types/:(id)
- """
-
- self.resources['snapshots'] = snapshots.create_resource(ext_mgr)
- mapper.resource("snapshot", "snapshots",
- controller=self.resources['snapshots'],
- collection={'detail': 'GET'},
- member={'action': 'POST'})
- """
- mapper =
- Route name Methods Path
- ...... ......
- POST /{project_id}/snapshots.:(format)
- POST /{project_id}/snapshots
- formatted_detail_snapshots GET /{project_id}/snapshots/detail.:(format)
- detail_snapshots GET /{project_id}/snapshots/detail
- formatted_snapshots GET /{project_id}/snapshots.:(format)
- snapshots GET /{project_id}/snapshots
- formatted_new_snapshot GET /{project_id}/snapshots/new.:(format)
- new_snapshot GET /{project_id}/snapshots/new
- PUT /{project_id}/snapshots/:(id).:(format)
- PUT /{project_id}/snapshots/:(id)
- formatted_action_snapshot POST /{project_id}/snapshots/:(id)/action.:(format)
- action_snapshot POST /{project_id}/snapshots/:(id)/action
- DELETE /{project_id}/snapshots/:(id).:(format)
- DELETE /{project_id}/snapshots/:(id)
- formatted_edit_snapshot GET /{project_id}/snapshots/:(id)/edit.:(format)
- edit_snapshot GET /{project_id}/snapshots/:(id)/edit
- formatted_snapshot GET /{project_id}/snapshots/:(id).:(format)
- snapshot GET /{project_id}/snapshots/:(id)
- """
-
- self.resources['snapshot_metadata'] = snapshot_metadata.create_resource()
- snapshot_metadata_controller = self.resources['snapshot_metadata']
- mapper.resource("snapshot_metadata", "metadata",
- controller=snapshot_metadata_controller,
- parent_resource=dict(member_name='snapshot',
- collection_name='snapshots'))
- """
- mapper =
- Route name Methods Path
- ...... ......
- POST /{project_id}/snapshots/:snapshot_id/metadata.:(format)
- POST /{project_id}/snapshots/:snapshot_id/metadata
- formatted_snapshot_metadata GET /{project_id}/snapshots/:snapshot_id/metadata.:(format)
- snapshot_metadata GET /{project_id}/snapshots/:snapshot_id/metadata
- formatted_snapshot_new_snapshot_metadata GET /{project_id}/snapshots/:snapshot_id/metadata/new.:(format)
- snapshot_new_snapshot_metadata GET /{project_id}/snapshots/:snapshot_id/metadata/new
- PUT /{project_id}/snapshots/:snapshot_id/metadata/:(id).:(format)
- PUT /{project_id}/snapshots/:snapshot_id/metadata/:(id)
- DELETE /{project_id}/snapshots/:snapshot_id/metadata/:(id).:(format)
- DELETE /{project_id}/snapshots/:snapshot_id/metadata/:(id)
- formatted_snapshot_edit_snapshot_metadata GET /{project_id}/snapshots/:snapshot_id/metadata/:(id)/edit.:(format)
- snapshot_edit_snapshot_metadata GET /{project_id}/snapshots/:snapshot_id/metadata/:(id)/edit
- formatted_snapshot_snapshot_metadata GET /{project_id}/snapshots/:snapshot_id/metadata/:(id).:(format)
- snapshot_snapshot_metadata GET /{project_id}/snapshots/:snapshot_id/metadata/:(id)
- """
-
- mapper.connect("metadata",
- "/{project_id}/snapshots/{snapshot_id}/metadata",
- controller=snapshot_metadata_controller,
- action='update_all',
- conditions={"method": ['PUT']})
- """
- mapper =
- Route name Methods Path
- ...... ......
- metadata PUT /{project_id}/snapshots/{snapshot_id}/metadata
- """
-
- self.resources['limits'] = limits.create_resource()
- mapper.resource("limit", "limits",controller=self.resources['limits'])
- """
- mapper =
- Route name Methods Path
- ...... ......
- POST /{project_id}/limits.:(format)
- POST /{project_id}/limits
- formatted_limits GET /{project_id}/limits.:(format)
- limits GET /{project_id}/limits
- formatted_new_limit GET /{project_id}/limits/new.:(format)
- new_limit GET /{project_id}/limits/new
- PUT /{project_id}/limits/:(id).:(format)
- PUT /{project_id}/limits/:(id)
- DELETE /{project_id}/limits/:(id).:(format)
- DELETE /{project_id}/limits/:(id)
- formatted_edit_limit GET /{project_id}/limits/:(id)/edit.:(format)
- edit_limit GET /{project_id}/limits/:(id)/edit
- formatted_limit GET /{project_id}/limits/:(id).:(format)
- limit GET /{project_id}/limits/:(id)
- """
-
- self.resources['volume_metadata'] = volume_metadata.create_resource()
- volume_metadata_controller = self.resources['volume_metadata']
- mapper.resource("volume_metadata", "metadata",
- controller=volume_metadata_controller,
- parent_resource=dict(member_name='volume',
- collection_name='volumes'))
- """
- mapper =
- Route name Methods Path
- ...... ......
- POST /{project_id}/volumes/:volume_id/metadata.:(format)
- POST /{project_id}/volumes/:volume_id/metadata
- formatted_volume_metadata GET /{project_id}/volumes/:volume_id/metadata.:(format)
- volume_metadata GET /{project_id}/volumes/:volume_id/metadata
- formatted_volume_new_volume_metadata GET /{project_id}/volumes/:volume_id/metadata/new.:(format)
- volume_new_volume_metadata GET /{project_id}/volumes/:volume_id/metadata/new
- PUT /{project_id}/volumes/:volume_id/metadata/:(id).:(format)
- PUT /{project_id}/volumes/:volume_id/metadata/:(id)
- DELETE /{project_id}/volumes/:volume_id/metadata/:(id).:(format)
- DELETE /{project_id}/volumes/:volume_id/metadata/:(id)
- formatted_volume_edit_volume_metadata GET /{project_id}/volumes/:volume_id/metadata/:(id)/edit.:(format)
- volume_edit_volume_metadata GET /{project_id}/volumes/:volume_id/metadata/:(id)/edit
- formatted_volume_volume_metadata GET /{project_id}/volumes/:volume_id/metadata/:(id).:(format)
- volume_volume_metadata GET /{project_id}/volumes/:volume_id/metadata/:(id)
- """
-
- mapper.connect("metadata",
- "/{project_id}/volumes/{volume_id}/metadata",
- controller=volume_metadata_controller,
- action='update_all',
- conditions={"method": ['PUT']})
- """
- mapper =
- Route name Methods Path
- ...... ......
- metadata PUT /{project_id}/volumes/{volume_id}/metadata
- """</b>
复制代码
这里调用了方法mapper.connect和mapper.resource,实现进而调用python库routes,来实现从url提取相应的参数,如controller,action或者其它用户自己定义的变量,从而实现URL和相应action的映射。具体实现没有进行解析。也就是可以简单的理解为,通过得到的URL,通过这里实现的映射关系,进行格式匹配,具体定位到所要调用的方法上。具体的输出示例,如上述源码中已经给出,可以作为参考。
需要注意的是,这里实现的是模块中正规的功能的URL和具体方法的映射关系,也就是/cinder/api/v1/或者是/cinder/api/v2/包下的各个py文件中控制类下的功能方法。对于扩展功能方法的URL映射关系,在后面的语句中进行了实现。
(3)self._setup_ext_routes(mapper, ext_mgr)
来看方法/cinder/api/openstack/__init__.py----class APIRouter----def __init__中第三条比较重要的语句:
self._setup_ext_routes(mapper, ext_mgr)
具体来看方法_setup_ext_routes的源码实现:
- def _setup_ext_routes(self, mapper, ext_mgr):
- """
- mapper =
- Route name Methods Path
- versions /
- ...... ...... ......
- formatted_volume_edit_volume_metadata GET /{project_id}/volumes/:volume_id/metadata/:(id)/edit.:(format)
- volume_edit_volume_metadata GET /{project_id}/volumes/:volume_id/metadata/:(id)/edit
- formatted_volume_volume_metadata GET /{project_id}/volumes/:volume_id/metadata/:(id).:(format)
- volume_volume_metadata GET /{project_id}/volumes/:volume_id/metadata/:(id)
- metadata PUT /{project_id}/volumes/{volume_id}/metadata
- """
- # ext_mgr.get_resources():获取ResourceExtension对象列表;
- for resource in ext_mgr.get_resources():
- LOG.debug(_('Extended resource: %s'), resource.collection)
- wsgi_resource = wsgi.Resource(resource.controller)
- self.resources[resource.collection] = wsgi_resource
- kargs = dict(
- controller=wsgi_resource,
- collection=resource.collection_actions,
- member=resource.member_actions)
-
- if resource.parent:
- kargs['parent_resource'] = resource.parent
- mapper.resource(resource.collection, resource.collection, **kargs)
- if resource.custom_routes_fn:
- resource.custom_routes_fn(mapper, wsgi_resource)
复制代码
注:需要说明的是在/cinder/api/contrib/目录下的文件都是用来实现功能扩展的,这里主要分为两部分:1.在一个控制器中单纯地实现新的Restful资源功能;2.在一个控制器中即可实现新的Restful资源功能又可对已有的Restful资源功能实现扩展。
方法_setup_ext_routes中针对的是上述第一类,也就是在一个控制器中单纯地实现新的Restful资源功能。这个方法主要实现了两部分的功能,即得到alias和self.extensions[alias]一一对应的关系,以及获取新定义Restful资源功能的URL和具体功能方法的映射关系。
首先来看方法中的语句:
for resource in ext_mgr.get_resources()
wsgi_resource = wsgi.Resource(resource.controller)
来看输出示例:
- resource.controller = <cinder.api.extensions.ExtensionsResource object at 0x3579bd0>
- resource.controller = <cinder.api.contrib.hosts.HostController object at 0x3579cd0>
- resource.controller = <cinder.api.contrib.quotas.QuotaSetsController object at 0x3579d90>
- resource.controller = <cinder.api.contrib.volume_encryption_metadata.VolumeEncryptionMetadataController object at 0x3579e10>
- resource.controller = <cinder.api.contrib.backups.BackupsController object at 0x3579ed0>
- resource.controller = <cinder.api.contrib.volume_type_encryption.VolumeTypeEncryptionController object at 0x35cf050>
- resource.controller = <cinder.api.contrib.availability_zones.Controller object at 0x35cf450>
- resource.controller = <cinder.api.contrib.types_extra_specs.VolumeTypeExtraSpecsController object at 0x35cf490>
- resource.controller = <cinder.api.contrib.qos_specs_manage.QoSSpecsController object at 0x35cf550>
- resource.controller = <cinder.api.contrib.quota_classes.QuotaClassSetsController object at 0x35cf5d0>
- resource.controller = <cinder.api.contrib.volume_transfer.VolumeTransferController object at 0x35cf890>
- resource.controller = <cinder.api.contrib.services.ServiceController object at 0x35cf710>
复制代码
我们看到这里除了cinder.api.extensions.ExtensionsResource,一共实现了11个扩展类的变量controller的值,应该是在这22个扩展功能的实现类中,其中的11个中实现了方法get_resources。我们继续来看方法get_resources的具体实现:
- def get_resources(self):
- """
- Returns a list of ResourceExtension objects.
- 获取ResourceExtension对象列表;
- """
- resources = []
- resources.append(ResourceExtension('extensions',ExtensionsResource(self)))
- for ext in self.extensions.values():
- try:
- resources.extend(ext.get_resources())
-
- except AttributeError:
- pass
- return resources
复制代码
我们首先来看输出示例:
self.extensions = {
'OS-SCH-HNT': ,
'os-hosts': ,
'os-vol-tenant-attr': ,
'os-quota-sets': ,
'os-types-manage': ,
'os-volume-encryption-metadata': ,
'os-snapshot-actions': ,
'backups': ,
'os-volume-actions': ,
'os-vol-host-attr': ,
'encryption': ,
'os-availability-zone': ,
'os-types-extra-specs': ,
'os-vol-mig-status-attr': ,
'os-image-create': ,
'os-extended-snapshot-attributes': ,
'qos-specs': ,
'os-quota-class-sets': ,
'os-volume-transfer': ,
'os-vol-image-meta': ,
'os-admin-actions': ,
'os-services': }
我们可以看到,这里实现了22个alias和具体实现类的对应字典,即是上篇博客中分析的语句ext_mgr = self.ExtensionManager()所实现的扩展功能目录下所有功能alias和具体实现类的对应。
通过一一到具体类中的验证,我们可以发现其中10个类只实现了方法get_resources,10个类只实现了方法get_controller_extensions,而1个类中即实现了方法get_resources也实现了方法get_controller_extensions。还有一个类中两个方法都没由直接实现;
输出示例(分类):
只实现了方法get_resources:
- ext = <cinder.api.contrib.hosts.Hosts object at 0x18b0b50>
- ext = <cinder.api.contrib.quotas.Quotas object at 0x1908250>
- ext = <cinder.api.contrib.volume_encryption_metadata.Volume_encryption_metadata object at 0x18b0750>
- ext = <cinder.api.contrib.backups.Backups object at 0x226f810>
- ext = <cinder.api.contrib.availability_zones.Availability_zones object at 0x226f290>
- ext = <cinder.api.contrib.types_extra_specs.Types_extra_specs object at 0x18f91d0>
- ext = <cinder.api.contrib.qos_specs_manage.Qos_specs_manage object at 0x236a490>
- ext = <cinder.api.contrib.quota_classes.Quota_classes object at 0x18b0a50>
- ext = <cinder.api.contrib.volume_transfer.Volume_transfer object at 0x2282cd0>
- ext = <cinder.api.contrib.services.Services object at 0x18f9c90>
复制代码
只实现了方法get_controller_extensions:
- ext = <cinder.api.contrib.volume_image_metadata.Volume_image_metadata object at 0x236ae90>
- ext = <cinder.api.contrib.admin_actions.Admin_actions object at 0x2282910>
- ext = <cinder.api.contrib.volume_mig_status_attribute.Volume_mig_status_attribute object at 0x18f9710>
- ext = <cinder.api.contrib.volume_actions.Volume_actions object at 0x226f910>
- ext = <cinder.api.contrib.snapshot_actions.Snapshot_actions object at 0x18b0510>
- ext = <cinder.api.contrib.types_manage.Types_manage object at 0x2277c10>
- ext = <cinder.api.contrib.volume_tenant_attribute.Volume_tenant_attribute object at 0x236aa90>
- ext = <cinder.api.contrib.scheduler_hints.Scheduler_hints object at 0x18f9a10>
- ext = <cinder.api.contrib.volume_host_attribute.Volume_host_attribute object at 0x1908050>
- ext = <cinder.api.contrib.extended_snapshot_attributes.Extended_snapshot_attributes object at 0x2282090>
复制代码
即实现了方法get_resources也实现了方法get_controller_extensions:
- ext = <cinder.api.contrib.volume_type_encryption.Volume_type_encryption object at 0x18b01d0>
复制代码
两个方法都没由直接实现:
- ext = <cinder.api.contrib.image_create.Image_create object at 0x18b05d0>
复制代码
经上分析,返回了11个类ResourceExtension的初始化对象;
来看方法get_resources中的语句:resources.extend(ext.get_resources()),这里的方法get_resources()调用了具体类中的get_resources()方法,而类中没有实现get_resources()方法的,在其父类class ExtensionDescriptor(object)中有实现,我们来看具体的类中get_resources的实现,我简单进行了一个归纳:
直接实现了方法get_resources的类(看几个例子,看一下实现过程):
- ext = <cinder.api.contrib.backups.Backups object at 0x226f810>:
- class Backups(extensions.ExtensionDescriptor):
- """Backups support."""
-
- name = 'Backups'
- alias = 'backups'
- namespace = 'http://docs.openstack.org/volume/ext/backups/api/v1'
- updated = '2012-12-12T00:00:00+00:00'
-
- def get_resources(self):
- resources = []
- res = extensions.ResourceExtension(
- Backups.alias,
- BackupsController(),
- collection_actions={'detail': 'GET'},
- member_actions={'restore': 'POST'})
- resources.append(res)
- return resources
-
- class BackupsController(wsgi.Controller):
- """
- The Backups API controller for the OpenStack API.
- OpenStack的备份操作API控制器;
- """
-
- _view_builder_class = backup_views.ViewBuilder
-
- def __init__(self):
- self.backup_api = backupAPI.API()
- super(BackupsController, self).__init__()
-
- class Controller(object):
- """Default controller."""
-
- __metaclass__ = ControllerMetaclass
-
- _view_builder_class = None
-
- def __init__(self, view_builder=None):
- """Initialize controller with a view builder instance."""
- if view_builder:
- self._view_builder = view_builder
- elif self._view_builder_class:
- self._view_builder = self._view_builder_class()
- else:
- self._view_builder = None
- ==========================================================
- ext = <cinder.api.contrib.hosts.Hosts object at 0x18b0b50>:
- class Hosts(extensions.ExtensionDescriptor):
- """Admin-only host administration"""
-
- name = "Hosts"
- alias = "os-hosts"
- namespace = "http://docs.openstack.org/volume/ext/hosts/api/v1.1"
- updated = "2011-06-29T00:00:00+00:00"
-
- def get_resources(self):
- resources = [extensions.ResourceExtension('os-hosts',
- HostController(),
- collection_actions={'update': 'PUT'},
- member_actions={
- 'startup': 'GET',
- 'shutdown': 'GET',
- 'reboot': 'GET'})]
- return resources
-
- class HostController(object):
- """
- The Hosts API controller for the OpenStack API.
- 主机控制API;
- """
- def __init__(self):
- self.api = volume_api.HostAPI()
- super(HostController, self).__init__()
- ==========================================================
- ext = <cinder.api.contrib.quotas.Quotas object at 0x1908250>:
- class Quotas(extensions.ExtensionDescriptor):
- """Quotas management support"""
-
- name = "Quotas"
- alias = "os-quota-sets"
- namespace = "http://docs.openstack.org/volume/ext/quotas-sets/api/v1.1"
- updated = "2011-08-08T00:00:00+00:00"
-
- def get_resources(self):
- resources = []
-
- res = extensions.ResourceExtension('os-quota-sets',
- QuotaSetsController(),
- member_actions={'defaults': 'GET'})
- resources.append(res)
-
- return resources
-
- class QuotaSetsController(object)
- ==========================================================
- ext = <cinder.api.contrib.volume_encryption_metadata.Volume_encryption_metadata object at 0x18b0750>:
- class Volume_encryption_metadata(extensions.ExtensionDescriptor):
- """Volume encryption metadata retrieval support."""
-
- name = "VolumeEncryptionMetadata"
- alias = "os-volume-encryption-metadata"
- namespace = ("http://docs.openstack.org/volume/ext/"
- "os-volume-encryption-metadata/api/v1")
- updated = "2013-07-10T00:00:00+00:00"
-
- def get_resources(self):
- resources = []
- res = extensions.ResourceExtension('encryption',
- VolumeEncryptionMetadataController(),
- parent=dict(member_name='volume', collection_name='volumes'))
- resources.append(res)
- return resources
-
- class VolumeEncryptionMetadataController(wsgi.Controller):
- """
- The volume encryption metadata API extension
- 卷加密元数据控制API类;
- """
-
- class Controller(object):
- """Default controller."""
-
- __metaclass__ = ControllerMetaclass
-
- _view_builder_class = None
-
- def __init__(self, view_builder=None):
- """Initialize controller with a view builder instance."""
- if view_builder:
- self._view_builder = view_builder
- elif self._view_builder_class:
- self._view_builder = self._view_builder_class()
- else:
- self._view_builder = None
- ==========================================================
复制代码
没有实现get_resources()方法的类,在其父类class ExtensionDescriptor(object)中有实现:
- def get_resources(self):
- """
- List of extensions.ResourceExtension extension objects.
- Resources define new nouns, and are accessible through URLs.
- """
- resources = []
- return resources
复制代码
可见没有做什么具体的工作;
从分析中可以看到,类中直接实现了get_resources()的部分,都进行了类class Resource(wsgi.Application)的初始化工作,简单来看类class Resource(wsgi.Application)的初始化方法:
- class Resource(wsgi.Application):
- def __init__(self, controller, action_peek=None, **deserializers):
- """
- :param controller: object that implement methods created by routes lib
- :param action_peek: dictionary of routines for peeking into an action request body to determine the desired action
- """
- self.controller = controller
- # 获取和更新默认的反序列化方法;
- default_deserializers = dict(xml=XMLDeserializer, json=JSONDeserializer)
- default_deserializers.update(deserializers)
- self.default_deserializers = default_deserializers
- # 获取默认的序列化方法;
- self.default_serializers = dict(xml=XMLDictSerializer, json=JSONDictSerializer)
- # 获取和确认所要引用的动作;
- # action_peek_xml:通过解析xml字符串,实现确定所要引用的动作;
- # action_peek_json:通过反序列化操作,实现确定所要引用的动作;
- self.action_peek = dict(xml=action_peek_xml, json=action_peek_json)
- self.action_peek.update(action_peek or {})
- # Copy over the actions dictionary
- self.wsgi_actions = {}
- if controller:
- self.register_actions(controller)
- # Save a mapping of extensions
- self.wsgi_extensions = {}
- self.wsgi_action_extensions = {}
复制代码
其中的语句:self.register_actions(controller)实现的功能就是把self.resources和wsgi_resource一一对应起来。
方法get_resources(self)先分析到这里,我们回到方法_setup_ext_routes:
- def _setup_ext_routes(self, mapper, ext_mgr):
- """
- mapper =
- Route name Methods Path
- versions /
- ...... ...... ......
- formatted_volume_edit_volume_metadata GET /{project_id}/volumes/:volume_id/metadata/:(id)/edit.:(format)
- volume_edit_volume_metadata GET /{project_id}/volumes/:volume_id/metadata/:(id)/edit
- formatted_volume_volume_metadata GET /{project_id}/volumes/:volume_id/metadata/:(id).:(format)
- volume_volume_metadata GET /{project_id}/volumes/:volume_id/metadata/:(id)
- metadata PUT /{project_id}/volumes/{volume_id}/metadata
- """
- # ext_mgr.get_resources():获取ResourceExtension对象列表;
- for resource in ext_mgr.get_resources():
- LOG.debug(_('Extended resource: %s'), resource.collection)
- wsgi_resource = wsgi.Resource(resource.controller)
- self.resources[resource.collection] = wsgi_resource
- kargs = dict(
- controller=wsgi_resource,
- collection=resource.collection_actions,
- member=resource.member_actions)
-
- if resource.parent:
- kargs['parent_resource'] = resource.parent
- mapper.resource(resource.collection, resource.collection, **kargs)
- if resource.custom_routes_fn:
- resource.custom_routes_fn(mapper, wsgi_resource)
复制代码
再来看语句:
kargs = dict(controller=wsgi_resource,
collection=resource.collection_actions,
member=resource.member_actions)
if resource.parent:
kargs['parent_resource'] = resource.parent
这里实现的功能就是获取各个类中的collection_actions和member_actions,分别赋值给collection和member,实现格式的统一,为后续的调用做准备;
再来看语句:
mapper.resource(resource.collection, resource.collection, **kargs)
实现的功能就是获取新定义Restful资源功能的URL和具体功能方法的映射关系。
输出示例:
复制代码
至此方法def _setup_ext_routes(self, mapper, ext_mgr)的实现分析完成。
相关文章
OpenStack Cinder服务启动过程中的资源加载和扩展源码解析之一
http://www.aboutyun.com/thread-10222-1-1.html
OpenStack Cinder服务启动过程中的资源加载和扩展源码解析之三
http://www.aboutyun.com/thread-10224-1-1.html
原文链接:http://blog.csdn.net/gaoxingnengjisuan/article/details/21752277
|