Horizon学习笔记

Horizon吊炸天!之前,一直认为horizon只不过是一个面板,没啥好研究的,而且我对django又不是很熟,一直懒的看horizon,今晚硬着头皮看了下去,没想到,越看越有劲,眼睛差点跟不上我的思路了!我觉得horizon牛不在对django的运用,而是对事物高度的抽象能力:D


程序的入口点在horizon/openstack_dashboard/urls.py中:

url(r'', include(horizon.urls))


然后由Horizon这个单例的Site对象,开始加载urls,自动发现并注册dashboard,然后对每一个dashboard,再自动发现并注册panel:

Horizon._lazy_url

程序的入口看起来那么平常不过,进入之后发现这大千世界,让人惊叹不已!!!




可以在horizon/base/_urls()方法中,一窥全貌:

```
    def _urls(self):  
        """Constructs the URLconf for Horizon from registered Dashboards."""
        urlpatterns = self._get_default_urlpatterns()
        self._autodiscover() # 自动发现并注册dashboard,其实就是从INSTALL_APPS中加载dashboard
        
        # Discover each dashboard's panels.
        for dash in self._registry.values():
            dash._autodiscover()  # 自动发现并注册panel,这个是根据路径来发现的
            
        # Allow for override modules
        if self._conf.get("customization_module", None):
            customization_module = self._conf["customization_module"]
            bits = customization_module.split('.')
            mod_name = bits.pop()
            package = '.'.join(bits)
            mod = import_module(package)
            try: 
                before_import_registry = copy.copy(self._registry)
                import_module('%s.%s' % (package, mod_name))
            except Exception:
                self._registry = before_import_registry
                if module_has_submodule(mod, mod_name):
                    raise
                 
        # Compile the dynamic urlconf.
        for dash in self._registry.values():
            urlpatterns += patterns('',
                    url(r'^%s/' % dash.slug, include(dash._decorated_urls)))
                    
        # Return the three arguments to django.conf.urls.defaults.include
        return urlpatterns, self.namespace, self.slug
```

默认的,一个HorizonSite中有三个Dashboard: project, admin, setting,在HorizonSite的autodiscover过程中,注册在HorizonSite中:
```
(Pdb) pp self._registry
{<class 'openstack_dashboard.dashboards.project.dashboard.Project'>: <Dashboard: project>,
 <class 'openstack_dashboard.dashboards.admin.dashboard.Admin'>: <Dashboard: admin>,
 <class 'openstack_dashboard.dashboards.settings.dashboard.Settings'>: <Dashboard: settings>}
```

然后再对每一个Dashboard进行autodiscover,将Panel注册在Dashboard中,从上面的类图中可以看到Dashboard和HorizonSite都是Registry的子类,它们都具有**注册**的能力:
```
(Pdb) pp self._registry.values()[0]._registry
{<class 'openstack_dashboard.dashboards.project.overview.panel.Overview'>: <Panel: overview>,
 <class 'openstack_dashboard.dashboards.project.containers.panel.Containers'>: <Panel: containers>,
 <class 'openstack_dashboard.dashboards.project.instances.panel.Instances'>: <Panel: instances>,
 <class 'openstack_dashboard.dashboards.project.network_topology.panel.NetworkTopology'>: <Panel: network_topology>,
 <class 'openstack_dashboard.dashboards.project.images_and_snapshots.panel.ImagesAndSnapshots'>: <Panel: images_and_snapshots>,
 <class 'openstack_dashboard.dashboards.project.networks.panel.Networks'>: <Panel: networks>,
 <class 'openstack_dashboard.dashboards.project.access_and_security.panel.AccessAndSecurity'>: <Panel: access_and_security>,
 <class 'openstack_dashboard.dashboards.project.firewalls.panel.Firewall'>: <Panel: firewalls>,
 <class 'openstack_dashboard.dashboards.project.volumes.panel.Volumes'>: <Panel: volumes>,
 <class 'openstack_dashboard.dashboards.project.routers.panel.Routers'>: <Panel: routers>,
 <class 'openstack_dashboard.dashboards.project.loadbalancers.panel.LoadBalancer'>: <Panel: loadbalancers>,
 <class 'openstack_dashboard.dashboards.project.vpn.panel.VPN'>: <Panel: vpn>,
 <class 'openstack_dashboard.dashboards.project.database_backups.panel.Backups'>: <Panel: database_backups>,
 <class 'openstack_dashboard.dashboards.project.stacks.panel.Stacks'>: <Panel: stacks>,
 <class 'openstack_dashboard.dashboards.project.databases.panel.Databases'>: <Panel: databases>}
```

