Horizon 源码阅读(二)—— Horizon 模块注册机制

一、写在前面

这篇文章主要介绍一下Openstack Horizon — juno项目模块注册机制,本文将通过对Horizon源码解析了解各个模块注册加载机制。全文穿插了Horizon组建的代码块以及个人理解注释,由于能力和时间有限,错误之处在所难免,欢迎指正!

       如果转载,请保留作者信息。
       邮箱地址:[email protected]


二、Horizon模块注册机制

       Horizon/base.py中实现了一套dashboard/panel注册、动态加载机制,使得Horizon面板上所有的dashboard都是”可插拔”的,所有的panel都是”动态加载”的,在以下的内容里将通过源码解析具体分析horizon/base.py文件,揭开这神秘的面纱。

       流程图: 

       

       整个Horizon模块的加载流程如上图所示,horizon项目在引入的时候自动通过horizon.__init__()自动Load类属性方法def_lazy_urls(self),加载LazyURLPattern(url_patterns)其中url_patterns是一个嵌套方法,LazyURLPattern继承自Django SimpleLazyObject类,个人理解这是把_lazy_urls()方法转换成一个懒惰方法,这里只加载不执行,等正真用到的时候在执行。

       当用户通过Request请求访问的时候,根据Django Urls映射机制,会去openstack_dashboard.urls.py匹配,urls.py文件中url(r’', include(horizon.urls)),触发执行_lazy_urls()方法。_lazy_urls()方法返回def_urls(self)处理结果的第一个参数urlpatterns,整个Horizon模块的注册Urls编译都是在这个方法内完成,通过_autodiscover()方法,从“settings.INSTALLED_APPS发现模块,包含dashboard.py文件的模块进行注册,并添加到self._registry注册表中,然后通过循环遍历注册表,调用每个注册dashboard的_autodiscover()方法,注册每个dashboard下面的panel,完成整个horizon模块的注册,最终返回一个urlpatterns值,urls匹配调用相应的views模块。

       

 注意点:

          1、settings.INSTALLED_APPS在这里拉出来讲解一下,settings.INSTALLED_APPS是一个字符串tuple ,内容是项目中引入的应用,在Horizon项目中有两部分组成:

第一部分:settings.py

第二部分:settings.py

openstack_dashboard.enabled/openstack_dashboard.local.enabled:配置启用和显示Daishboard,用来配置Horizon左侧导航显示的dashboard。自己开发一个dashboard需要在openstack_dashboard/enabled 添加一个类似 _50_mydashboard.py文件,这样才会被注入到settings.INSTALLED_APPS配置项中。整个settings.INSTALLED_APPS中引入的APP由这两部分组拼在一起。

2、每个dashboard模块下都有一个dasbboard.py文件里面定义了属于当前dashboard的PanelGroup,和各个PanelGroup下的Panel,在Horizon模块被导入的时候会去依次遍历Dasboard→PanelGroup→Panel,所有的dashboard注册到Horizon命名空间下,各个panel注册到自己的dashboard命名空间下。

三、Horizon模块注册源码解析

       接下去刚通过分析Juno 中Horizon关于这部分的原码来讲解。

       细粒度的数据流图: 

       Horizon 源码阅读(二)—— Horizon 模块注册机制_第1张图片

       上图是关于Horizon中关于模块注册的数据流图。


1)horizon导入

      settings.py-> 导入horizon

      INSTALLED_APPS = [
                                       ‘horizon',

                                        ……
       ]

python中在导入一个包时,实际上导入了它的__init__.py文件,当我们导入Horizon这个包的时候,__init__.py文件自动运行,在__init__.py 文件中再导入其他的包,或者模块。其中在horizon包的__init__.py文件中:

    from horizon.baseimport Horizon  # noqa

    ……
    urls = Horizon._lazy_urls

    ……


导入了Horizon.base._lazy_urls方法,_lazy_urls()是完成整个模块注册的入口,Horizon.base._lazy_urls方法增加了@property, @property 可以将python定义的函数“当做”属性访问。__init__.py将Horizon.base._lazy_urls导入的时候自动执行该方法体。


注:horizon提供的Site类、Dashboard类、Panel类,负责整个基本架构,实现单例的设计模式,全局只有一个只有一个horizon对象。 对于这个文件代码架构的分析放到以后。

       

其中LazyURLPattern(url_patterns)没有继续执行下去,LazyURLPattern()继承自Djano SimpleLazyObject理解成将一个方法转换成延迟执行的方法,只有正真调用的时候才会正真执行,显然这里没有正真调用,这里只是一个加载,url_patterns作为一个方法引用当作参数。

     

2)ruquest请求

      当用户通过浏览器发起request请求,根据Django的框架结构,使用URLconf进行连接请求和后端处理(view)的绑定,使用view进行后端处理,使用template进行页面渲染。

      

     

       openstack_dashboard.urls.py:

       url(r'', include(horizon.urls)): horizon.urls对应的是horizon.baise._lazy_urls(),执行之前导入horizon包加载_lazy_urls()方法中的

            def url_patterns():
                 
return self._urls()[0]


接着调用 horizon.base.Site._urls(),完成所有Dashboard和Panel的注册变编译URLconf:


标记(1)从“settings.INSTALLED_APPS发现模块,包含dashboard.py、panel.py的模块注册,添加到注册表中self._registry,没有的抛出异常。

                horizon.Site._autodiscover():

               

标记(2)发现每个Dashboards里的Panels,从注册表self._registry 取出注册dashboard,注册每个dashboard中的panel

                horizon.Dashboard_autodiscover():

               

你可能感兴趣的:(openstack,horizon)