关闭

control your panel

234人阅读 评论(0) 收藏 举报

本科的时候学了点儿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_vpn': 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 %}
      <a href="{% url 'horizon:project:network_topology:createnetwork' %}" id="networks__action_create" class="btn btn-default btn-sm ajax-modal

{% if network_quota_exceeded %}disabled

{% endif %}">

<span class="fa fa-plus"></span> {% if network_quota_exceeded %}{% trans "Create Network (Quota exceeded)"%}

{% else %}{% trans "Create Network"%}{% endif %}</a>

点击create network button弹出创建网络的template。


再看一句:

<span data-networktopology="{% url 'horizon:project:network_topology:json' %}" id="networktopology"></span>

要想在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')

得到数据了!

在哪儿用的呢?

<script type="text/javascript">
  if (typeof horizon.network_topology !== 'undefined') {
    horizon.network_topology.init();
  } else {
    addHorizonLoadEvent(function () {
      horizon.network_topology.init();
    });
  }
</script>

我们看看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




0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:25420次
    • 积分:1146
    • 等级:
    • 排名:千里之外
    • 原创:95篇
    • 转载:0篇
    • 译文:0篇
    • 评论:4条
    最新评论