From a129c4e92eebd03772e5f68a2fcf855e00874f19 Mon Sep 17 00:00:00 2001 From: Ed tanous Date: Sun, 22 Apr 2018 10:53:28 -0700 Subject: [PATCH] Implement KVM in webui This patchset adds the infrastructure to allow KVM sessions through the webui. A websocket capable VNC/RFB connection on the BMC is needed for KVM sessions. To access, navigate to Server control -> KVM. Tested: Ran obmc-ikvm on the BMC, added a KVM Handler to Phosphor Rest Server, and was able to establish a KVM session in the webui on a Witherspoon. Change-Id: I7dda5bec41d270ae8d0913697714d4df4ec3a257 Signed-off-by: Ed Tanous Signed-off-by: Gunnar Mills --- app/common/directives/app-navigation.html | 12 +++-- app/index.js | 1 + app/server-control/controllers/kvm-controller.html | 5 ++ app/server-control/controllers/kvm-controller.js | 55 ++++++++++++++++++++++ app/server-control/index.js | 5 ++ app/server-control/styles/index.scss | 1 + app/server-control/styles/kvm.scss | 11 +++++ package-lock.json | 5 ++ package.json | 5 +- webpack.config.js | 6 ++- 10 files changed, 98 insertions(+), 8 deletions(-) create mode 100644 app/server-control/controllers/kvm-controller.html create mode 100644 app/server-control/controllers/kvm-controller.js create mode 100644 app/server-control/styles/kvm.scss diff --git a/app/common/directives/app-navigation.html b/app/common/directives/app-navigation.html index 2f3ded76cad2..f8b5db742acc 100644 --- a/app/common/directives/app-navigation.html +++ b/app/common/directives/app-navigation.html @@ -85,19 +85,21 @@ Reboot BMC
  • Serial over LAN console
  • +
  • + KVM
  • diff --git a/app/index.js b/app/index.js index c9fed83fe4a9..d6b4a08fa5c6 100644 --- a/app/index.js +++ b/app/index.js @@ -69,6 +69,7 @@ import power_operations_controller from './server-control/controllers/power-oper import power_usage_controller from './server-control/controllers/power-usage-controller.js'; import remote_console_window_controller from './server-control/controllers/remote-console-window-controller.js'; import server_led_controller from './server-control/controllers/server-led-controller.js'; +import kvm_controller from './server-control/controllers/kvm-controller.js'; import server_health_index from './server-health/index.js'; import inventory_overview_controller from './server-health/controllers/inventory-overview-controller.js'; diff --git a/app/server-control/controllers/kvm-controller.html b/app/server-control/controllers/kvm-controller.html new file mode 100644 index 000000000000..40e4d97454bc --- /dev/null +++ b/app/server-control/controllers/kvm-controller.html @@ -0,0 +1,5 @@ +
    +
    +
    +
    +
    diff --git a/app/server-control/controllers/kvm-controller.js b/app/server-control/controllers/kvm-controller.js new file mode 100644 index 000000000000..a43f169ddf19 --- /dev/null +++ b/app/server-control/controllers/kvm-controller.js @@ -0,0 +1,55 @@ +/** + * Controller for KVM (Kernel-based Virtual Machine) + * + * @module app/serverControl + * @exports kvmController + * @name kvmController + */ + +import RFB from '@novnc/novnc/core/rfb.js'; + +window.angular && (function(angular) { + 'use strict'; + + angular.module('app.serverControl').controller('kvmController', [ + '$scope', '$location', '$log', + function($scope, $location, $log) { + var rfb; + + $scope.$on('$destroy', function() { + if (rfb) { + rfb.disconnect(); + } + }); + + function sendCtrlAltDel() { + rfb.sendCtrlAltDel(); + return false; + }; + + function connected(e) { + $log.debug('RFB Connected'); + } + function disconnected(e) { + $log.debug('RFB disconnected'); + } + + var host = $location.host(); + var port = $location.port(); + var target = + angular.element(document.querySelector('#noVNC_container'))[0]; + + try { + rfb = new RFB(target, 'wss://' + host + ':' + port + '/kvm/0', {}); + + rfb.addEventListener('connect', connected); + rfb.addEventListener('disconnect', disconnected); + } catch (exc) { + $log.error(exc); + updateState( + null, 'fatal', null, 'Unable to create RFB client -- ' + exc); + return; // don't continue trying to connect + }; + } + ]); +})(angular); diff --git a/app/server-control/index.js b/app/server-control/index.js index 739bd1eb8ad9..1b8aad50b702 100644 --- a/app/server-control/index.js +++ b/app/server-control/index.js @@ -48,6 +48,11 @@ window.angular && (function(angular) { 'controller': 'remoteConsoleWindowController', authenticated: true }) + .when('/server-control/kvm', { + 'template': require('./controllers/kvm-controller.html'), + 'controller': 'kvmController', + authenticated: true + }) .when('/server-control', { 'template': require('./controllers/power-operations-controller.html'), diff --git a/app/server-control/styles/index.scss b/app/server-control/styles/index.scss index f6b15ab6afc9..5e8a99580894 100644 --- a/app/server-control/styles/index.scss +++ b/app/server-control/styles/index.scss @@ -3,3 +3,4 @@ @import "./remote-console.scss"; @import "./server-led.scss"; @import "./power-usage.scss"; +@import "./kvm.scss"; diff --git a/app/server-control/styles/kvm.scss b/app/server-control/styles/kvm.scss new file mode 100644 index 000000000000..2f9e2c0c9f37 --- /dev/null +++ b/app/server-control/styles/kvm.scss @@ -0,0 +1,11 @@ + +.noNVC_shown { + display: inline; +} +.noVNC_hidden { + display: none; +} + +#noVNC_left_dummy_elem { + flex: 1; +} diff --git a/package-lock.json b/package-lock.json index 2d9d31b21968..103c9b84b933 100644 --- a/package-lock.json +++ b/package-lock.json @@ -807,6 +807,11 @@ "to-fast-properties": "2.0.0" } }, + "@novnc/novnc": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@novnc/novnc/-/novnc-1.0.0.tgz", + "integrity": "sha1-drDonm+HOMqBVBlbr1uOaoC8kQU=" + }, "@types/node": { "version": "10.12.18", "resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.18.tgz", diff --git a/package.json b/package.json index 35c6b78e320c..c0125a0b72fd 100644 --- a/package.json +++ b/package.json @@ -28,8 +28,9 @@ "node" ], "dependencies": { - "angular": "^1.7.5", - "angular-animate": "^1.7.5", + "@novnc/novnc": "^1.0.0", + "angular": "^1.7.3", + "angular-animate": "^1.7.3", "angular-clipboard": "^1.6.2", "angular-cookies": "^1.7.5", "angular-messages": "^1.7.6", diff --git a/webpack.config.js b/webpack.config.js index 91cbea8f2952..6c8667cbbc98 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -113,7 +113,11 @@ module.exports = (env, options) => { 'base-uri': '\'self\'', 'object-src': '\'none\'', 'script-src': ['\'self\''], - 'style-src': ['\'self\''] + 'style-src': ['\'self\''], + // KVM requires image buffers from data: payloads, so allow that in + // img-src + // https://stackoverflow.com/questions/18447970/content-security-policy-data-not-working-for-base64-images-in-chrome-28 + 'img-src': ['\'self\'', 'data:'], }), new MiniCssExtractPlugin(), -- 2.7.4