20141002 delapsley-socalangularjs-final

81
Enhancing OpenStack Horizon with AngularJS #socalangularjs David Lapsley @devlaps, [email protected] October 2, 2014

Upload: david-lapsley

Post on 26-May-2015

189 views

Category:

Internet


2 download

DESCRIPTION

The OpenStack project was launched by Rackspace and NASA in July 2010. Since then it has gained considerable momentum, with over 200 companies joining the project. The OpenStack Horizon project provides a highly extensible web-based User Interface to OpenStack services. However, in the time since Horizon was first architected, there have been major advances in the design and best practices for web applications. In particular, the use of more sophisticated and robust client-side javascript frameworks have come to the fore. These frameworks provide a much more responsive user experience and much cleaner separation between the client and server. They also enable configuration driven interfaces, facilitate more modular testing, and can facilitate shorter development cycles, more testable software, and above all, a better user experience. In this presentation, we share some of our recent work in re-architecting parts of Horizon to take advantage of these new technologies. We will provide a brief introduction of OpenStack and Horizon, describe the recent work we have done, and then delve into architectural details and code examples of our recent work.

TRANSCRIPT

Page 1: 20141002 delapsley-socalangularjs-final

Enhancing OpenStack Horizon with AngularJS

#socalangularjs

David Lapsley@devlaps, [email protected]

October 2, 2014

Page 2: 20141002 delapsley-socalangularjs-final

OpenStack Horizon in Action

Page 3: 20141002 delapsley-socalangularjs-final

Launching an Instance

Page 4: 20141002 delapsley-socalangularjs-final

Admin Overview

Page 5: 20141002 delapsley-socalangularjs-final

Project Overview

Page 6: 20141002 delapsley-socalangularjs-final

Launching an Instance

Page 7: 20141002 delapsley-socalangularjs-final

Launching an Instance

Page 8: 20141002 delapsley-socalangularjs-final

Launching an Instance

Page 9: 20141002 delapsley-socalangularjs-final

Launching an Instance

Page 10: 20141002 delapsley-socalangularjs-final

Launching an Instance

Page 11: 20141002 delapsley-socalangularjs-final

Launching an Instance

Page 12: 20141002 delapsley-socalangularjs-final

OpenStack CloudsArchitecture and Model

Page 13: 20141002 delapsley-socalangularjs-final

Cloud Computing Model

Page 14: 20141002 delapsley-socalangularjs-final

Virtualization

Page 15: 20141002 delapsley-socalangularjs-final

OpenStack● Open Source Cloud Platformo Build public/private cloudso Multi-tenanto Virtual machines on demando Storage volumes

● Founded in 2010 by Rackspace and NASA● Since then, enormous growth…

Page 16: 20141002 delapsley-socalangularjs-final

Some interesting OpenStack facts …

Page 17: 20141002 delapsley-socalangularjs-final

OpenStack Source Code

Page 18: 20141002 delapsley-socalangularjs-final

OpenStack Source Code

Page 19: 20141002 delapsley-socalangularjs-final

OpenStack Contributors

Page 20: 20141002 delapsley-socalangularjs-final

19,410 People144 Countries

http://www.openstack.org

Page 21: 20141002 delapsley-socalangularjs-final

“Linux for the Cloud”

Page 22: 20141002 delapsley-socalangularjs-final

OpenStack Model

http://docs.openstack.org/openstack-ops/content/example_architecture.html

http://docs.openstack.org/training-guides/content/module001-ch004-openstack-architecture.html

Page 23: 20141002 delapsley-socalangularjs-final

OpenStack Projects

● Compute (Nova)

● Network (Nova, Neutron)

● VM Registration (Glance)

● Identity (Keystone)

● Object Storage (Swift, …)

● Block Storage (Cinder)

● Dashboard (Horizon)

Page 24: 20141002 delapsley-socalangularjs-final

OpenStack HorizonArchitecture

Page 25: 20141002 delapsley-socalangularjs-final

Horizon Overview

● Django-based application deployed via

Apache and WSGI

● Provides access to OpenStack services

● Leverages existing technologieso Bootstrap, jQuery, Underscore.js,

AngularJS, D3.js, Rickshaw, LESS CSS

● Extends Django to enhance

