虚拟化技术openstackOpenStack

Neutron-server的启动流程和工作方式(二)

2017-05-02  本文已影响59人  分享放大价值

导读

上一篇“Neutron-server的启动流程和工作方式(一)”里提到APIRouter类实现了app功能的扩展和加载过程,本文进一步展开分析。

APIRouter类

 69 class APIRouter(base_wsgi.Router):
 70      
 71     @classmethod 
 72     def factory(cls, global_config, **local_config):
 73         return cls(**local_config) 
 74    
 75     def __init__(self, **local_config):
 76         mapper = routes_mapper.Mapper() 
 77         manager.init()  
 78         plugin = directory.get_plugin() 
            #(1)生成一个PluginAwareExtensionManager实例
 79         ext_mgr = extensions.PluginAwareExtensionManager.get_instance() 
 80         ext_mgr.extend_resources("2.0", attributes.RESOURCE_ATTRIBUTE_MAP)   
 81                                                                
 82         col_kwargs = dict(collection_actions=COLLECTION_ACTIONS,  
 83                           member_actions=MEMBER_ACTIONS)     
 84         #(2)建立resource到URL的映射关系                                               
 85         def _map_resource(collection, resource, params, parent=None): 
 86             allow_bulk = cfg.CONF.allow_bulk
                #(3) 创建resource
 87             controller = base.create_resource(
 88                 collection, resource, plugin, params, allow_bulk=allow_bulk, 
 89                 parent=parent, allow_pagination=True,   
 90                 allow_sorting=True)
 91             path_prefix = None
 92             if parent:
 93                 path_prefix = "/%s/{%s_id}/%s" % (parent['collection_name'],
 94                                                   parent['member_name'],
 95                                                   collection)
                #根据之前创建的Controller、REQUIREMENTS和path_prefix建立字典
 96             mapper_kwargs = dict(controller=controller, 
 97                                  requirements=REQUIREMENTS,
 98                                  path_prefix=path_prefix,
 99                                  **col_kwargs)
                #最后根据字典,建立neutron api的顶级资源集合体
100             return mapper.collection(collection, resource,
101                                      **mapper_kwargs)
102 
103         mapper.connect('index', '/', controller=Index(RESOURCES))
104         for resource in RESOURCES:
105             _map_resource(RESOURCES[resource], resource,
106                           attributes.RESOURCE_ATTRIBUTE_MAP.get(
107                               RESOURCES[resource], dict()))
108             resource_registry.register_resource_by_name(resource)
109 
110         for resource in SUB_RESOURCES:
111             _map_resource(SUB_RESOURCES[resource]['collection_name'], resource,
112                           attributes.RESOURCE_ATTRIBUTE_MAP.get(
113                               SUB_RESOURCES[resource]['collection_name'],
114                               dict()),
115                           SUB_RESOURCES[resource]['parent'])
116 
117         # Certain policy checks require that the extensions are loaded
118         # and the RESOURCE_ATTRIBUTE_MAP populated before they can be
119         # properly initialized. This can only be claimed with certainty
120         # once this point in the code has been reached. In the event
121         # that the policies have been initialized before this point,
122         # calling reset will cause the next policy check to
123         # re-initialize with all of the required data in place.
124         policy.reset()
125         super(APIRouter, self).__init__(mapper) 

上面的代码中比较重要就是(1)和(2)两部分。先来看下(1)的实现,首先生成PluginAwareExtensionManager类,再调用get_instance()方法获取ext_mgr实例:

486 class PluginAwareExtensionManager(ExtensionManager):
487 
488     _instance = None
489 
490     def __init__(self, path, plugins):
491         self.plugins = plugins
            #调用父类ExtensionManager的构造函数
492         super(PluginAwareExtensionManager, self).__init__(path)
493         self.check_if_plugin_extensions_loaded()
305 class ExtensionManager(object):
306     """Load extensions from the configured extension path.
307 
308     See tests/unit/extensions/foxinsocks.py for an
309     example extension implementation.
310     """
311 
312     def __init__(self, path):
313         LOG.info(_LI('Initializing extension manager.'))
314         self.path = path
315         self.extensions = {}
316         self._load_all_extensions()

