openstack horizon 新增dashboard

在horizon上新增dashboard

环境:centos7、devstack(openstack kilo)

1.       快速建立一个自己的dashboard

1.1 run_test.sh

Horizon提供一个定制管理的命令来帮助我们建立一个典型的dashboard的架构,然后可以根据自己的需要来修改这个架构,进入到horizon这个目录下,命令如下:

1.2 目录结构如下:

因为我运行上面命令没有成功,所以下面自己照着这个目录结构手动建立了一个自己的dashboard

2.       手动建立dashboard

2.1 dashboard

在openstack_dashboard/dashboards/mydashboard目录下vimdashboard.py,代码如下

from django.utils.translation import ugettext_lazy as_

 

import horizon

 

class Mydashboard(horizon.Dashboard):

   name =_("Mydashboard")

   slug ="mydashboard"

   panels =()           # Add your panels here.

   default_panel= ''    # Specify the slug of thedashboard's default panel.

 

 

horizon.register(Mydashboard)

 

如果你想要修改dashboard的名字,你可以这样做

name=_(“Fronware”)

一个dashboard类的属性有

name:dashboard对外所呈现的名称

slug:被其它组件引用的内部名称

panels:

default_panel:

 

2.2   panel

2.2.1        panel structure如下

[stack@devstack mypanel]$ tree

.

|-- __init__.py

|-- __init__.pyc

|-- panel.py

|-- panel.pyc

|-- tables.py

|-- tables.pyc

|-- tabs.py

|-- tabs.pyc

|-- templates

|   `-- mypanel

|       `--index.html

|-- urls.py

|-- urls.pyc

|-- views.py

