Newton版Openstack学习笔记Dashboard开发

一.背景:

学习Openstack已有段时间了,之前一直研究的是安装以及使用Openstack,但是用同事的话讲,你只会安装你连入门都没有。所以想更深入一点,那就想在安装部署之上更进一步做一些开发改造,所以第一个想到的就是开发Dashboard。因为它安装简单,但是一旦开发研究学习源码才发现自己太天真了,更何况自己本身并没有语言基础更别说Python了,所以在Openstack的开发道路上步履蹒跚。此刻,这里,做一点笔记,先把书读"厚"再说。

二.Dashboard简介

Openstack的Dashboard项目一般被称为Horizon,根据官网安装部署及其简单,yum install openstack-dashboard即可,配置也简单只要修改/etc/openstack-dashboard/local_settings以及/etc/sysconfig/memcached,再启动httpd服务就可以登录了。

但是在查看它的源码就会发现,它并不是你想的那么简单。

Horizon:它是一个基于django webframework开发的标准的python wsgi程序,一般运行在webserver(apache httpd)之上。

Horizon的源码中,包含两个代码文件夹

  1. horizon ### /usr/lib/python2.7/site-packages/horizon
  2. openstack_dashboard ### /usr/share/openstack-dashboard

三.创建一个Dashboard

1.环境准备

操作系统Centos7.2
OpenstackNewton
Python2.7.5
Django1.8.14
  • 查看Django版本