430     def _load_all_extensions(self):
431         """Load extensions from the configured path.
432 
433         The extension name is constructed from the module_name. If your
434         extension module is named widgets.py, the extension class within that
435         module should be 'Widgets'.
436 
437         See tests/unit/extensions/foxinsocks.py for an example extension
438         implementation.
439         """
440 
441         for path in self.path.split(':'):
442             if os.path.exists(path):
443                 self._load_all_extensions_from_path(path)
444             else:
445                 LOG.error(_LE("Extension path '%s' doesn't exist!"), path)

447     def _load_all_extensions_from_path(self, path):
448         # Sorting the extension list makes the order in which they
449         # are loaded predictable across a cluster of load-balanced
450         # Neutron Servers
451         for f in sorted(os.listdir(path)):
452             try:
453                 LOG.debug('Loading extension file: %s', f)
454                 mod_name, file_ext = os.path.splitext(os.path.split(f)[-1])
455                 ext_path = os.path.join(path, f)
456                 if file_ext.lower() == '.py' and not mod_name.startswith('_'):
457                     mod = imp.load_source(mod_name, ext_path)
458                     ext_name = mod_name[0].upper() + mod_name[1:]
459                     new_ext_class = getattr(mod, ext_name, None)
460                     if not new_ext_class:
461                         LOG.warning(_LW('Did not find expected name '
462                                         '"%(ext_name)s" in %(file)s'),
463                                     {'ext_name': ext_name,
464                                      'file': ext_path})
465                         continue
                        #根据path下的文件名,生成extension,并调用add_extension加入到self.extensions[]中
466                     new_ext = new_ext_class()
467                     self.add_extension(new_ext)
468             except Exception as exception:
469                 LOG.warning(_LW("Extension file %(f)s wasn't loaded due to "
470                                 "%(exception)s"),
471                             {'f': f, 'exception': exception})

上述代码主要是将配置的extension路径下的所有"*.py"的文件进行排序后分别加载,获取文件名为extension的名称,其中加载的模块包括external_net,dns,dvr等等。
回到(1),类初始化完成后,就调用get_instance():

530     def get_instance(cls):                                                                          
531         if cls._instance is None:
532             service_plugins = directory.get_plugins()
533             cls._instance = cls(get_extensions_path(service_plugins),
534                                 service_plugins)
535         return cls._instance

这个函数中,获取路径下所有文件的path和服务的插件,并构建cls返回。

再来看(2),这个是内置函数,在下面被遍历调用.这个函数中比较重要的是(3):

 # create_resource中主要是根据资源信息建立Controller,这个Controller就是用以之后api请求到来之后真正去处理这些请求
            #这个Controller是在neutron.api.v2.base中
            #之后wsgi_resource.Resource中根据collection、resource以及对应的RESOURCE_ATTRIBUTE_MAP的信息
            #创建一个xml和json的序列化和反序列化的对象
            #序列化指:对xml或json语句进行解析,确定要引用的动作
            #反序列化指:进行xml或json的封装
750 def create_resource(collection, resource, plugin, params, allow_bulk=False,
751                     member_actions=None, parent=None, allow_pagination=False,
752                     allow_sorting=False):
753     controller = Controller(plugin, collection, resource, params, allow_bulk,
754                             member_actions=member_actions, parent=parent,
755                             allow_pagination=allow_pagination,
756                             allow_sorting=allow_sorting)
757 
758     return wsgi_resource.Resource(controller, FAULT_MAP)

通过(3)创建的controller,就是著名的MVC模式中C,就是用来干脏活累活的主体了。_map_resource函数就是用来实现对资源的映射,具体可以理解为,得到了URL,通过这里的映射关系,匹配定位到具体要调用的方法上。
至此,app功能的扩展和加载就搞定了。

上一篇 下一篇

猜你喜欢

热点阅读