var vmid = getQueryParameter('vmid');
var vmname = getQueryParameter('vmname');
var nodename = getQueryParameter('node');
+var cmd = getQueryParameter('cmd');
+var cmdOpts = getQueryParameter('cmd-opts');
-function updateState(newState, msg) {
+function updateState(newState, msg, code) {
var timeout, severity, message;
switch (newState) {
case states.connecting:
severity = severities.warning;
break;
case states.connected:
+ window.onbeforeunload = windowUnload;
message = "Connected";
break;
case states.disconnecting:
+ window.onbeforeunload = undefined;
message = "Disconnecting...";
timeout = 0;
severity = severities.warning;
break;
case states.reconnecting:
+ window.onbeforeunload = undefined;
message = "Reconnecting...";
timeout = 0;
severity = severities.warning;
break;
case states.disconnected:
+ window.onbeforeunload = undefined;
switch (state) {
case states.start:
case states.connecting:
case states.disconnecting:
var time_since_started = new Date() - starttime;
timeout = 5000;
- if (time_since_started > 5*1000) {
+ if (time_since_started > 5*1000 || type === 'shell') {
message = "Connection closed";
} else {
message = "Connection failed";
default:
throw "unknown state";
}
+ let msgArr = [];
if (msg) {
- message += " (" + msg + ")";
+ msgArr.push(msg);
+ }
+ if (code !== undefined) {
+ msgArr.push(`Code: ${code}`);
+ }
+ if (msgArr.length > 0) {
+ message += ` (${msgArr.join(', ')})`;
}
state = newState;
showMsg(message, timeout, severity);
var terminalContainer = document.getElementById('terminal-container');
document.getElementById('status_bar').addEventListener('click', hideMsg);
-Terminal.applyAddon(fit);
+document.getElementById('connect_btn').addEventListener('click', startGuest);
+const fitAddon = new FitAddon.FitAddon();
createTerminal();
-function createTerminal() {
- term = new Terminal(getTerminalSettings());
-
- term.on('resize', function (size) {
- if (state === states.connected) {
- socket.send("1:" + size.cols + ":" + size.rows + ":");
- }
- });
-
- protocol = (location.protocol === 'https:') ? 'wss://' : 'ws://';
-
- var params = {};
- var url = '/nodes/' + nodename;
- switch (type) {
- case 'kvm':
- url += '/qemu/' + vmid;
- break;
- case 'lxc':
- url += '/lxc/' + vmid;
- break;
- case 'upgrade':
- params.upgrade = 1;
- break;
- }
+function startConnection(url, params, term) {
API2Request({
method: 'POST',
params: params,
socket.onopen = runTerminal;
socket.onclose = tryReconnect;
socket.onerror = tryReconnect;
- window.onbeforeunload = stopTerminal;
updateState(states.connecting);
},
failure: function(msg) {
updateState(states.disconnected,msg);
}
});
+}
+function startGuest() {
+ let api_type = type === 'kvm' ? 'qemu' : 'lxc';
+ API2Request({
+ method: 'POST',
+ url: `/nodes/${nodename}/${api_type}/${vmid}/status/start`,
+ success: function(result) {
+ showMsg('Guest started successfully', 0);
+ setTimeout(function() {
+ location.reload();
+ }, 1000);
+ },
+ failure: function(msg) {
+ if (msg.match(/already running/)) {
+ showMsg('Guest started successfully', 0);
+ setTimeout(function() {
+ location.reload();
+ }, 1000);
+ } else {
+ updateState(states.disconnected,msg);
+ }
+ }
+ });
+}
+
+function createTerminal() {
+ term = new Terminal(getTerminalSettings());
+ term.loadAddon(fitAddon);
+
+ term.onResize(function (size) {
+ if (state === states.connected) {
+ socket.send("1:" + size.cols + ":" + size.rows + ":");
+ }
+ });
+
+ protocol = (location.protocol === 'https:') ? 'wss://' : 'ws://';
+
+ var params = {};
+ var url = '/nodes/' + nodename;
+ switch (type) {
+ case 'kvm':
+ url += '/qemu/' + vmid;
+ break;
+ case 'lxc':
+ url += '/lxc/' + vmid;
+ break;
+ case 'upgrade':
+ params.cmd = 'upgrade';
+ break;
+ case 'cmd':
+ params.cmd = decodeURI(cmd);
+ if (cmdOpts !== undefined && cmdOpts !== null && cmdOpts !== "") {
+ params['cmd-opts'] = decodeURI(cmdOpts);
+ }
+ break;
+ }
+ if (type === 'kvm' || type === 'lxc') {
+ API2Request({
+ method: 'GET',
+ url: `${url}/status/current`,
+ success: function(result) {
+ if (result.data.status === 'running') {
+ startConnection(url, params, term);
+ } else {
+ document.getElementById('connect_dlg').classList.add('pve_open');
+ }
+ },
+ failure: function(msg) {
+ updateState(states.disconnected, msg);
+ },
+ });
+ } else {
+ startConnection(url, params, term);
+ }
}
function runTerminal() {
socket.onmessage = function(event) {
- var answer = Utf8ArrayToStr(event.data);
+ var answer = new Uint8Array(event.data);
if (state === states.connected) {
term.write(answer);
} else if(state === states.connecting) {
- if (answer.slice(0,2) === "OK") {
+ if (answer[0] === 79 && answer[1] === 75) { // "OK"
updateState(states.connected);
term.write(answer.slice(2));
} else {
}
};
- term.on('data', function(data) {
+ term.onData(function(data) {
if (state === states.connected) {
socket.send("0:" + unescape(encodeURIComponent(data)).length.toString() + ":" + data);
}
clearTimeout(resize);
resize = setTimeout(function() {
// done resizing
- term.fit();
+ fitAddon.fit();
}, 250);
});
socket.send(PVE.UserName + ':' + ticket + "\n");
- setTimeout(function() {term.fit();}, 250);
+ // initial focus and resize
+ setTimeout(function() {
+ term.focus();
+ fitAddon.fit();
+ }, 250);
}
function getLxcStatus(callback) {
// still waiting
updateState(states.reconnecting, 'waiting for migration to finish...');
setTimeout(checkMigration, 5000);
+ } else if (started) {
+ // container was rebooted
+ location.reload();
} else {
stopTerminal();
}
});
}
-function tryReconnect() {
+function tryReconnect(event) {
var time_since_started = new Date() - starttime;
var type = getQueryParameter('console');
- if (time_since_started < 5*1000) { // 5 seconds
- stopTerminal({});
+ if (time_since_started < 5*1000 || type === 'shell' || type === 'cmd') { // 5 seconds
+ stopTerminal(event);
return;
- } else if (type === 'shell') {
- updateState(states.reconnecting, 'trying to reconnect...');
- setTimeout(function() {
- location.reload();
- }, 1000);
}
updateState(states.disconnecting, 'Detecting migration...');
setTimeout(checkMigration, 5000);
}
+function clearEvents() {
+ term.onResize(() => {});
+ term.onData(() => {});
+}
+
+function windowUnload(e) {
+ let message = "Are you sure you want to leave this page?";
+
+ e = e || window.event;
+ if (e) {
+ e.returnValue = message;
+ }
+
+ return message;
+}
+
function stopTerminal(event) {
- term.off('resize');
- term.off('data');
+ event = event || {};
+ clearEvents();
clearInterval(ping);
socket.close();
- updateState(states.disconnected, event.msg + event.code);
+ updateState(states.disconnected, event.reason, event.code);
}
function errorTerminal(event) {
- term.off('resize');
- term.off('data');
+ even = event || {};
+ clearEvents();
clearInterval(ping);
socket.close();
- term.destroy();
- updateState(states.disconnected, event.msg + event.code);
+ term.dispose();
+ updateState(states.disconnected, event.msg, event.code);
}