`-- views.pyc

 

2 directories, 13 files

[stack@devstack mypanel]$

2.2.2        定义一个panel

1.The panel.py file referencedabove has a special meaning. Within a dashboard, any module name listed inthe panels attribute on the dashboard class will be auto-discoveredby looking for thepanel.py file in a corresponding directory (the detailsare a bit magical, but have been thoroughly vetted in Django’s admin codebase).

panel.py格式如下:

from django.utils.translation import ugettext_lazy as_

 

import horizon

 

from openstack_dashboard.dashboards.mydashboard importdashboard

 

class Mypanel(horizon.Panel):

    name =_("Mypanel")

    slug ="mypanel"

 

dashboard.Mydashboard.register(Mypanel)

 

你可以修改name属性,如:

name=_(“Manage”)

3.      现在你要再次打开dashboard.py,把下面的代码插入在Mydashboard类的上面,这个代码定义了一个Mygroup类,以及添加了一个叫mypanel的panel

class Mygroup(horizon.PanelGroup):

    slug ="mygroup"

    name =_("My Group")

    panels =('mypanel',)

 

4.       修改Mydashboard类让他包含Mygroup,并且 add mypanel asthe default panel

class Mydashboard(horizon.Dashboard):

   name =_("Fronware")

   slug ="mydashboard"

   panels =(Mygroup,)  # Add your panels here.

   default_panel= 'mypanel'  # Specify the slug of thedefault panel.

 

5.      完整的dashboard.py如下

from django.utils.translation import ugettext_lazy as_

 

import horizon

 

 

class Mygroup(horizon.PanelGroup):

    slug ="mygroup"

    name =_("Manage")

    panels =('mypanel',)

 

 

class Mydashboard(horizon.Dashboard):

    name =_("Fronware")

    slug ="mydashboard"

    panels =(Mygroup,)  # Add your panels here.

   default_panel = 'mypanel'  #Specify the slug of the default panel.

 

horizon.register(Mydashboard)

 

运行dashboard.py,然后再进入mypanel运行panel.py但是报下列错误:

[stack@devstack mypanel]$ python panel.py

Traceback (most recent call last):

  File"panel.py", line 5, in <module>

    fromopenstack_dashboard.dashboards.mydashboard import dashboard

ImportError: No module named mydashboard

原因是要在mydashboard加入__init__.py文件,然后再运行该文件最后运行panel.py文件即可

2.3 Tables、Tabs、Views

We’ll start with the table, combine thatwith the tabs, and then build our view from the pieces.

2.3.1 定义一个table

Horizon provides a SelfHandlingForm DataTable classwhich simplifies the vast majority of displaying data to an end-user. We’rejust going to skim the surface here, but it has a tremendous number ofcapabilities

tables.py的代码如下:

from django.utils.translation import ugettext_lazy as_

 

from horizon import tables

 

 

class InstancesTable(tables.DataTable):

    name =tables.Column("name", verbose_name=_("Name"))

    status =tables.Column("status", verbose_name=_("Status"))

    zone = tables.Column('availability_zone',

                         verbose_name=_("Availability Zone"))

    image_name =tables.Column('image_name', verbose_name=_("Image Name"))

 

    class Meta:

        name ="instances"

       verbose_name = _("Instances")

 

There are several things going on here...we created a table subclass, and defined four columns that we want to retrievedata and display. Each of those columns defines what attribute it accesses onthe instance object as the first argument, and since we like to make everythingtranslatable, we give each column a verbose_name that’s marked fortranslation.

Lastly, we added a Meta class which indicatesthe meta object that describes the instances table.

2.3.1.1 Addingactions to a table

Horizon提供了三种基本的可以呈现table数据的action类:

在基本的action的基础上,还提供了一些扩展的action类:

现在,我们创建并向table添加一个“filter action”。我们需要编辑上面的table.py文件,添加了“filter action”后,我们将只能看到filter域中规定的字段。先定义一个FilterAction类:

class MyFilterAction(tables.FilterAction):

    name ="myfilter"

Then, we add that action to the tableactions for our table.:

class InstancesTable:

    class Meta:

       table_actions = (MyFilterAction,)

完整的tables.py

from django.utils.translation import ugettext_lazy as_

 

from horizon import tables

 

class MyFilterAction(tables.FilterAction):

    name ="myfilter"

 

class InstancesTable(tables.DataTable):

    name =tables.Column('name', \

                        verbose_name=_("Name"))

    status =tables.Column('status', \

                          verbose_name=_("Status"))

    zone =tables.Column('availability_zone', \

                         verbose_name=_("AvailabilityZone"))

    image_name =tables.Column('image_name', \

                              verbose_name=_("Image Name"))

 

    class Meta:

        name ="instances"

       verbose_name = _("Instances")

       table_actions = (MyFilterAction,)

 

2.3.2 定义一个tabs

因为我们有了table,可以接收数据,我们可以直接得到一个视图,这种情况下,我们同样适用HorizonTabGroup类,它给我们一个干净、简化的tabs接口来显示我们的可视化数据。

Create a tabs.py file underthe mypanel directory. Let’s make a tab group which has onetab. The completed code should look like the following:

from django.utils.translation import ugettext_lazy as_

 

from horizon import exceptions

from horizon import tabs

 

from openstack_dashboard import api

fromopenstack_dashboard.dashboards.mydashboard.mypanel import tables

 

 

class InstanceTab(tabs.TableTab):

    name =_("Instances Tab")

    slug ="instances_tab"

   table_classes = (tables.InstancesTable,)

   template_name = ("horizon/common/_detail_table.html")

    preload =False

 

    defhas_more_data(self, table):

        returnself._has_more

 

    def get_instances_data(self):

        try:

           marker = self.request.GET.get(

                       tables.InstancesTable._meta.pagination_param, None)

 

           instances, self._has_more = api.nova.server_list(

               self.request,

               search_opts={'marker': marker, 'paginate': True})

 

           return instances

        exceptException:

           self._has_more = False

           error_message = _('Unable to get instances')

           exceptions.handle(self.request, error_message)

 

           return []

 

class MypanelTabs(tabs.TabGroup):

    slug ="mypanel_tabs"

    tabs =(InstanceTab,)

    sticky =True

这个tab有一点复杂。tab处理tables的数据(以及所有有关的特性),同时它可以使用preload属性来指定这个tab该不该被加载,默认情况下为不加载。当有人点击它时,它将通过AJAX方式加载,在绝大多数情况下保存我们的API调用。

Additionally,the displaying of the table is handled by a reusable template,horizon/common/_detail_table.html. Some simplepagination code was added to handle large instance lists.

Lastly, thiscode introduces the concept of error handling in horizon. Thehorizon.exceptions.handle() functionis a centralized error handling mechanism that takes all the guess-work andinconsistency out of dealing with exceptions from the API. Use it everywhere.

2.3.3 把他们整合到一个视图(view)中

Horizon中,有很多基于类的预建视图,我们试着给所有通用整合组件提供起始点。

views.py代码如下:

from horizon import views

 

class IndexView(views.APIView):

    # A verysimple class-based view...

   template_name = 'mydashboard/mypanel/index.html'

 

    defget_data(self, request, context, *args, **kwargs):

        # Adddata to the context here...

        returncontext

这种情况我们想要一个起始的视图类型与tablestabs一起工作,那应该是TabbedTableView类。它很好的动态延迟加载能力(tabgroup提供的并混合在actions中)和AJAX方式更新tables的能力,使得在用户端基本不用做任何工作。

Change views.APIView tobe tabs.TabbedTableView and add MypanelTabs as the tabgroup class in the IndexView class:

class IndexView(tabs.TabbedTableView):

   tab_group_class = mydashboard_tabs.MypanelTabs

完整的views.py

from horizon import tabs

 

fromopenstack_dashboard.dashboards.mydashboard.mypanel \

    import tabsas mydashboard_tabs

 

class IndexView(tabs.TabbedTableView):

   tab_group_class = mydashboard_tabs.MypanelTabs

   template_name = 'mydashboard/mypanel/index.html'

 

    defget_data(self, request, context, *args, **kwargs):

        # Adddata to the context here...

        returncontext

2.3.4 URLs

The auto-generated urls.py file is like:

from django.conf.urls import patterns

from django.conf.urls import url

 

fromopenstack_dashboard.dashboards.mydashboard.mypanel.views \

    importIndexView

 

 

urlpatterns = patterns(

    '',

    url(r'^$',IndexView.as_view(), name='index'),

)

Adjust the import of IndexView to make thecode readable:

fromopenstack_dashboard.dashboards.mydashboard.mypanel import views

Replace the existing url pattern with thefollowing line:

url(r'^$',

   views.IndexView.as_view(), name='index'),

The completed urls.py file should look likethe following:

from django.conf.urls import patterns

from django.conf.urls import url

 

from openstack_dashboard.dashboards.mydashboard.mypanelimport views

 

 

urlpatterns = patterns('',

    url(r'^$',

       views.IndexView.as_view(), name='index'),

)

2.4 Template(模板)

Open the index.html file inthe mydashboard/mypanel/templates/mypanel directory, theauto-generated code is like the following:

{% extends 'base.html' %}

{% load i18n %}

{% block title %}{% trans "Mypanel" %}{%endblock %}

 

{% block page_header %}

    {% include"horizon/common/_page_header.html" with title=_("Mypanel")%}

{% endblock page_header %}

 

{% block main %}

{% endblock %}

The main block must be modified to insert thefollowing code:

<div class="row">

   <divclass="col-sm-12">

   {{tab_group.render }}

   </div>

</div>

If you want to change the title ofthe index.html file to be something else, you can change it. Forexample, change it to be My Panel inthe block title section. If you want the title inthe blockpage_header section to be something else, you can change it.For example, change it to be My Panel. The updated code could belike:

{% extends 'base.html' %}

{% load i18n %}

{% block title %}{% trans "My Panel" %}{%endblock %}

 

{% block page_header %}

   {% include"horizon/common/_page_header.html" with title=_("My Panel")%}

{% endblock page_header %}

 

{% block main %}

<div class="row">

   <divclass="col-sm-12">

   {{tab_group.render }}

   </div>

</div>

{% endblock %}

This gives us a custom page title, a header, andrenders our tab group provided by the view.

With all our code in place, the only thing left to dois to integrate it into our OpenStack Dashboard site.

2.5 Enable and show the dashboard

In order to make My Dashboard show upalong with the existing dashboards like Project or Admin onhorizon, you need to create a filecalled _50_mydashboard.py under openstack_dashboard/enabled andadd the following:

# The name of the dashboard to be added toHORIZON['dashboards']. Required.

DASHBOARD = 'mydashboard'

 

# If set to True, this dashboard will not be added tothe settings.

DISABLED = False

 

# A list of applications to be added toINSTALLED_APPS.

ADD_INSTALLED_APPS = [

   'openstack_dashboard.dashboards.mydashboard',

]

 

2.6 Run and check the dashboard

Everything is in place, now run Horizon onthe different port:

./run_tests.sh --runserver 0.0.0.0:8877

Goto http://<your server>:8877 using a browser. After loginas an admin you should be able see MyDashboard shows up at the leftside on horizon. Click it, My Group will expandwith My Panel. Click on MyPanel, the right side panel willdisplay an Instances Tab which has an Instances table.

If you don’t see any instance data, you haven’t createdany instances yet. Go to dashboard Project -> Images, selecta small image, for example, crioos-0.3.1-x86_64-uec ,click Launch and enter anInstance Name, click thebutton Launch. It should create an instance if the OpenStack or devstackis correctly set up. Once the creation of an instance is successful, goto My Dashboard again to check the data.

 

3. horizon的汉化

目录:/opt/stack/horizon/openstack_dashboard/locale/zh_CN/LC_MESSAGES

3.1 django.po

在django.po文件末尾加上你的东西,如:

msgid "Fronware"

msgstr "方物虚拟化"

 

msgid "Fcloud_Class"

msgstr "云教室"

 

msgid "Desktop_Manage"

msgstr "桌面管理"

3.2 编译django.po

msgfmt --statistics --verbose -o django.mo django.po

3.3 重启http服务

sudo service httpd restart

3.4 效果截图

效果图1.

 

效果图2.

 

4.参考:

 

http://docs.openstack.org/developer/horizon/topics/tutorial.html

http://www.doc88.com/p-118669710578.html

http://yuky1327.iteye.com/blog/1711337 

http://blog.csdn.net/qiuhan0314/article/details/44827669

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值