summaryrefslogtreecommitdiff
path: root/src/views/_sila/Operations/Kvm/KvmConsole.vue
diff options
context:
space:
mode:
Diffstat (limited to 'src/views/_sila/Operations/Kvm/KvmConsole.vue')
-rw-r--r--src/views/_sila/Operations/Kvm/KvmConsole.vue170
1 files changed, 170 insertions, 0 deletions
diff --git a/src/views/_sila/Operations/Kvm/KvmConsole.vue b/src/views/_sila/Operations/Kvm/KvmConsole.vue
new file mode 100644
index 00000000..c028a9fc
--- /dev/null
+++ b/src/views/_sila/Operations/Kvm/KvmConsole.vue
@@ -0,0 +1,170 @@
+<template>
+ <div :class="marginClass">
+ <div ref="toolbar" class="kvm-toolbar">
+ <b-row class="d-flex">
+ <b-col class="d-flex flex-column justify-content-end" cols="4">
+ <dl class="mb-2" sm="2" md="2">
+ <dt class="d-inline font-weight-bold mr-1">
+ {{ $t('pageKvm.status') }}:
+ </dt>
+ <dd class="d-inline">
+ <status-icon :status="serverStatusIcon" />
+ <span class="d-none d-md-inline"> {{ serverStatus }}</span>
+ </dd>
+ </dl>
+ </b-col>
+
+ <b-col class="d-flex justify-content-end pr-1">
+ <b-button
+ v-if="isConnected"
+ variant="link"
+ type="button"
+ @click="sendCtrlAltDel"
+ >
+ <icon-arrow-down />
+ {{ $t('pageKvm.buttonCtrlAltDelete') }}
+ </b-button>
+ <b-button
+ v-if="!isFullWindow"
+ variant="link"
+ type="button"
+ @click="openConsoleWindow()"
+ >
+ <icon-launch />
+ {{ $t('pageKvm.openNewTab') }}
+ </b-button>
+ </b-col>
+ </b-row>
+ </div>
+ <div id="terminal-kvm" ref="panel" :class="terminalClass"></div>
+ </div>
+</template>
+
+<script>
+import RFB from '@novnc/novnc/core/rfb';
+import StatusIcon from '@/components/Global/StatusIcon';
+import IconLaunch from '@carbon/icons-vue/es/launch/20';
+import IconArrowDown from '@carbon/icons-vue/es/arrow--down/16';
+import { throttle } from 'lodash';
+
+const Connecting = 0;
+const Connected = 1;
+const Disconnected = 2;
+
+export default {
+ name: 'KvmConsole',
+ components: { StatusIcon, IconLaunch, IconArrowDown },
+ props: {
+ isFullWindow: {
+ type: Boolean,
+ default: true,
+ },
+ },
+ data() {
+ return {
+ rfb: null,
+ isConnected: false,
+ terminalClass: this.isFullWindow ? 'full-window' : '',
+ marginClass: this.isFullWindow ? 'margin-left-full-window' : '',
+ status: Connecting,
+ convasRef: null,
+ resizeKvmWindow: null,
+ };
+ },
+ computed: {
+ serverStatusIcon() {
+ if (this.status === Connected) {
+ return 'success';
+ } else if (this.status === Disconnected) {
+ return 'danger';
+ }
+ return 'secondary';
+ },
+ serverStatus() {
+ if (this.status === Connected) {
+ return this.$t('pageKvm.connected');
+ } else if (this.status === Disconnected) {
+ return this.$t('pageKvm.disconnected');
+ }
+ return this.$t('pageKvm.connecting');
+ },
+ },
+ mounted() {
+ this.openTerminal();
+ },
+ beforeDestroy() {
+ window.removeEventListener('resize', this.resizeKvmWindow);
+ this.closeTerminal();
+ },
+ methods: {
+ sendCtrlAltDel() {
+ this.rfb.sendCtrlAltDel();
+ },
+ closeTerminal() {
+ this.rfb.disconnect();
+ this.rfb = null;
+ },
+ 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;
+ this.rfb.clipViewport = true;
+ const that = this;
+
+ this.resizeKvmWindow = throttle(() => {
+ setTimeout(that.setWidthToolbar, 0);
+ }, 1000);
+ window.addEventListener('resize', this.resizeKvmWindow);
+
+ this.rfb.addEventListener('connect', () => {
+ that.isConnected = true;
+ that.status = Connected;
+ that.setWidthToolbar();
+ });
+
+ this.rfb.addEventListener('disconnect', () => {
+ this.isConnected = false;
+ that.status = Disconnected;
+ });
+ },
+ setWidthToolbar() {
+ if (
+ this.$refs.panel.children &&
+ this.$refs.panel.children.length > 0 &&
+ this.$refs.panel.children[0].children.length > 0
+ ) {
+ this.$refs.toolbar.style.width =
+ this.$refs.panel.children[0].children[0].clientWidth - 10 + 'px';
+ }
+ },
+ openConsoleWindow() {
+ window.open(
+ '#/console/kvm',
+ '_blank',
+ 'directories=no,titlebar=no,toolbar=no,location=no,status=no,menubar=no,scrollbars=no,resizable=yes,width=700,height=550'
+ );
+ },
+ },
+};
+</script>
+
+<style scoped lang="scss">
+.button-ctrl-alt-delete {
+ float: right;
+}
+
+.kvm-status {
+ padding-top: $spacer / 2;
+ padding-left: $spacer / 4;
+ display: inline-block;
+}
+
+.margin-left-full-window {
+ margin-left: 5px;
+}
+</style>