本科的时候学了点儿UI开发的皮毛,研究生的时候摆弄过Django,后来终究还是把UI那一套东西留在某个角落了,虽然horizon提供了极为动态的扩展修改机制,
并不需要对UI有太多的了解就能开发出不错的效果(终究是一个Django项目,要想实现自己的复杂的js效果,还是需要专门搞UI的人来写html页面的), 前面讲了好
几篇关于怎么实现horizon的东西,有几个疑问需要收尾:
1. 各种settings文件的关系, RDO装好之后又/etc/openstack-dashboard/local_settings(使用virtual env时候,要配置的local setting也是这个), 有
/usr/share/openstack-dashboard/openstack_dashboard/settings, 还有配apache之后/etc/httpd/conf.d/15-horizon_vhost.conf,主要是这三个
2. 如何控制panel的显示?比如在/usr/share/openstack-dashboard/openstack_dashboard/dashboards/project中的dashboard.py中:
class Project(horizon.Dashboard):
name = _("Project")
slug = "project"
panels = (
BasePanels,
NetworkPanels,
ObjectStorePanels,
OrchestrationPanels,
DatabasePanels,
DataProcessingPanels,)
default_panel = 'overview'
红色的是我们常规可以看到的compute,network,object store三个panel group,我们在panel group中添加panel前面已经说过很多,没有问题,会显示出来,但是
这些剩下的heat,trove,sahara为什么没有显示出来呢?
3. 在template中call url怎么做到呢,我们事先自己的页面,初始化的数据可以传进去,想tabview那样,但是如果动态获取数据怎么得到呢?
整个horizon的问题很多,虽然horizon是openstack的一个模块,然而它并不影响openstack的逻辑,你也可以实现自己的完全新的UI,国内的利用openstack搞公有云的
都是这个路子。
查阅资料,但看horizon的源码,我的理解是:
1. 几个setting文件的作用,/usr/share/openstack-dashboard/openstack_dashboard/settings是基本的配置,/etc/openstack-dashboard/local_settings则可以
修改它,在local_settings中做的配置可以覆盖基本配置,关于STATIC_ROOT, error log等则在/etc/httpd/conf.d/15-horizon_vhost.conf中(关于horizon和apache的
配置可以参看horizon官网配置), Ubuntu上在openstack-dashboard/openstack_dashboard/dashboards/local/local_settings.py中的修改才会起作用(为什么ubuntu和Centos表现出来的不一样的,难道是J版和K版的差异?需要再看看。。。)
2. 即使我们在 openstack_dashboards/dashboards/project中的dashboard.py中添加Panel,还是不一定会显示,实际控制Panel显示的是keystone, 只有在
keystone中注册service才可以看到对应的panel,比如data_processing/clusters/panel.py和firewall/panel.py中我们可以看到:
permissions = ('openstack.services.network',)
permissions = (('openstack.services.data-processing',
'openstack.services.data_processing'),) #本来是个bug,这里填写两个,表示两者均可, 是OR的关系
参照: https://bugs.launchpad.net/horizon/+bug/1429987
然而即便是permissions的限制解除,仍有方法限制是否显示,比如在firewall/panel.py中:
def allowed(self, context):
request = context['request']
if not request.user.has_perms(self.permissions):
return False
try:
if not neutron.is_service_enabled(request,
config_name='enable_firewall',
ext_name='fwaas'):
return False
看neutron的api中代码,找到is_service_enabled方法,
def is_service_enabled(request, config_name, ext_name):
return (is_enabled_by_config(config_name) and
is_extension_supported(request, ext_name))
最终走到settings配置文件中(local_setting):
OPENSTACK_NEUTRON_NETWORK = {
'enable_lb': False,
'enable_firewall': False,
'enable_quotas': True,
'enable_security_group': True,
'enable_': False,
'enable_distributed_router': False,
'enable_ha_router': False,
所以既要enabled by 配置文件,也要extension supported,这里的extension supported在分析neutron时候提过。
3.之前写了如何加入自己的static file比如css或者js库,这里第三个问题更多的时候如何写完整的,特殊效果的html页, 看一个最典型的例子,
network_topology panel中的index.html.
首先是include了三个html页面,都是{% extends "horizon/client_side/template.html" %},且包含一个block id,什么时候体现作用,我们稍后提到
{% include "project/network_topology/client_side/_balloon_container.html" %}
{% include "project/network_topology/client_side/_balloon_device.html" %}
{% include "project/network_topology/client_side/_balloon_port.html" %}
接着定义了几个button,看一个create network的button:
{% if create_network_allowed %}
url 'horizon:project:network_topology:createnetwork' %}" id="networks__action_create" class="btn btn-default btn-sm ajax-modal
{% if network_quota_exceeded %}disabled
{% endif %}">
{% if network_quota_exceeded %}{% trans "Create Network (Quota exceeded)"%}
{% else %}{% trans "Create Network"%}{% endif %}
点击create network button弹出创建网络的template。
再看一句:
url 'horizon:project:network_topology:json' %}" id="networktopology">
要想在html里面获得数据怎么办?答案就在这里,trace horizon:project:network_topology:json最终在network_toplogy的view中得到:
def get(self, request, *args, **kwargs):
data = {'servers': self._get_servers(request),
'networks': self._get_networks(request),
'ports': self._get_ports(request),
'routers': self._get_routers(request)}
self._prepare_gateway_ports(data['routers'], data['ports'])
json_string = json.dumps(data, ensure_ascii=False)
return HttpResponse(json_string, content_type='text/json')
得到数据了!
在哪儿用的呢?
我们看看horizon.network_toplogy.init()最终调用的是什么?
horizon/static/horizon/js/horizon.network_topoligy.js中的init()方法,在该方法中我们可以看到:
self.balloon_tmpl = Hogan.compile($('#balloon_container').html());
self.balloon_device_tmpl = Hogan.compile($('#balloon_device').html());
self.balloon_port_tmpl = Hogan.compile($('#balloon_port').html());
红色的部分就是前面提到的include进来的三个html页的id, 在init函数中通过:
$.getJSON($('#networktopology').data('networktopology') + '?' + $.now(),
function(data) {
self.model = data;
self.data_convert();
setTimeout(function(){
self.load_network_info();
}, self.reload_duration);
}
);
拿到数据, 点击不同按钮或者不同操作时,用js生成不同效果。
到这里,三个问题就回答完了,最后mark一个关于url解析的文章,写的不错:
http://blog.csdn.net/feelang/article/details/25464261