extensibility

Page 26: 20141002 delapsley-socalangularjs-final

Django Stack

Page 27: 20141002 delapsley-socalangularjs-final

Horizon Stack

Page 28: 20141002 delapsley-socalangularjs-final

Horizon UINav entries

Column sorting

Linking

RPCData retrieval

Row actions

Table actionsFiltering

Multi-select

Page 29: 20141002 delapsley-socalangularjs-final

Customized UI

Page 30: 20141002 delapsley-socalangularjs-final

AngularJS

Page 31: 20141002 delapsley-socalangularjs-final

AngularJS lets you extend HTML

vocabulary for your application. The

resulting environment is extraordinarily

expressive, readable, and quick to

develop.https://angularjs.org

Page 32: 20141002 delapsley-socalangularjs-final

Develop smaller, lighter web apps that

are simple to create and easy to test,

extend and maintain as they grow

Brad Green, Shyam Seshadri, “AngularJS”

Page 33: 20141002 delapsley-socalangularjs-final

Core concepts

● Model View Controller framework

● Client-side templates

● Data binding

● Dependency injection

Page 34: 20141002 delapsley-socalangularjs-final

Hello Worldindex.html

<html ng-app><head> <script src="angular.js"></script> <script src="controllers.js"></script></head><body> <div ng-controller='HelloController'> <p>{{greeting.text}}, World</p> <button ng-click="action()">Alert</button> </div></body></html>

controllers.js

function HelloController($scope) { $scope.greeting = { text: 'Hello' }; $scope.action = function() { alert('Action!'); };}

AngularJSBy: Brad Green; Shyam SeshadriPublisher: O'Reilly Media, Inc.Pub. Date: April 23, 2013

Page 35: 20141002 delapsley-socalangularjs-final

Hello World

Page 36: 20141002 delapsley-socalangularjs-final

Hello World

Page 37: 20141002 delapsley-socalangularjs-final

AngularJS + Horizon

Page 38: 20141002 delapsley-socalangularjs-final

Horizon Stack Extended

Page 39: 20141002 delapsley-socalangularjs-final

Adding a new PanelUsing current Horizon

Page 40: 20141002 delapsley-socalangularjs-final

Dashboards & Panels

● Horizon provides a flexible framework

for creating Dashboards and Panels

● Panels grouped into PanelGroups

● PanelGroups into Dashboards

Page 41: 20141002 delapsley-socalangularjs-final

Dashboard App

● Dashboards created as Django

Applications

● Dashboard modules partitioned into:o statico templateso python modules

Page 42: 20141002 delapsley-socalangularjs-final

Directory Structuresocalangularjs/ __init__.py dashboard.py templates/

socalangularjs/ static/

socalangularjs/ css/ img/ js/

Page 43: 20141002 delapsley-socalangularjs-final

_10_socalangularjs.py

DASHBOARD = 'socalangularjs'

DISABLED = False

ADD_INSTALLED_APPS = [

'openstack_dashboard.dashboards.socalangularjs',

]

Page 44: 20141002 delapsley-socalangularjs-final

dashboard.pyclass BasePanelGroup(horizon.PanelGroup): slug = "overview" name = _("Overview") panels = ("hypervisors",)

