作者:吕嘉伟
团队:大云虚机网络
Horizon可分为3层,由上到下分别为Dashboard →PanelGroup → Panel。从代码结构上看可以发现最上层是dashboards,它包含了4个主要的dashboard:project 普通用户登陆后看到的项目面板;admin 管理登陆后可见,左侧的管理员面板;settings 右上角的设置面板,里面可设置语言,时区,更改密码;router(配置文件中将profile_support打开可见,在应用中我未曾使用过)。Dashboards的页面展示如图1。
图1dashboards
每一个dashboard都是django中的一个app,里面又包含了许多独立的Panel,这些panel组成了panelgroup,以网络功能panelgroup为例,它包含了6个panel,分别是’network_topology','networks','routers','loadbalancers','firewalls','。这些panelgroup及group中包含的panel,都定义在dashboard.py文件中。
project/dashboard.py
class Project(horizon.Dashboard):
name =_("Project")
slug ="project"
panels = (
BasePanels,
NetworkPanels,
ObjectStorePanels,
OrchestrationPanels,
DatabasePanels,
DataProcessingPanels,)
default_panel ='overview'
horizon.register(Project)
class NetworkPanels(horizon.PanelGroup):
slug ="network"
name =_("Network")
panels =('network_topology',
'networks',
'routers',
'loadbalancers',
'firewalls',
'',)
图2 NetworkPanels
每个panel是以一个包(文件夹)的形式存在,里面包含了panel.py、tables.py、urls.py、views.py、forms.py等文件。其中panel.py是一个特殊的文件,系统会根据一个dashboard中定义的panels属性,自动查找相应目录(例如'networks')中的panel.py。
project/dashboard/networks/panel.py
from django.utils.translation import ugettext_lazy as_
import horizon
from openstack_dashboard.dashboards.project importdashboard
class Networks(horizon.Panel):
name =_("Networks")
slug ='networks' #猜测是用这个属性去找networks目录下的panel.py文件
permissions= ('openstack.services.network',)
dashboard.Project.register(Networks)
每个panel中都有一个tables.py文件,table用来定义需要展示的数据,Horizon提供了DataTable基类,我们可以通过继承DataTable来实现自定义的table。以networks panel为例:
project/dashboard/networks/tables.py
class NetworksTable(tables.DataTable):
name =tables.Column("name_or_id",
verbose_name=_("Name"),
link='horizon:project:networks:detail')
subnets =tables.Column(get_subnets,
verbose_name=_("SubnetsAssociated"),)
shared =tables.Column("shared", verbose_name=_("Shared"),
filters=(filters.yesno, filters.capfirst))
status =tables.Column("status", verbose_name=_("Status"),
display_choices=STATUS_DISPLAY_CHOICES)
admin_state= tables.Column("admin_state",
verbose_name=_("Admin State"),
display_choices=DISPLAY_CHOICES)
classMeta(object):
name ="networks"
verbose_name = _("Networks")
table_actions = (CreateNetwork, DeleteNetwork,
NetworksFilterAction)
row_actions = (EditNetwork, CreateSubnet, DeleteNetwork)
从代码中可以看出,Networkstable定义了4列需要展示的数据以及两种动作集合。Horizon 为table定义了3中基本动作(Action、LinkAction、FilterAction)和4个扩展动作(BatchAction、DeleteAction、UpdateAction、FixedFilterAction)。
每个panel中还包含一个views.py,view负责集成table,获取数据并展示在相应的table中。
project/dashboard/networks/views.py
from openstack_dashboard.dashboards.project.networksimport tables as project_tables
class IndexView(tables.DataTableView):
table_class= project_tables.NetworksTable
template_name = 'project/networks/index.html'
page_title= _("Networks")
defget_data(self):
try:
tenant_id = self.request.user.tenant_id
networks = api.neutron.network_list_for_tenant(self.request, tenant_id)
exceptException:
networks = []
msg= _('Network list can not be retrieved.')
exceptions.handle(self.request, msg)
returnnetworks
从代码中可以发现,IndexView集成了NetworksTable,通过get_data方法获取数据,使用index.html构建页面,页面效果如图3。
图3 展示网络信息
另外一个panel中还包括urls.py和template,其中urls.py负责匹配url并调用相应的方法,template包含了若干html文件,负责具体的页面呈现。
结语:
本文简要描述了一个dashboard的基本组成模块,主要包括panel、tables、views的介绍。在一个dashboard panel中还包含了tabs、forms、workflows等内容,本文并未涉及,同时tables、views、action还包含多种类型,这些内容将在后续的实践中加以实验并总结。
参考文献:
[1] Tutorial: Building a Dashboard using Horizon.http://docs.openstack.org/developer/horizon/topics/tutorial.html.
[2] Horizon Is Easy, Horizon Is Complexhttp://www.cnblogs.com/yuxc/p/3419102.html.
[3]扩展OpenStack Dashboard简明教程.http://my.oschina.net/ckanner/blog/193370?fromerr=tVWBbXcP#OSC_h2_4.
[4] Horizon Quickstart.http://docs.openstack.org/developer/horizon/quickstart.html.