]>
git.proxmox.com Git - pve-xtermjs.git/blob - xterm.js/src/main.js
85cc39953c928bc2003323777069a49fca5078ab
1 console
.log('xtermjs: starting');
20 starttime
= new Date();
22 var type
= getQueryParameter('console');
23 var vmid
= getQueryParameter('vmid');
24 var vmname
= getQueryParameter('vmname');
25 var nodename
= getQueryParameter('node');
26 var cmd
= getQueryParameter('cmd');
27 var cmdOpts
= getQueryParameter('cmd-opts');
29 function updateState(newState
, msg
, code
) {
30 var timeout
, severity
, message
;
32 case states
.connecting
:
33 message
= "Connecting...";
35 severity
= severities
.warning
;
37 case states
.connected
:
38 window
.onbeforeunload
= windowUnload
;
39 message
= "Connected";
41 case states
.disconnecting
:
42 window
.onbeforeunload
= undefined;
43 message
= "Disconnecting...";
45 severity
= severities
.warning
;
47 case states
.reconnecting
:
48 window
.onbeforeunload
= undefined;
49 message
= "Reconnecting...";
51 severity
= severities
.warning
;
53 case states
.disconnected
:
54 window
.onbeforeunload
= undefined;
57 case states
.connecting
:
58 case states
.reconnecting
:
59 message
= "Connection failed";
61 severity
= severities
.error
;
63 case states
.connected
:
64 case states
.disconnecting
:
65 var time_since_started
= new Date() - starttime
;
67 if (time_since_started
> 5*1000 || type
=== 'shell') {
68 message
= "Connection closed";
70 message
= "Connection failed";
71 severity
= severities
.error
;
74 case states
.disconnected
:
78 throw "unknown state";
82 throw "unknown state";
88 if (code
!== undefined) {
89 msgArr
.push(`Code: ${code}`);
91 if (msgArr
.length
> 0) {
92 message
+= ` (${msgArr.join(', ')})`;
95 showMsg(message
, timeout
, severity
);
98 var terminalContainer
= document
.getElementById('terminal-container');
99 document
.getElementById('status_bar').addEventListener('click', hideMsg
);
100 document
.getElementById('connect_btn').addEventListener('click', startGuest
);
101 const fitAddon
= new FitAddon
.FitAddon();
102 const webglAddon
= new WebglAddon
.WebglAddon();
106 function startConnection(url
, params
, term
) {
110 url
: url
+ '/termproxy',
111 success: function(result
) {
112 var port
= encodeURIComponent(result
.data
.port
);
113 ticket
= result
.data
.ticket
;
114 socketURL
= protocol
+ location
.hostname
+ ((location
.port
) ? (':' + location
.port
) : '') + '/api2/json' + url
+ '/vncwebsocket?port=' + port
+ '&vncticket=' + encodeURIComponent(ticket
);
116 socket
= new WebSocket(socketURL
, 'binary');
117 socket
.binaryType
= 'arraybuffer';
118 socket
.onopen
= runTerminal
;
119 socket
.onclose
= tryReconnect
;
120 socket
.onerror
= tryReconnect
;
121 updateState(states
.connecting
);
123 failure: function(msg
) {
124 updateState(states
.disconnected
,msg
);
129 function startGuest() {
130 let api_type
= type
=== 'kvm' ? 'qemu' : 'lxc';
133 url
: `/nodes/${nodename}/${api_type}/${vmid}/status/start`,
134 success: function(result
) {
135 showMsg('Guest started successfully', 0);
136 setTimeout(function() {
140 failure: function(msg
) {
141 if (msg
.match(/already running/)) {
142 showMsg('Guest started successfully', 0);
143 setTimeout(function() {
147 updateState(states
.disconnected
,msg
);
153 function createTerminal() {
154 term
= new Terminal(getTerminalSettings());
155 term
.open(terminalContainer
);
156 term
.loadAddon(fitAddon
);
158 term
.loadAddon(webglAddon
);
160 console
.warn("webgl-addon loading failed, falling back to regular dom renderer");
163 term
.onResize(function (size
) {
164 if (state
=== states
.connected
) {
165 socket
.send("1:" + size
.cols
+ ":" + size
.rows
+ ":");
169 protocol
= (location
.protocol
=== 'https:') ? 'wss://' : 'ws://';
172 var url
= '/nodes/' + nodename
;
175 url
+= '/qemu/' + vmid
;
178 url
+= '/lxc/' + vmid
;
181 params
.cmd
= 'upgrade';
184 params
.cmd
= decodeURI(cmd
);
185 if (cmdOpts
!== undefined && cmdOpts
!== null && cmdOpts
!== "") {
186 params
['cmd-opts'] = decodeURI(cmdOpts
);
190 if (type
=== 'kvm' || type
=== 'lxc') {
193 url
: `${url}/status/current`,
194 success: function(result
) {
195 if (result
.data
.status
=== 'running') {
196 startConnection(url
, params
, term
);
198 document
.getElementById('connect_dlg').classList
.add('pve_open');
201 failure: function(msg
) {
202 updateState(states
.disconnected
, msg
);
206 startConnection(url
, params
, term
);
210 function runTerminal() {
211 socket
.onmessage = function(event
) {
212 var answer
= new Uint8Array(event
.data
);
213 if (state
=== states
.connected
) {
215 } else if(state
=== states
.connecting
) {
216 if (answer
[0] === 79 && answer
[1] === 75) { // "OK"
217 updateState(states
.connected
);
218 term
.write(answer
.slice(2));
225 term
.onData(function(data
) {
226 if (state
=== states
.connected
) {
227 socket
.send("0:" + unescape(encodeURIComponent(data
)).length
.toString() + ":" + data
);
231 ping
= setInterval(function() {
235 window
.addEventListener('resize', function() {
236 clearTimeout(resize
);
237 resize
= setTimeout(function() {
243 socket
.send(PVE
.UserName
+ ':' + ticket
+ "\n");
245 // initial focus and resize
246 setTimeout(function() {
252 function getLxcStatus(callback
) {
255 url
: '/nodes/' + nodename
+ '/lxc/' + vmid
+ '/status/current',
256 success: function(result
) {
257 if (typeof callback
=== 'function') {
258 callback(true, result
);
261 failure: function(msg
) {
262 if (typeof callback
=== 'function') {
263 callback(false, msg
);
269 function checkMigration() {
271 if (apitype
=== 'kvm') {
279 url
: '/cluster/resources',
280 success: function(result
) {
281 // if not yet migrated , wait and try again
282 // if not migrating and stopped, cancel
283 // if started, connect
284 result
.data
.forEach(function(entity
) {
285 if (entity
.id
=== (apitype
+ '/' + vmid
)) {
286 var started
= entity
.status
=== 'running';
287 var migrated
= entity
.node
!== nodename
;
290 // goto different node
291 location
.href
= '?console=' + type
+
292 '&xtermjs=1&vmid=' + vmid
+ '&vmname=' +
293 vmname
+ '&node=' + entity
.node
;
296 updateState(states
.reconnecting
, 'waiting for migration to finish...');
297 setTimeout(checkMigration
, 5000);
300 if (type
=== 'lxc') {
301 // we have to check the status of the
302 // container to know if it has the
304 getLxcStatus(function(success
, result
) {
306 if (result
.data
.lock
=== 'migrate') {
308 updateState(states
.reconnecting
, 'waiting for migration to finish...');
309 setTimeout(checkMigration
, 5000);
310 } else if (started
) {
311 // container was rebooted
317 // probably the status call failed because
318 // the ct is already somewhere else, so retry
319 setTimeout(checkMigration
, 1000);
322 } else if (started
) {
323 // this happens if we have old data in
324 // /cluster/resources, or the connection
325 // disconnected, so simply try to reload here
327 } else if (type
=== 'kvm') {
328 // it seems the guest simply stopped
337 failure: function(msg
) {
338 errorTerminal({msg
: msg
});
343 function tryReconnect(event
) {
344 var time_since_started
= new Date() - starttime
;
345 var type
= getQueryParameter('console');
346 if (time_since_started
< 5*1000 || type
=== 'shell' || type
=== 'cmd') { // 5 seconds
351 updateState(states
.disconnecting
, 'Detecting migration...');
352 setTimeout(checkMigration
, 5000);
355 function clearEvents() {
356 term
.onResize(() => {});
357 term
.onData(() => {});
360 function windowUnload(e
) {
361 let message
= "Are you sure you want to leave this page?";
363 e
= e
|| window
.event
;
365 e
.returnValue
= message
;
371 function stopTerminal(event
) {
376 updateState(states
.disconnected
, event
.reason
, event
.code
);
379 function errorTerminal(event
) {
385 updateState(states
.disconnected
, event
.msg
, event
.code
);