class OpenstackOC(horizon.Dashboard): name = _(”SoCalAngularJS") slug = ”SoCalAngularJS" panels = (BasePanelGroup,) default_panel = "hypervisors" roles = ("admin",)

horizon.register(SoCalAngularJS)

Page 45: 20141002 delapsley-socalangularjs-final

DashboardDashboard

PanelGroup

Page 46: 20141002 delapsley-socalangularjs-final

Panel● Panels are created as Python Modules● Panel modules partitioned into:o static/o templates/o python modules:

urls.py, views.py, panel.pytables.py, forms.py, tabs.py, tests.py

Page 47: 20141002 delapsley-socalangularjs-final

Directory Structuresocalangularjs/ hypervisors/

__init__.py panel.py urls.py views.py

tests.py tables.py templates/

socalangularjs/ hypervisors/ index.html static/

socalangularjs/ hypervisors /

Page 48: 20141002 delapsley-socalangularjs-final

panel.py

from django.utils.translation import ugettext_lazy as _ import horizon from openstack_dashboard.dashboards.socalangularjs import dashboard class Hypervisors(horizon.Panel): name = _("Hypervisors") slug = 'hypervisors' dashboard.socalangularjs.register(Hypervisors)

Page 49: 20141002 delapsley-socalangularjs-final

DashboardDashboard

PanelGroup

Panel

Page 50: 20141002 delapsley-socalangularjs-final

View Module● View module ties together everything:o Tables, Templates, API Calls

● Horizon base views:o APIView, LoginView, MultiTableView,

DataTableView, MixedDataTableView, TabView,

TabbedTableView, WorkflowView

Page 51: 20141002 delapsley-socalangularjs-final

views.py

from horizon import tables

class HypervisorsIndexView(tables.DataTableView): table_class = hv_tables.AdminHypervisorsTable template_name = ’socalangularjs/hypervisors/index.html’

def get_data(self): hypervisors = [] states = {} hypervisors = api.nova.hypervisor_list(self.request) … return hypervisors

Page 52: 20141002 delapsley-socalangularjs-final

Table Module● Table classes provide framework for tables: o consistent look and feelo configurable table_actions and

row_actionso select/multi-select columno sortingo pagination

● Functionality is split server- and client-side

Page 53: 20141002 delapsley-socalangularjs-final

tables.pyclass 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)

Page 54: 20141002 delapsley-socalangularjs-final

tables.pyclass 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)

Page 55: 20141002 delapsley-socalangularjs-final

Template

● Standard Django template format

● Typically leverage base horizon

templates (e.g. base.html)

Page 56: 20141002 delapsley-socalangularjs-final

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 %}<div class="quota-dynamic"> <h3>{% trans "Hypervisor Summary" %}</h3> <div class="d3_quota_bar"> <div class="d3_pie_chart" …></div> </div> …</div><div class="row-fluid"> <div class="col-sm-12"> {{ tab_group.render }} </div></div>{% endblock %}

Page 57: 20141002 delapsley-socalangularjs-final

URLs Modules● Provides URL to View mappings

Page 58: 20141002 delapsley-socalangularjs-final

urls.py

from django.conf.urls import patterns from django.conf.urls import url

from openstack_dashboard.dashboards.socalangularjs.hypervisors import views

urlpatterns = patterns( 'openstack_dashboard.dashboards.socalangularjs.hypervisors.views' url(r'^$', views.IndexView.as_view(), name='index'),)

Page 59: 20141002 delapsley-socalangularjs-final

Completed DashboardNav entries

Column sorting

Panel rendering

Linking

RPCData retrieval

Page 60: 20141002 delapsley-socalangularjs-final

Adding a new Panelwith AngularJS

Page 61: 20141002 delapsley-socalangularjs-final

Directory Structuresocalangularjs/ hypervisors/

__init__.py panel.py urls.py views.py

tables.py tests.py templates/socalangularjs/hypervisors/ index.html static/socalangularjs/hypervisors/js/ hypervisors-controller.jsrest/nova/ __init__.py hypervisor.py instance.py

Page 62: 20141002 delapsley-socalangularjs-final

REST Resource● Provides the source of data via RESTful API

● Resource includes/provides:o entity data/stateo configurable table_actions and

row_actionso sortingo paginationo CRUD operations

Page 63: 20141002 delapsley-socalangularjs-final

hypervisors.pyclass HypervisorResource(resource.BaseNovaResource):

pk = fields.CharField(attribute="pk", _("Primary Key"), hidden=True) hypervisor_hostname = fields.CharField(attribute='hypervisor_hostname', sortable=True, searchable=True) … actions = fields.ActionsField(attribute='actions', actions=[HypervisorViewLiveStats, HypervisorEnableAction, HypervisorDisableAction], title=_("Actions"), sortable=True) class Meta: authorization = auth.RestAuthorization() list_allowed_methods = ['get'] resource_name = '^hypervisor' field_order = ['pk', 'hypervisor_hostname', 'hypervisor_type', 'vcpus', 'vcpus_used', 'memory_mb', 'memory_mb_used', 'running_vms', 'state', 'status', 'actions']

Page 64: 20141002 delapsley-socalangularjs-final

Controller

