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

导读

  • APIRouter类实现

上一篇“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功能的扩展和加载就搞定了。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,585评论 18 139
  • 导读: 启动机制 Entry point 和Eventlet的交互 server的启动过程源代码分析 wsgi a...
    分享放大价值阅读 2,774评论 0 3
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,560评论 18 399
  • 我们常在叹息 生活一潭死水生命黯淡无光 我们常在埋怨 才华随时间而逝机遇从不垂青自己 把头埋在沙里 看到的都是灰暗...
    江城曼舞阅读 248评论 0 2
  • 第三个创业公司失败,薪资已经三月有余未能发放,心情如同外面一样天气一样,烦躁。 所以想畅谈下这四年来在创业公司的心...
    小666666阅读 182评论 0 0