Professional Documents
Culture Documents
Launching an Instance
Admin Overview
Project Overview
Launching an Instance
Launching an Instance
Launching an Instance
Launching an Instance
Launching an Instance
Launching an Instance
OpenStack Clouds
Architecture and Model
OpenStack Model
http://docs.openstack.org/training-guides/content/module001-ch004-openstack-architecture.html
http://docs.openstack.org/openstack-ops/content/example_architecture.html
OpenStack Projects
Nova (Compute)
Nova (Network)
VM Registration (Glance)
Identity (Keystone)
Object Storage (Swift)
Block Storage (Cinder)
Dashboard (Horizon)
OpenStack Horizon
Controlling the Cloud with Django
Horizon Overview
Django-based application deployed via
Apache and WSGI
Provides access to OpenStack services
Leverages existing technologies
o Bootstrap, jQuery, Underscore.js,
AngularJS, D3.js, Rickshaw, LESS CSS
Extends Django to enhance extensibility
Django Stack
Horizon Stack
Horizon UI Structure
Dashboard
Projects
Branding
Panel Group
Panel
Panel Content
Sidebar
User Info
Admin Dashboard
Admin Dashboard
Project Dashboard
OpenStack Horizon
Panels and Features
Instance List
Filtering
Sorting
Sorting
Row Actions
Table Actions
Table Actions
Table Actions
Table Actions
Instance Details
Instance Details
Instance Log
Instance Console
OpenStack Horizon
Interesting Patterns
Dashboard App
Dashboards created as Django Applications
Dashboard modules partitioned into:
o static
o templates
o python modules
Directory Structure
cloudopen/
__init__.py
dashboard.py
templates/
cloudopen/
static/
cloudopen/
css/
img/
js/
settings.py
INSTALLED_APPS = (
...
'horizon',
'openstack_dashboard.dashboards.project',
'openstack_dashboard.dashboards.admin',
'openstack_dashboard.dashboards.metacloud',
'openstack_dashboard.dashboards.settings',
'openstack_dashboard.dashboards.cloudopen',
...
)
dashboard.py
class BasePanelGroup(horizon.PanelGroup):
slug = "overview"
name = _("Overview")
panels = ("hypervisors",)
class CloudOpen(horizon.Dashboard):
name = _("Linuxcon")
slug = "linuxcon"
panels = (BasePanelGroup,)
default_panel = "hypervisors"
roles = ("admin",)
horizon.register(CloudOpen)
CloudOpen Dashboard
Dashboard
PanelGroup
View
Module
View
module
,es
together
everything:
o Tables,
Templates,
API
Calls
Horizon
base
views:
o APIView,
LoginView,
Mul,TableView,
DataTableView,
MixedDataTableView,
TabView,
TabbedTableView,
WorkowView
views.py
from horizon import tables
class HypervisorsIndexView(tables.DataTableView):
table_class = hv_tables.AdminHypervisorsTable
template_name = cloudopen/hypervisors/index.html
def get_data(self):
hypervisors = []
states = {}
hypervisors = api.nova.hypervisor_list(self.request)
return hypervisors
Table
Module
Table classes provide framework for tables:
o consistent look and feel
o configurable table_actions and row_actions
o select/multi-select column
o sorting
o pagination
Functionality is split server- and client-side
tables.py
class EnableAction(tables.BatchAction):
class DisableAction(tables.BatchAction):
name = 'disable'
classes = ('btn-danger',)
def allowed(self, request, hv):
return hv.service.get('status') == 'enabled'
def action(self, request, obj_id):
hv = api.nova.hypervisor_get(request, obj_id)
host = getattr(hv, hv.NAME_ATTR)
return api.nova.service_disable(request, host, 'nova-compute')
def search_link(x):
return '/admin/instances?q={0}'.format(x.hypervisor_hostname)
tables.py
class AdminHypervisorsTable(tables.DataTable):
hypervisor_hostname = tables.Column(
'hypervisor_hostname', verbose_name=_('Hostname'))
state = tables.Column(
lambda hyp: hyp.service.get('state', _('UNKNOWN')).title(),
verbose_name=_('State'))
running_vms = tables.Column(
'running_vms', link=search_link, verbose_name=_('Instances'))
...
class Meta:
name = 'hypervisors'
verbose_name = _('Hypervisors')
row_actions = (EnableAction, DisableAction)
Template
Standard Django template format
Typically leverage base horizon templates
(e.g. base.html)
index.html
{% extends 'base.html' %}
{% load i18n horizon humanize sizeformat %}
{% block title %}{% trans 'Hypervisors' %}{% endblock %}
{% block page_header %}
{% include 'horizon/common/_page_header.html' with title=_('All
Hypervisors') %}
{% endblock page_header %}
{% block main %}
{{ table.render }}
{% endblock %}
URLs
Modules
Provides
URL
to
View
mappings
index.html
from django.conf.urls import patterns
from django.conf.urls import url
Completed Dashboard!
Nav entries
Panel rendering
Column sorting
Data retrieval
Linking
Row actions
RPC
Authen,ca,on
Keystone
manages
all
Authen,ca,on
for
OpenStack
To
access
an
OpenStack
service:
o authen,cate
with
Keystone
and
obtain
a
TOKEN
o Use
TOKEN
for
transac,ons
with
Service
Horizon
passes
all
Auth
requests
to
Keystone
backend.py
class MetacloudKeystoneBackend(KeystoneBackend):
def authenticate(self, request=None, username=None, password=None,
user_domain_name=None, auth_url=None):
keystone_client = get_keystone_client()
client = keystone_client.Client(
user_domain_name=user_domain_name, username=username,
password=password, auth_url=auth_url, )
# auth_ref gets assigned here
Customiza,on
Hooks
Change
Site
Title,
Logo,
Brand
Links
Modify
Dashboards
and
Panels
Change
BuRon
Styles
Use
Custom
Stylesheets
Use
Custom
Javascript
local_settings.py
HORIZON_CONFIG = {
...
'customization_module':
'openstack_dashboard.dashboards.cloudopen.overrides',
'test_enabled': True,
}
overrides.py
from openstack_dashboard.dashboards.cloudopen.test import panel\
as test_panel
from openstack_dashboard.dashboards.cloudopen import dashboard \
as cloudopen_dashboard
from django.conf import settings
import horizon
CLOUDOPEN_DASHBOARD_SETTINGS = horizon.get_dashboard('cloudopen')
if settings.HORIZON_CONFIG.get('test_enabled'):
CLOUDOPEN_DASHBOARD_SETTINGS .register(test_panel.Tests)
cloudopen_dashboard.BasePanels.panels += ('ui', )
Test Panel
Pluggable Settings
Since Icehouse release, Horizon enables
pluggable settings to control structure
o Enable/Disable new Dashboards
o Add new PanelGroups
o Add/Remove Panels to/from PanelGroups
Settings all live in:
o openstack_dashboard/local/enabled
Pluggable Settings
_10_cloudopen.py
_20_cloudopen_add_panel_group.py
_30_tests_add_panel.py
__init__.py
Pluggable Settings
_10_cloudopen.py
DASHBOARD = 'cloudopen'
DISABLED = False
ADD_INSTALLED_APPS = [
'openstack_dashboard.dashboards.cloudopen',
]
Pluggable Settings
_20_cloudopen_add_panel_group.py
DASHBOARD = 'cloudopen'
DISABLED = False
ADD_INSTALLED_APPS = [
'openstack_dashboard.dashboards.cloudopen',
]
Pluggable Settings
_30_tests_add_panel.py
PANEL = 'test'
PANEL_DASHBOARD = 'cloudopen'
PANEL_GROUP = 'tests'
ADD_PANEL = \
'openstack_dashboard.dashboards.cloudopen.test.panel.Tests'
Pluggable Settings
_30_tests_add_panel.py
PANEL = 'test'
PANEL_DASHBOARD = 'cloudopen'
PANEL_GROUP = 'tests'
ADD_PANEL = \
'openstack_dashboard.dashboards.cloudopen.test.panel.Tests'
Pluggable Settings
Pluggable Settings
_30_overview_add_panel.py
PANEL = 'test'
PANEL_DASHBOARD = 'cloudopen'
PANEL_GROUP = 'overview'
ADD_PANEL = \
'openstack_dashboard.dashboards.cloudopen.test.panel.Tests'
Pluggable Settings
base.html
<!DOCTYPE html>
<html>
<head>
<title>{% block title %}{% endblock %} - {% site_branding %}</title>
{% block css %}
{% include "_stylesheets.html" %}
{% endblock %}
. . .
</head>
<body id="{% block body_id %}{% endblock %}">
{% block content %}
. . .
{% endblock %}
<div id="footer">{% block footer %}{% endblock %}</div>
{% block js %}
{% include "horizon/_scripts.html" %}
{% endblock %}
</body>
</html>
index.html
{% extends "base.html" %}
{% load i18n %}
{% block title %}{% trans "Volumes" %}{% endblock %}
{% block css %}
{% include "cloudopen/_stylesheets.html" %}
{% endblock %}
{% block page_header %}
{% include "horizon/common/_page_header.html" with title=_("Volumes") %}
{% endblock page_header %}
{% block main %}
<div id="volumes">{{ volumes_table.render }}</div>
<div id="volume-types">{{ volume_types_table.render }}</div>
{% endblock %}
{% block js%}
{% include "cloudopen/_scripts.html" %}
{% endblock %}
Custom View
Home button
Project selector
Simplified Nav
Custom View
Customized UI
Customized UI
Instance locking
Customized UI
Controller Page
Hypervisor Actions
Advanced Features
Client-side Rendering
Full dataset search
Full pagination
Real-time Data
Updates every 5s
Historical Metrics
Convenient access
Up to 1 year of data
OpenStack Horizon
Contributing
Thank You
David Lapsley
@devlaps, david.lapsley@metacloud.com