# python
Python 2.7.5 (default, Nov  6 2016, 00:28:07) 
[GCC 4.8.5 20150623 (Red Hat 4.8.5-11)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import django
>>> print django.VERSION
(1, 8, 14, 'final', 0)

2.创建dashboard应用

  • 既然每个dashboard都是django中的一个app,那就可以使用django的命令来创建一个dashboard目录结构
# cd /usr/share/openstack-dashboard
# python manage.py

Type 'manage.py help <subcommand>' for help on a specific subcommand.

Available subcommands:

[auth]
    changepassword
    createsuperuser

[compressor]
    compress
    mtime_cache

[django]
    check
    compilemessages
    createcachetable
    dbshell
    diffsettings
    dumpdata
    flush
    inspectdb
    loaddata
    makemessages
    makemigrations
    migrate
    runfcgi
    shell
    showmigrations
    sql
    sqlall
    sqlclear
    sqlcustom
    sqldropindexes
    sqlflush
    sqlindexes
    sqlmigrate
    sqlsequencereset
    squashmigrations
    startapp
    startproject
    syncdb
    test
    testserver
    validate

[horizon]
    startdash
    startpanel

[openstack_dashboard]
    make_web_conf
    migrate_settings

[sessions]
    clearsessions

[staticfiles]
    collectstatic
    findstatic
    runserver
  • 可以看到horizon部分有startdash和startpanel两个命令,可以直接使用:
# mkdir -p openstack_dashboard/dashboards/dlwdashboard
# python manage.py startdash dlwdashboard  --target openstack_dashboard/dashboards/dlwdashboard 
# mkdir -p openstack_dashboard/dashboards/dlwdashboard/dlwpanel
# python manage.py startpanel dlwpanel   --dashboard=openstack_dashboard.dashboards.dlwdashboard   --target=openstack_dashboard/dashboards/dlwdashboard/dlwpanel

2.1、目录结构:

# cd openstack_dashboard/dashboards/
# tree dlwdashboard/
dlwdashboard/
├── dashboard.py
├── dashboard.pyc
├── dlwpanel
│   ├── __init__.py
│   ├── panel.py
│   ├── templates
│   │   └── dlwpanel
│   │       └── index.html
│   ├── tests.py
│   ├── urls.py
│   └── views.py
├── __init__.py
├── __init__.pyc
├── static
│   └── dlwdashboard
│       ├── js
│       │   └── dlwdashboard.js
│       └── scss
│           └── dlwdashboard.scss
└── templates
    └── dlwdashboard
        └── base.html


9 directories, 13 files

2.2定义一个仪表盘dashboard

# cd dlwdashboard/
# vi dashboard.py

# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.

from django.utils.translation import ugettext_lazy as _

import horizon


class Dlwgroup(horizon.PanelGroup):
    slug = "dlwgroup"
    name = _("Dlw Group")
    panels = ('dlwpanel',)

class Dlwdashboard(horizon.Dashboard):
#    name = _("Dlw dashboard")
    name = _("Dlw")
    slug = "dlwdashboard"
    panels = (Dlwgroup,)  # Add your panels here.
    default_panel = 'dlwpanel'  # Specify the slug of the dashboard's default panel.


horizon.register(Dlwdashboard)
  • 可以定义修改dashboard的名字
name = _("Dlw")

3.创建面板panel

3.1、目录结构

# tree dlwpanel/
dlwpanel/
├── __init__.py
├── panel.py
├── templates
│   └── dlwpanel
│       └── index.html
├── tests.py
├── urls.py
└── views.py

2 directories, 6 files

3.2、定义面板

# cd dlwpanel
# vi panel.py 

# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from django.utils.translation import ugettext_lazy as _

import horizon
from openstack_dashboard.dashboards.dlwdashboard import dashboard


class Dlwpanel(horizon.Panel):
    name = _("Dlw panel")
    slug = "dlwpanel"


dashboard.Dlwdashboard.register(Dlwpanel)

3.3、定义表单tables

# vi 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=_("Availability Zone"))
    image_name = tables.Column('image_name', \
                               verbose_name=_("Image Name"))
    class Meta(object):
        name = "instances"
        verbose_name = _("Instances")
        table_actions = (MyFilterAction,)

3.4、定义标签页tab

# vi tab.py

from django.utils.translation import ugettext_lazy as _

from horizon import exceptions
from horizon import tabs

from openstack_dashboard import api
from openstack_dashboard.dashboards.dlwdashboard.dlwpanel 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

    def has_more_data(self, table):
        return self._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
        except Exception:
            self._has_more = False
            error_message = _('Unable to get instances')
            exceptions.handle(self.request, error_message)

            return []

class DlwpanelTabs(tabs.TabGroup):
    slug = "dlwpanel_tabs"
    tabs = (InstanceTab,)
    sticky = True

3.4、定义视图views.py

# vi views.py 

# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.

from horizon import tabs

from openstack_dashboard.dashboards.dlwdashboard.dlwpanel \
    import tabs as dlwdashboard_tabs


class IndexView(tabs.TabbedTableView):
    tab_group_class = dlwdashboard_tabs.DlwpanelTabs
    template_name = 'dlwdashboard/dlwpanel/index.html'

    def get_data(self, request, context, *args, **kwargs):
        # Add data to the context here...
        return context

3.5、自动生成的url.py

# vi url.py

# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.

from django.conf.urls import url

from openstack_dashboard.dashboards.dlwdashboard.dlwpanel import views


urlpatterns = [
    url(r'^$', views.IndexView.as_view(), name='index'),
]

3.6、定义模板template

# cd templates/dlwpanel/
# vi index.html 

{% extends 'base.html' %}
{% load i18n %}
{% block title %}{% trans "DlwPanel" %}{% endblock %}

{% block page_header %}
  {% include "horizon/common/_page_header.html" with title=_("DlwPanel") %}
{% endblock page_header %}

{% block main %}
<div class="row">
   <div class="col-sm-12">
   {{ tab_group.render }}
   </div>
</div>
{% endblock %}

4.激活新增的dashboard

# cd /usr/share/openstack-dashboard/openstack_dashboard/enabled
# vi _50_dlwdashboard.py 

# The name of the dashboard to be added to HORIZON['dashboards']. Required.
DASHBOARD = 'dlwdashboard'

# If set to True, this dashboard will not be added to the settings.
DISABLED = False

# A list of applications to be added to INSTALLED_APPS.
ADD_INSTALLED_APPS = [
    'openstack_dashboard.dashboards.dlwdashboard',
]

重启httpd服务

页面查看

输入图片说明

5.再定义表单tables

添加一个ip,在上面定义的tables.py里添加ip的代码,可以直接从原有的openstack代码里摘(因为这里的name,status,zone,image_name就是摘的)

# cat tables.py 
from django.utils.translation import ugettext_lazy as _
from horizon import tables
from django import template
class MyFilterAction(tables.FilterAction):
    name = "myfilter"
import six
def get_ips(instance):
    template_name = 'project/instances/_instance_ips.html'
    ip_groups = {}

    for ip_group, addresses in six.iteritems(instance.addresses):
        ip_groups[ip_group] = {}
        ip_groups[ip_group]["floating"] = []
        ip_groups[ip_group]["non_floating"] = []

        for address in addresses:
            if ('OS-EXT-IPS:type' in address and
               address['OS-EXT-IPS:type'] == "floating"):
                ip_groups[ip_group]["floating"].append(address)
            else:
                ip_groups[ip_group]["non_floating"].append(address)

    context = {
        "ip_groups": ip_groups,
    }
    return template.loader.render_to_string(template_name, context)

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"))
    ip = tables.Column(get_ips,
                       verbose_name=_("IP Address"),
                       attrs={'data-type': "ip"})
    class Meta(object):
        name = "instances"
        verbose_name = _("Instances")
        table_actions = (MyFilterAction,)

重启httpd服务 页面查看

输入图片说明

四.小结

创建一个新的dashboard,下面有group还有面板panel整个的流程:

1.app
2.dashboard.py
3.panel.py
4.tables.py
5.tabs.py
6.views
7.url.py
8.template
9.enabled
10.httpd
  • Horizon面板的设计分成三层:Dashboard → PanelGroup → Panel
  • Horizon中现有的dashboard有4个:
    1. project 普通用户登陆后看到的项目面板
    2. admin 管理登陆后可见,左侧的管理员面板
    3. settings 右上角的设置面板,里面可设置语言,时区,更改密码
    4. router(配置文件中将profile_support打开可见),ciso nexus 1000v的管理面板

每一个dashboard都是django中的一个app,django中的app可以理解成对业务逻辑模块化的一种手段,里面可以包含自己独有的url设定,模板,和业务逻辑代码

每个dashboard下定义了一系列的PanelGroup,虚拟机管理对应到界面上就是一个PanelGroup(Manage Compute), 里面有一系列的子panel(Overview, Instances, Volumes…)。Swift,heat,neutron的管理面板各自都是一个PanelGroup,底下有各自的子panel.

五.在已有的dashboard下创建panel

此处选择在project下建一个名为dbc的空白面板 有了上面的步骤,这里就很简单了,建一个空白的面板,只需要三步

1.建立panel

# /usr/share/openstack-dashboard/openstack_dashboard/dashboards/project/
# mkdir bdc
# cd  /usr/share/openstack-dashboard/
# python manage.py startpanel bdc   --dashboard=openstack_dashboard.dashboards.project  --target=openstack_dashboard/dashboards/project/bdc

2.激活enabled

# cd /usr/share/openstack-dashboard/openstack_dashboard/enabled
# cp _1050_project_images_panel.py _1051_project_bdc_panel.py 
# vi _1051_project_bdc_panel.py 


# (c) Copyright 2016 Hewlett Packard Enterprise Development Company LP
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.

# The slug of the panel to be added to HORIZON_CONFIG. Required.
PANEL = 'bdc'
# The slug of the dashboard the PANEL associated with. Required.
PANEL_DASHBOARD = 'project'
# The slug of the panel group the PANEL is associated with.
PANEL_GROUP = 'compute'

# Python panel class of the PANEL to be added.
ADD_PANEL = 'openstack_dashboard.dashboards.project.bdc.panel.Bdc'

3.重启httpd

# systemctl restart httpd

页面查看

输入图片说明

六.国际化

1.简介


国际化,django的一个组成部分,支持多国语言,不同的机器打开的页面显示不同的语言,这里做个中英文对照关系的简单改造。 在/usr/share/openstack-dashboard/openstack_dashboard/locale/zh_CN/LC_MESSAGES目录下有个django.mo文件,这里就是作为中英文翻译的依据,将该文件取出来放在G:/Python练习目录下:


sftp> cd /usr/share/openstack-dashboard/openstack_dashboard/locale/zh_CN/LC_MESSAGES
sftp> lcd G:/Python练习
sftp> get django.mo

2.反编译django.mo

  1. mo文件是不可以编辑文件,需要将其反编译为.po文件
  2. 安装一个工具软件Poedit
  3. 使用cmd或者powershell进行反编译操作
  4. 命令行进入Poedit的安装目录目录
cd E:\Program Files (x86)\Poedit\GettextTools\bin
msgunfmt.exe G:\Python练习\django.mo -o G:\Python练习\django.po

3.修改po文件并编译

  1. 生成django.po文件,可以使用Pycharm工具打开该po文件,照葫芦翻译之前新建的Bdc面板

输入图片说明

  1. 使用Poedit将po文件编译为mo文件

输入图片说明

  1. 上传至/usr/share/openstack-dashboard/openstack_dashboard/locale/zh_CN/LC_MESSAGES

重启httpd服务

页面查看

输入图片说明

翻译成功!

参考链接:

http://blog.csdn.net/ll_jcb/article/details/54291154

http://www.cnblogs.com/yuxc/p/3419102.html

https://docs.openstack.org/developer/horizon/tutorials/dashboard.html

转载于:https://my.oschina.net/xiaozhublog/blog/877717

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值