在注册每一个Panel的时候,还会将每一个Panel的template路径,保存到loaders模块中:
```
(Pdb) pp loaders.panel_template_dirs
{'admin/defaults': '/opt/stack/horizon/openstack_dashboard/dashboards/admin/defaults/templates',
 'admin/flavors': '/opt/stack/horizon/openstack_dashboard/dashboards/admin/flavors/templates',
 'admin/hypervisors': '/opt/stack/horizon/openstack_dashboard/dashboards/admin/hypervisors/templates',
 'admin/images': '/opt/stack/horizon/openstack_dashboard/dashboards/admin/images/templates',
 'admin/info': '/opt/stack/horizon/openstack_dashboard/dashboards/admin/info/templates',
 'admin/instances': '/opt/stack/horizon/openstack_dashboard/dashboards/admin/instances/templates',
 'admin/metering': '/opt/stack/horizon/openstack_dashboard/dashboards/admin/metering/templates',
 'admin/networks': '/opt/stack/horizon/openstack_dashboard/dashboards/admin/networks/templates',
 'admin/overview': '/opt/stack/horizon/openstack_dashboard/dashboards/admin/overview/templates',
 'admin/projects': '/opt/stack/horizon/openstack_dashboard/dashboards/admin/projects/templates',
 'admin/routers': '/opt/stack/horizon/openstack_dashboard/dashboards/admin/routers/templates',
 'admin/users': '/opt/stack/horizon/openstack_dashboard/dashboards/admin/users/templates',
 'admin/volumes': '/opt/stack/horizon/openstack_dashboard/dashboards/admin/volumes/templates',
 'project/access_and_security': '/opt/stack/horizon/openstack_dashboard/dashboards/project/access_and_security/templates',
 'project/containers': '/opt/stack/horizon/openstack_dashboard/dashboards/project/containers/templates',
 'project/database_backups': '/opt/stack/horizon/openstack_dashboard/dashboards/project/database_backups/templates',
 'project/databases': '/opt/stack/horizon/openstack_dashboard/dashboards/project/databases/templates',
 'project/firewalls': '/opt/stack/horizon/openstack_dashboard/dashboards/project/firewalls/templates',
 'project/images_and_snapshots': '/opt/stack/horizon/openstack_dashboard/dashboards/project/images_and_snapshots/templates',
 'project/instances': '/opt/stack/horizon/openstack_dashboard/dashboards/project/instances/templates',
 'project/loadbalancers': '/opt/stack/horizon/openstack_dashboard/dashboards/project/loadbalancers/templates',
 'project/network_topology': '/opt/stack/horizon/openstack_dashboard/dashboards/project/network_topology/templates',
 'project/networks': '/opt/stack/horizon/openstack_dashboard/dashboards/project/networks/templates',
 'project/overview': '/opt/stack/horizon/openstack_dashboard/dashboards/project/overview/templates',
 'project/routers': '/opt/stack/horizon/openstack_dashboard/dashboards/project/routers/templates',
 'project/stacks': '/opt/stack/horizon/openstack_dashboard/dashboards/project/stacks/templates',
 'project/volumes': '/opt/stack/horizon/openstack_dashboard/dashboards/project/volumes/templates',
 'project/vpn': '/opt/stack/horizon/openstack_dashboard/dashboards/project/vpn/templates',
 'settings/password': '/opt/stack/horizon/openstack_dashboard/dashboards/settings/password/templates',
 'settings/user': '/opt/stack/horizon/openstack_dashboard/dashboards/settings/user/templates'}
```

接下来就是最关键的urlpatterns,整个horizon所有的路径,并不是写到一个url.py文件中的,而是分散在每一个dashboard, 每一个panel中,有层级的关系。首先找dashboard的url,到每一个dashboard,再找每一个panel的url,所以url的路径关系为: ./dashboard/panel
urlpatterns in site:
```
(Pdb) pp urlpatterns
[<RegexURLPattern user_home ^home/$>,
 <RegexURLPattern jsi18n ^i18n/js/(?P<packages>\S+?)/$>,
 <RegexURLPattern set_language ^i18n/setlang/$>,
 <RegexURLResolver <module 'django.conf.urls.i18n' from '/usr/local/lib/python2.7/dist-packages/django/conf/urls/i18n.pyc'> (None:None) ^i18n/>,
 <RegexURLPattern qunit_tests ^qunit/$>,
 <RegexURLResolver <RegexURLResolver list> (admin:admin) ^admin/>,
 <RegexURLResolver <RegexURLResolver list> (settings:settings) ^settings/>,
 <RegexURLResolver <RegexURLResolver list> (project:project) ^project/>]
```


urlpatterns in dashboard
```
(Pdb) pp urlpatterns[-1].urlconf_name
[<RegexURLResolver <RegexURLPattern list> (instances:instances) ^instances/>,
 <RegexURLResolver <RegexURLPattern list> (routers:routers) ^routers/>,
 <RegexURLResolver <RegexURLPattern list> (databases:databases) ^databases/>,
 <RegexURLResolver <RegexURLPattern list> (firewalls:firewalls) ^firewalls/>,
 <RegexURLResolver <RegexURLPattern list> (containers:containers) ^containers/>,
 <RegexURLResolver <RegexURLPattern list> (access_and_security:access_and_security) ^access_and_security/>,
 <RegexURLResolver <RegexURLPattern list> (network_topology:network_topology) ^network_topology/>,
 <RegexURLResolver <RegexURLPattern list> (database_backups:database_backups) ^database_backups/>,
 <RegexURLResolver <RegexURLPattern list> (loadbalancers:loadbalancers) ^loadbalancers/>,
 <RegexURLResolver <RegexURLPattern list> (vpn:vpn) ^vpn/>,
 <RegexURLResolver <RegexURLPattern list> (volumes:volumes) ^volumes/>,
 <RegexURLResolver <RegexURLPattern list> (stacks:stacks) ^stacks/>,
 <RegexURLResolver <RegexURLPattern list> (networks:networks) ^networks/>,
 <RegexURLResolver <RegexURLPattern list> (images_and_snapshots:images_and_snapshots) ^images_and_snapshots/>,
 <RegexURLResolver <RegexURLPattern list> (overview:overview) >]
```


urlpatterns in panel
```
(Pdb) pp urlpatterns[-1].urlconf_name[-1].urlconf_name
[<RegexURLPattern index ^$>, <RegexURLPattern warning ^warning$>]
```


猜你喜欢

转载自blog.csdn.net/hackerain/article/details/25929759