OPENSTACK THAT JUST WORKS
OpenStack Horizon:
Controlling the Cloud using Django
David Lapsley @devlaps, david.lapsley@metacloud.com August 21, 2014
OpenStack Horizon: Controlling the Cloud using Django David Lapsley - - PowerPoint PPT Presentation
OpenStack Horizon: Controlling the Cloud using Django David Lapsley @devlaps, david.lapsley@metacloud.com August 21, 2014 OPENSTACK THAT JUST WORKS OpenStack Horizon in Action OPENSTACK THAT JUST WORKS Launching an Instance Admin Overview
OPENSTACK THAT JUST WORKS
David Lapsley @devlaps, david.lapsley@metacloud.com August 21, 2014
OPENSTACK THAT JUST WORKS
OPENSTACK THAT JUST WORKS
http://docs.openstack.org/openstack-ops/content/example_architecture.html http://docs.openstack.org/training-guides/content/module001-ch004-openstack-architecture.html
OPENSTACK THAT JUST WORKS
Branding Dashboard Panel Group Panel Sidebar User Info Projects Panel Content
OPENSTACK THAT JUST WORKS
OPENSTACK THAT JUST WORKS
INSTALLED_APPS = ( ... 'horizon', 'openstack_dashboard.dashboards.project', 'openstack_dashboard.dashboards.admin', 'openstack_dashboard.dashboards.metacloud', 'openstack_dashboard.dashboards.settings', 'openstack_dashboard.dashboards.cloudopen', ... )
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)
Dashboard PanelGroup
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
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)
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)
{% 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 %}
from django.conf.urls import patterns from django.conf.urls import url from openstack_dashboard.dashboards.cloudopen.hypervisors import views urlpatterns = patterns( 'openstack_dashboard.dashboards.cloudopen.hypervisors.views' url(r'^$', views.IndexView.as_view(), name='index'), )
Nav entries Column sorting Panel rendering Linking RPC Data retrieval Row actions
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… … # If we made it here we succeeded. Create our User! user = create_user_from_token(request, Token(auth_ref)) request.user = user return user
HORIZON_CONFIG = { ... 'customization_module': 'openstack_dashboard.dashboards.cloudopen.overrides', 'test_enabled': True, }
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', )
DASHBOARD = 'cloudopen' DISABLED = False ADD_INSTALLED_APPS = [ 'openstack_dashboard.dashboards.cloudopen', ]
DASHBOARD = 'cloudopen' DISABLED = False ADD_INSTALLED_APPS = [ 'openstack_dashboard.dashboards.cloudopen', ]
PANEL = 'test' PANEL_DASHBOARD = 'cloudopen' PANEL_GROUP = 'tests' ADD_PANEL = \ 'openstack_dashboard.dashboards.cloudopen.test.panel.Tests'
PANEL = 'test' PANEL_DASHBOARD = 'cloudopen' PANEL_GROUP = 'tests' ADD_PANEL = \ 'openstack_dashboard.dashboards.cloudopen.test.panel.Tests'
PANEL = 'test' PANEL_DASHBOARD = 'cloudopen' PANEL_GROUP = 'overview' ADD_PANEL = \ 'openstack_dashboard.dashboards.cloudopen.test.panel.Tests'
<!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>
{% 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 %}
Home button Project selector Simplified Nav Context-driven Admin Panel
Instance locking
Hypervisor Actions Controller Page
OPENSTACK THAT JUST WORKS
“Full” dataset search Cache up to 1K records client-side “Full” pagination
Updates every 5s Increased platform visibility Every node instrumented
Up to 1 year of data Increased platform visibility Every node instrumented Convenient access
OPENSTACK THAT JUST WORKS
OPENSTACK THAT JUST WORKS
David Lapsley @devlaps, david.lapsley@metacloud.com