diff options
author | Mateusz Gapski <mateuszx.gapski@intel.com> | 2020-07-09 10:21:33 +0300 |
---|---|---|
committer | Derick Montague <derick.montague@ibm.com> | 2020-07-22 01:04:15 +0300 |
commit | 632de22a066e7a1224d2c490962530389273c717 (patch) | |
tree | 6452cd27736c1979f243b8a02d1996bac6c8dc3d | |
parent | 2c98b0954ac5c50ea9c77e9ee780e3dee4fcdad8 (diff) | |
download | webui-vue-632de22a066e7a1224d2c490962530389273c717.tar.xz |
KVM console
- The kvm console with using novnc library
Signed-off-by: Mateusz Gapski <mateuszx.gapski@intel.com>
Change-Id: Icfb7643595d8c17231ca3671753d6de971525bd3
-rw-r--r-- | package-lock.json | 5 | ||||
-rw-r--r-- | package.json | 1 | ||||
-rw-r--r-- | src/components/AppNavigation/AppNavigation.vue | 3 | ||||
-rw-r--r-- | src/locales/en-US.json | 11 | ||||
-rw-r--r-- | src/router/index.js | 20 | ||||
-rw-r--r-- | src/views/Control/Kvm/Kvm.vue | 56 | ||||
-rw-r--r-- | src/views/Control/Kvm/KvmConsole.vue | 74 | ||||
-rw-r--r-- | src/views/Control/Kvm/index.js | 2 |
8 files changed, 170 insertions, 2 deletions
diff --git a/package-lock.json b/package-lock.json index f99d5165..72167091 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1527,6 +1527,11 @@ "fastq": "^1.6.0" } }, + "@novnc/novnc": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@novnc/novnc/-/novnc-1.2.0.tgz", + "integrity": "sha512-FaUckOedGhSbwQBXk/KGyxKt9ngskg4wPw6ghbHWXOUEmQscAZr3467lTU5DSfppwHJt5k+lQiHoeYUuY90l2Q==" + }, "@nuxt/opencollective": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/@nuxt/opencollective/-/opencollective-0.3.0.tgz", diff --git a/package.json b/package.json index 8c90675e..9942f12d 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,7 @@ }, "dependencies": { "@carbon/icons-vue": "10.6.1", + "@novnc/novnc": "1.2.0", "axios": "0.19.0", "bootstrap": "4.4.1", "bootstrap-vue": "2.12.0", diff --git a/src/components/AppNavigation/AppNavigation.vue b/src/components/AppNavigation/AppNavigation.vue index 37f0f717..2b773a04 100644 --- a/src/components/AppNavigation/AppNavigation.vue +++ b/src/components/AppNavigation/AppNavigation.vue @@ -34,6 +34,9 @@ <icon-expand class="icon-expand" /> </b-button> <b-collapse id="control-menu" tag="ul" class="nav-item__nav"> + <b-nav-item to="/control/kvm"> + {{ $t('appNavigation.kvm') }} + </b-nav-item> <b-nav-item to="/control/manage-power-usage"> {{ $t('appNavigation.managePowerUsage') }} </b-nav-item> diff --git a/src/locales/en-US.json b/src/locales/en-US.json index 02600f4c..e6c508b2 100644 --- a/src/locales/en-US.json +++ b/src/locales/en-US.json @@ -79,6 +79,7 @@ "firmware": "@:appPageTitle.firmware", "hardwareStatus": "@:appPageTitle.hardwareStatus", "health": "Health", + "kvm": "@:appPageTitle.kvm", "ldap": "@:appPageTitle.ldap", "localUserManagement": "@:appPageTitle.localUserManagement", "managePowerUsage": "@:appPageTitle.managePowerUsage", @@ -99,6 +100,7 @@ "eventLogs": "Event logs", "firmware": "Firmware", "hardwareStatus": "Hardware status", + "kvm": "KVM", "ldap": "LDAP", "localUserManagement": "Local user management", "login": "Login", @@ -198,6 +200,15 @@ "uuid": "UUID" } }, + "pageKvm": { + "openNewTab": "Open in new tab", + "subTitle": "Access the KVM console", + "buttonCtrlAltDelete": "Send Ctrl+Alt+Delete", + "status": "Status", + "connected": "Connected", + "connecting": "Connecting", + "disconnected": "Disconnected" + }, "pageLdap": { "pageDescription": "Configure LDAP settings and manage role groups", "roleGroups": "Role groups", diff --git a/src/router/index.js b/src/router/index.js index 0da37fa8..eace2bb6 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -90,6 +90,14 @@ const routes = [ } }, { + path: '/control/kvm', + name: 'kvm', + component: () => import('@/views/Control/Kvm'), + meta: { + title: 'appPageTitle.kvm' + } + }, + { path: '/control/manage-power-usage', name: 'manage-power-usage', component: () => import('@/views/Control/ManagePowerUsage'), @@ -178,13 +186,21 @@ const routes = [ }, children: [ { - path: '/console/serial-over-lan-console', - name: 'serial-over-lan', + path: 'serial-over-lan-console', + name: 'serial-over-lan-console', component: () => import('@/views/Control/SerialOverLan/SerialOverLanConsole'), meta: { title: 'appPageTitle.serialOverLan' } + }, + { + path: 'kvm', + name: 'kvm-console', + component: () => import('@/views/Control/Kvm/KvmConsole'), + meta: { + title: 'appPageTitle.kvm' + } } ] } diff --git a/src/views/Control/Kvm/Kvm.vue b/src/views/Control/Kvm/Kvm.vue new file mode 100644 index 00000000..195948b0 --- /dev/null +++ b/src/views/Control/Kvm/Kvm.vue @@ -0,0 +1,56 @@ +<template> + <b-container fluid="xl"> + <page-title /> + + <page-section :section-title="$t('pageKvm.subTitle')"> + <div> + <b-button + variant="link" + type="button" + class="button-launch" + @click="openConsoleWindow()" + > + <icon-launch /> + {{ $t('pageKvm.openNewTab') }} + </b-button> + </div> + <div class="terminal-container"> + <kvm-console /> + </div> + </page-section> + </b-container> +</template> + +<script> +import IconLaunch from '@carbon/icons-vue/es/launch/32'; +import PageTitle from '@/components/Global/PageTitle'; +import PageSection from '@/components/Global/PageSection'; +import KvmConsole from './KvmConsole'; + +export default { + name: 'Kvm', + components: { IconLaunch, PageSection, PageTitle, KvmConsole }, + methods: { + openConsoleWindow() { + window.open( + '#/console/kvm', + '_blank', + 'directories=no,titlebar=no,toolbar=no,location=no,status=no,menubar=no,scrollbars=no,resizable=yes,width=600,height=550' + ); + } + } +}; +</script> + +<style scoped> +.button-launch > svg { + height: 25px; +} +.button-launch { + padding-left: 0px; +} + +.terminal-container { + width: 100%; +} +</style> diff --git a/src/views/Control/Kvm/KvmConsole.vue b/src/views/Control/Kvm/KvmConsole.vue new file mode 100644 index 00000000..080f72e8 --- /dev/null +++ b/src/views/Control/Kvm/KvmConsole.vue @@ -0,0 +1,74 @@ +<template> + <div> + <span class="kvm-status">{{ $t('pageKvm.status') }}: {{ status }}</span> + <b-button + v-if="isConnected" + variant="link" + type="button" + class="button-launch button-ctrl-alt-delete" + @click="sendCtrlAltDel" + > + {{ $t('pageKvm.buttonCtrlAltDelete') }} + </b-button> + <div v-show="isConnected" id="terminal" ref="panel"></div> + </div> +</template> + +<script> +import RFB from '@novnc/novnc/core/rfb'; + +export default { + name: 'KvmConsole', + data() { + return { + rfb: null, + isConnected: false, + status: this.$t('pageKvm.connecting') + }; + }, + mounted() { + this.openTerminal(); + }, + methods: { + sendCtrlAltDel() { + this.rfb.sendCtrlAltDel(); + }, + openTerminal() { + const token = this.$store.getters['authentication/token']; + this.rfb = new RFB( + this.$refs.panel, + `wss://${window.location.host}/kvm/0`, + { wsProtocols: [token] } + ); + + this.rfb.scaleViewport = true; + const that = this; + this.rfb.addEventListener('connect', () => { + that.isConnected = true; + that.status = this.$t('pageKvm.connected'); + }); + + this.rfb.addEventListener('disconnect', () => { + that.status = this.$t('pageKvm.disconnected'); + }); + } + } +}; +</script> + +<style scoped lang="scss"> +@import 'src/assets/styles/helpers'; +#terminal { + height: calc(100vh - 42px); +} + +.button-ctrl-alt-delete { + float: right; +} + +.kvm-status { + padding-top: $spacer / 2; + padding-left: $spacer / 4; + display: inline-block; +} +</style> diff --git a/src/views/Control/Kvm/index.js b/src/views/Control/Kvm/index.js new file mode 100644 index 00000000..ac4f9667 --- /dev/null +++ b/src/views/Control/Kvm/index.js @@ -0,0 +1,2 @@ +import Kvm from './Kvm.vue'; +export default Kvm; |