Neutron-server的啟動(dòng)流程和工作方式(二)

導(dǎo)讀

  • APIRouter類(lèi)實(shí)現(xiàn)

上一篇“Neutron-server的啟動(dòng)流程和工作方式(一)”里提到APIRouter類(lèi)實(shí)現(xiàn)了app功能的擴(kuò)展和加載過(guò)程休涤,本文進(jìn)一步展開(kāi)分析。

APIRouter類(lèi)

 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)生成一個(gè)PluginAwareExtensionManager實(shí)例
 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的映射關(guān)系                                               
 85         def _map_resource(collection, resource, params, parent=None): 
 86             allow_bulk = cfg.CONF.allow_bulk
                #(3) 創(chuàng)建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)
                #根據(jù)之前創(chuàng)建的Controller但绕、REQUIREMENTS和path_prefix建立字典
 96             mapper_kwargs = dict(controller=controller, 
 97                                  requirements=REQUIREMENTS,
 98                                  path_prefix=path_prefix,
 99                                  **col_kwargs)
                #最后根據(jù)字典,建立neutron api的頂級(jí)資源集合體
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)兩部分。先來(lái)看下(1)的實(shí)現(xiàn),首先生成PluginAwareExtensionManager類(lèi),再調(diào)用get_instance()方法獲取ext_mgr實(shí)例:

486 class PluginAwareExtensionManager(ExtensionManager):
487 
488     _instance = None
489 
490     def __init__(self, path, plugins):
491         self.plugins = plugins
            #調(diào)用父類(lèi)ExtensionManager的構(gòu)造函數(shù)
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
                        #根據(jù)path下的文件名脂男,生成extension,并調(diào)用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"的文件進(jìn)行排序后分別加載种呐,獲取文件名為extension的名稱(chēng)宰翅,其中加載的模塊包括external_net,dns,dvr等等。
回到(1),類(lèi)初始化完成后爽室,就調(diào)用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

這個(gè)函數(shù)中堕油,獲取路徑下所有文件的path和服務(wù)的插件,并構(gòu)建cls返回肮之。

再來(lái)看(2),這個(gè)是內(nèi)置函數(shù)掉缺,在下面被遍歷調(diào)用.這個(gè)函數(shù)中比較重要的是(3):

 # create_resource中主要是根據(jù)資源信息建立Controller,這個(gè)Controller就是用以之后api請(qǐng)求到來(lái)之后真正去處理這些請(qǐng)求
            #這個(gè)Controller是在neutron.api.v2.base中
            #之后wsgi_resource.Resource中根據(jù)collection戈擒、resource以及對(duì)應(yīng)的RESOURCE_ATTRIBUTE_MAP的信息
            #創(chuàng)建一個(gè)xml和json的序列化和反序列化的對(duì)象
            #序列化指:對(duì)xml或json語(yǔ)句進(jìn)行解析眶明,確定要引用的動(dòng)作
            #反序列化指:進(jìn)行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)

通過(guò)(3)創(chuàng)建的controller,就是著名的MVC模式中C筐高,就是用來(lái)干臟活累活的主體了搜囱。_map_resource函數(shù)就是用來(lái)實(shí)現(xiàn)對(duì)資源的映射,具體可以理解為柑土,得到了URL蜀肘,通過(guò)這里的映射關(guān)系,匹配定位到具體要調(diào)用的方法上稽屏。
至此扮宠,app功能的擴(kuò)展和加載就搞定了。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末狐榔,一起剝皮案震驚了整個(gè)濱河市坛增,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌薄腻,老刑警劉巖收捣,帶你破解...
    沈念sama閱讀 206,482評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異庵楷,居然都是意外死亡罢艾,警方通過(guò)查閱死者的電腦和手機(jī)楣颠,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,377評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)咐蚯,“玉大人童漩,你說(shuō)我怎么就攤上這事〔智” “怎么了睁冬?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,762評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵挎春,是天一觀的道長(zhǎng)看疙。 經(jīng)常有香客問(wèn)我,道長(zhǎng)直奋,這世上最難降的妖魔是什么能庆? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,273評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮脚线,結(jié)果婚禮上搁胆,老公的妹妹穿的比我還像新娘。我一直安慰自己邮绿,他們只是感情好渠旁,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,289評(píng)論 5 373
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著船逮,像睡著了一般顾腊。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上挖胃,一...
    開(kāi)封第一講書(shū)人閱讀 49,046評(píng)論 1 285
  • 那天杂靶,我揣著相機(jī)與錄音,去河邊找鬼酱鸭。 笑死吗垮,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的凹髓。 我是一名探鬼主播烁登,決...
    沈念sama閱讀 38,351評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼蔚舀!你這毒婦竟也來(lái)了防泵?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 36,988評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤蝗敢,失蹤者是張志新(化名)和其女友劉穎捷泞,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體寿谴,經(jīng)...
    沈念sama閱讀 43,476評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡锁右,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,948評(píng)論 2 324
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片咏瑟。...
    茶點(diǎn)故事閱讀 38,064評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡拂到,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出码泞,到底是詐尸還是另有隱情兄旬,我是刑警寧澤,帶...
    沈念sama閱讀 33,712評(píng)論 4 323
  • 正文 年R本政府宣布余寥,位于F島的核電站领铐,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏宋舷。R本人自食惡果不足惜绪撵,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,261評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望祝蝠。 院中可真熱鬧音诈,春花似錦、人聲如沸绎狭。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,264評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)儡嘶。三九已至喇聊,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間社付,已是汗流浹背承疲。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,486評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留鸥咖,地道東北人燕鸽。 一個(gè)月前我還...
    沈念sama閱讀 45,511評(píng)論 2 354
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像啼辣,于是被迫代替她去往敵國(guó)和親啊研。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,802評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理鸥拧,服務(wù)發(fā)現(xiàn)党远,斷路器,智...
    卡卡羅2017閱讀 134,599評(píng)論 18 139
  • 導(dǎo)讀: 啟動(dòng)機(jī)制 Entry point 和Eventlet的交互 server的啟動(dòng)過(guò)程源代碼分析 wsgi a...
    分享放大價(jià)值閱讀 2,781評(píng)論 0 3
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語(yǔ)法富弦,類(lèi)相關(guān)的語(yǔ)法沟娱,內(nèi)部類(lèi)的語(yǔ)法,繼承相關(guān)的語(yǔ)法腕柜,異常的語(yǔ)法济似,線程的語(yǔ)...
    子非魚(yú)_t_閱讀 31,581評(píng)論 18 399
  • 我們常在嘆息 生活一潭死水生命黯淡無(wú)光 我們常在埋怨 才華隨時(shí)間而逝機(jī)遇從不垂青自己 把頭埋在沙里 看到的都是灰暗...
    江城曼舞閱讀 248評(píng)論 0 2
  • 第三個(gè)創(chuàng)業(yè)公司失敗矫废,薪資已經(jīng)三月有余未能發(fā)放,心情如同外面一樣天氣一樣砰蠢,煩躁蓖扑。 所以想暢談下這四年來(lái)在創(chuàng)業(yè)公司的心...
    小666666閱讀 182評(píng)論 0 0