● Controls view logic

Page 65: 20141002 delapsley-socalangularjs-final

hypervisor-controller.jshorizonApp.controller('TableController', function($scope, $http) { $scope.headers = headers; $scope.title = title; $http.get('/rest/api/v1/nova/instance/').success( function(data, status, headers, config) { $scope.instances = transform(data.objects); }); });

horizonApp.controller('ActionDropdownController', function($scope) { $scope.status = { isopen: false }; $scope.toggleDropdown = function($event) { $event.preventDefault(); $event.stopPropagation(); $scope.status.isopen = !$scope.status.isopen; }; $scope.action = function(action, id) { // Perform action. }; … });

Page 66: 20141002 delapsley-socalangularjs-final

View

● In AngularJS, view is defined in the

HTML template

Page 67: 20141002 delapsley-socalangularjs-final

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 %}

Page 68: 20141002 delapsley-socalangularjs-final

index.html

<div ng-controller="TableController"> <table class="..."> <thead> <tr class="..."> <th class="..."> <h3 class="...">{$ title $}</h3> </th> </tr> <tr class="..."> <th class="..." ng-repeat='header in headers'> <div class="...">{$ header.name $}</div> </th> </tr> </thead>

Page 69: 20141002 delapsley-socalangularjs-final

index.html <tr ng-repeat="instance in instances"> <td ng-repeat="datum in instance.data">{$ datum $}</td> <td class="..."> <div ng-controller="ActionDropdownController"> <div class="..." dropdown> <button class="..." ng-click="action(instance.actions[0], instance.name)"> {$ instance.actions[0].verbose_name $} </button> ... <div class="..."> <li class="..." ng-repeat="action in instance.actions"> <a href="#" class="..." ng-click="$parent.action(action,parent.instance.name)"> {$ action.verbose_name $} </a> </li> </ul> </div> </td> </tr> </table>

Page 70: 20141002 delapsley-socalangularjs-final

Advantages

● Clean split between server and client

side

● Significantly cleaner, terser, easier to

understand client-side code

● Significant easier to improve UX

● Client- and server-side code can be

developed and tested independently

● Faster feature velocity

Page 71: 20141002 delapsley-socalangularjs-final

AngularJS + Horizon in Production

Page 72: 20141002 delapsley-socalangularjs-final

Client-side Rendering

“Full” dataset search

Cache up to 1K records client-side

“Full” pagination

Page 73: 20141002 delapsley-socalangularjs-final

Real-time Data Updates every 5s

Increased platform visibility

Every node instrumented

Page 74: 20141002 delapsley-socalangularjs-final

Historical MetricsUp to 1 year of

data

Increased platform visibility

Every node instrumented

Convenient access

Page 75: 20141002 delapsley-socalangularjs-final

OpenStack HorizonContributing

Page 76: 20141002 delapsley-socalangularjs-final

Devstack and Contributing● Devstack:o “A documented shell script to build complete

OpenStack development environments.”o http://devstack.org

● Contributing to Horizon:

– http://docs.openstack.org/developer/

horizon/contributing.html

Page 77: 20141002 delapsley-socalangularjs-final

References• IRC channels (freenode.net)

– #openstack-dev

– #openstack-horizon

– #openstack-meeting

• Web:

– http://docs.openstack.org/developer/horizon/

– https://launchpad.net/horizon

– http://devstack.org

– https://github.com/openstack

– https://github.com/openstack/horizon

– http://docs.openstack.org/developer/horizon/

– http://docs.openstack.org/developer/horizon/topics/settings.html

– https://wiki.openstack.org/wiki/Gerrit_Workflow

Page 78: 20141002 delapsley-socalangularjs-final

References● Web:o http://www.stackalytics.como http://activity.openstack.org/dash/browser/o http://gabrielhurley.github.io/slides/

openstack/building_on_horizon/o http://www.solinea.com/blog/openstack-

grizzly-architecture-revisited

Page 79: 20141002 delapsley-socalangularjs-final

Thank You

David Lapsley@devlaps, [email protected]

Page 80: 20141002 delapsley-socalangularjs-final

If this sounds interesting…

http://jobs.metacloud.com

We are hiring!

Page 81: 20141002 delapsley-socalangularjs-final