blob: 62dd47ad1329cccb367420e33138d5de5b0acb90 [file] [log] [blame]
Mateusz Gapski632de222020-07-09 09:21:33 +02001<template>
Mateusz Gapski96b37af2020-09-04 14:11:55 +02002 <div :class="marginClass">
3 <div ref="toolbar" class="kvm-toolbar">
4 <b-row class="d-flex">
5 <b-col class="d-flex flex-column justify-content-end" cols="4">
6 <dl class="mb-2" sm="2" md="2">
7 <dt class="d-inline font-weight-bold mr-1">
8 {{ $t('pageKvm.status') }}:
9 </dt>
10 <dd class="d-inline">
Derick Montague71114fe2021-05-06 18:17:34 -050011 <status-icon :status="serverStatusIcon" />
12 <span class="d-none d-md-inline"> {{ serverStatus }}</span>
Mateusz Gapski96b37af2020-09-04 14:11:55 +020013 </dd>
14 </dl>
15 </b-col>
16
Dixsie Wolmers30f11f82020-11-10 16:07:56 -060017 <b-col class="d-flex justify-content-end pr-1">
Mateusz Gapski96b37af2020-09-04 14:11:55 +020018 <b-button
19 v-if="isConnected"
20 variant="link"
21 type="button"
Mateusz Gapski96b37af2020-09-04 14:11:55 +020022 @click="sendCtrlAltDel"
23 >
Dixsie Wolmers30f11f82020-11-10 16:07:56 -060024 <icon-arrow-down />
Mateusz Gapski96b37af2020-09-04 14:11:55 +020025 {{ $t('pageKvm.buttonCtrlAltDelete') }}
26 </b-button>
27 <b-button
28 v-if="!isFullWindow"
29 variant="link"
30 type="button"
Mateusz Gapski96b37af2020-09-04 14:11:55 +020031 @click="openConsoleWindow()"
32 >
Dixsie Wolmers30f11f82020-11-10 16:07:56 -060033 <icon-launch />
34 {{ $t('pageKvm.openNewTab') }}
Mateusz Gapski96b37af2020-09-04 14:11:55 +020035 </b-button>
36 </b-col>
37 </b-row>
38 </div>
39 <div id="terminal-kvm" ref="panel" :class="terminalClass"></div>
Mateusz Gapski632de222020-07-09 09:21:33 +020040 </div>
41</template>
42
43<script>
44import RFB from '@novnc/novnc/core/rfb';
Mateusz Gapski96b37af2020-09-04 14:11:55 +020045import StatusIcon from '@/components/Global/StatusIcon';
46import IconLaunch from '@carbon/icons-vue/es/launch/20';
47import IconArrowDown from '@carbon/icons-vue/es/arrow--down/16';
Konstantin Aladyshev69e8ec52021-02-22 14:07:57 +030048import { throttle } from 'lodash';
Mateusz Gapski96b37af2020-09-04 14:11:55 +020049
50const Connecting = 0;
51const Connected = 1;
52const Disconnected = 2;
Mateusz Gapski632de222020-07-09 09:21:33 +020053
54export default {
55 name: 'KvmConsole',
Mateusz Gapski96b37af2020-09-04 14:11:55 +020056 components: { StatusIcon, IconLaunch, IconArrowDown },
57 props: {
58 isFullWindow: {
59 type: Boolean,
Derick Montague602e98a2020-10-21 16:20:00 -050060 default: true,
61 },
Mateusz Gapski96b37af2020-09-04 14:11:55 +020062 },
Mateusz Gapski632de222020-07-09 09:21:33 +020063 data() {
64 return {
65 rfb: null,
66 isConnected: false,
Mateusz Gapski96b37af2020-09-04 14:11:55 +020067 terminalClass: this.isFullWindow ? 'full-window' : '',
68 marginClass: this.isFullWindow ? 'margin-left-full-window' : '',
69 status: Connecting,
Derick Montague602e98a2020-10-21 16:20:00 -050070 convasRef: null,
Konstantin Aladyshev69e8ec52021-02-22 14:07:57 +030071 resizeKvmWindow: null,
Mateusz Gapski632de222020-07-09 09:21:33 +020072 };
73 },
Mateusz Gapski96b37af2020-09-04 14:11:55 +020074 computed: {
Derick Montague71114fe2021-05-06 18:17:34 -050075 serverStatusIcon() {
Mateusz Gapski96b37af2020-09-04 14:11:55 +020076 if (this.status === Connected) {
77 return 'success';
78 } else if (this.status === Disconnected) {
79 return 'danger';
80 }
81 return 'secondary';
82 },
Derick Montague71114fe2021-05-06 18:17:34 -050083 serverStatus() {
Mateusz Gapski96b37af2020-09-04 14:11:55 +020084 if (this.status === Connected) {
85 return this.$t('pageKvm.connected');
86 } else if (this.status === Disconnected) {
87 return this.$t('pageKvm.disconnected');
88 }
89 return this.$t('pageKvm.connecting');
Derick Montague602e98a2020-10-21 16:20:00 -050090 },
Mateusz Gapski96b37af2020-09-04 14:11:55 +020091 },
kirankumarb07e78d10b2023-03-03 12:10:29 +053092 created() {
93 this.$store.dispatch('global/getSystemInfo');
94 },
Mateusz Gapski632de222020-07-09 09:21:33 +020095 mounted() {
96 this.openTerminal();
97 },
Konstantin Aladyshev69e8ec52021-02-22 14:07:57 +030098 beforeDestroy() {
99 window.removeEventListener('resize', this.resizeKvmWindow);
Lei YU6641cc42021-06-18 19:22:57 +0800100 this.closeTerminal();
Konstantin Aladyshev69e8ec52021-02-22 14:07:57 +0300101 },
Mateusz Gapski632de222020-07-09 09:21:33 +0200102 methods: {
103 sendCtrlAltDel() {
104 this.rfb.sendCtrlAltDel();
105 },
Lei YU6641cc42021-06-18 19:22:57 +0800106 closeTerminal() {
107 this.rfb.disconnect();
108 this.rfb = null;
109 },
Mateusz Gapski632de222020-07-09 09:21:33 +0200110 openTerminal() {
111 const token = this.$store.getters['authentication/token'];
112 this.rfb = new RFB(
113 this.$refs.panel,
114 `wss://${window.location.host}/kvm/0`,
Ed Tanous81323992024-02-27 11:26:24 -0800115 { wsProtocols: [token] },
Mateusz Gapski632de222020-07-09 09:21:33 +0200116 );
117
118 this.rfb.scaleViewport = true;
Mateusz Gapski96b37af2020-09-04 14:11:55 +0200119 this.rfb.clipViewport = true;
Mateusz Gapski632de222020-07-09 09:21:33 +0200120 const that = this;
Mateusz Gapski96b37af2020-09-04 14:11:55 +0200121
Konstantin Aladyshev69e8ec52021-02-22 14:07:57 +0300122 this.resizeKvmWindow = throttle(() => {
Mateusz Gapski96b37af2020-09-04 14:11:55 +0200123 setTimeout(that.setWidthToolbar, 0);
Konstantin Aladyshev69e8ec52021-02-22 14:07:57 +0300124 }, 1000);
125 window.addEventListener('resize', this.resizeKvmWindow);
Mateusz Gapski96b37af2020-09-04 14:11:55 +0200126
Mateusz Gapski632de222020-07-09 09:21:33 +0200127 this.rfb.addEventListener('connect', () => {
128 that.isConnected = true;
Mateusz Gapski96b37af2020-09-04 14:11:55 +0200129 that.status = Connected;
130 that.setWidthToolbar();
Mateusz Gapski632de222020-07-09 09:21:33 +0200131 });
132
133 this.rfb.addEventListener('disconnect', () => {
Mateusz Gapski96b37af2020-09-04 14:11:55 +0200134 this.isConnected = false;
135 that.status = Disconnected;
Mateusz Gapski632de222020-07-09 09:21:33 +0200136 });
Mateusz Gapski96b37af2020-09-04 14:11:55 +0200137 },
138 setWidthToolbar() {
139 if (
140 this.$refs.panel.children &&
141 this.$refs.panel.children.length > 0 &&
142 this.$refs.panel.children[0].children.length > 0
143 ) {
144 this.$refs.toolbar.style.width =
145 this.$refs.panel.children[0].children[0].clientWidth - 10 + 'px';
146 }
147 },
148 openConsoleWindow() {
Konstantinfb6c6de2023-06-14 17:23:14 +0300149 // If consoleWindow is not null
kirankumarb07b89eed22023-01-12 15:50:30 +0530150 // Check the newly opened window is closed or not
Konstantinfb6c6de2023-06-14 17:23:14 +0300151 if (this.$eventBus.$consoleWindow) {
kirankumarb07b89eed22023-01-12 15:50:30 +0530152 // If window is not closed set focus to new window
153 // If window is closed, do open new window
Konstantinfb6c6de2023-06-14 17:23:14 +0300154 if (!this.$eventBus.$consoleWindow.closed) {
155 this.$eventBus.$consoleWindow.focus();
kirankumarb07b89eed22023-01-12 15:50:30 +0530156 return;
157 } else {
158 this.openNewWindow();
159 }
160 } else {
Konstantinfb6c6de2023-06-14 17:23:14 +0300161 // If consoleWindow is null, open new window
kirankumarb07b89eed22023-01-12 15:50:30 +0530162 this.openNewWindow();
163 }
164 },
165 openNewWindow() {
Konstantinfb6c6de2023-06-14 17:23:14 +0300166 this.$eventBus.$consoleWindow = window.open(
Mateusz Gapski96b37af2020-09-04 14:11:55 +0200167 '#/console/kvm',
kirankumarb07b89eed22023-01-12 15:50:30 +0530168 'kvmConsoleWindow',
Ed Tanous81323992024-02-27 11:26:24 -0800169 'directories=no,titlebar=no,toolbar=no,location=no,status=no,menubar=no,scrollbars=no,resizable=yes,width=700,height=550',
Mateusz Gapski96b37af2020-09-04 14:11:55 +0200170 );
Derick Montague602e98a2020-10-21 16:20:00 -0500171 },
172 },
Mateusz Gapski632de222020-07-09 09:21:33 +0200173};
174</script>
175
176<style scoped lang="scss">
Mateusz Gapski632de222020-07-09 09:21:33 +0200177.button-ctrl-alt-delete {
178 float: right;
179}
180
181.kvm-status {
182 padding-top: $spacer / 2;
183 padding-left: $spacer / 4;
184 display: inline-block;
185}
Mateusz Gapski96b37af2020-09-04 14:11:55 +0200186
187.margin-left-full-window {
188 margin-left: 5px;
189}
Mateusz Gapski632de222020-07-09 09:21:33 +0200190</style>