]> git.proxmox.com Git - novnc-pve.git/blobdiff - pveui.js
replace s/openvz/lxc/
[novnc-pve.git] / pveui.js
index f616a0edd2100244d725732634bffc970cb1915f..b4bae6277dd759a2bffb71049c607a114aca1697 100644 (file)
--- a/pveui.js
+++ b/pveui.js
@@ -4,7 +4,8 @@
  * Copyright (C) 2013 Samuel Mannehed for Cendio AB
  * Licensed under MPL 2.0 (see LICENSE.txt)
  *
- * See README.md for usage and integration instructions.
+ * This is a modified version of the original 'ui.js' file, used
+ * for the proxmox console.
  */
 
 "use strict";
@@ -21,11 +22,13 @@ Util.load_scripts(["webutil.js", "base64.js", "websock.js", "des.js",
 var UI = {
 
 rfb_state : 'loaded',
+pveAllowMigratedVMTest: false, // set to true after a succesful conection 
 pveCommandsOpen: false,
 settingsOpen : false,
 connSettingsOpen : false,
 popupStatusOpen : false,
 clipboardOpen: false,
+sendKeysVisible: false,
 keyboardVisible: false,
 hideKeyboardTimeout: null,
 lastKeyboardinput: null,
@@ -143,13 +146,43 @@ pve_show_msg: function(klass, msg, permanant) {
     }, 5000);
 },
 
+pve_detect_migrated_vm: function() {
+    if (!(UI.consoletype === 'kvm' || UI.consoletype === 'lxc')) {
+       return;
+    }
+
+    // try to detect migrated VM
+    UI.API2Request({
+       url: '/cluster/resources',
+       method: 'GET',
+       success: function(result) {
+           var list = result.data;
+           list.every(function(item) {
+               if ((item.type === 'qemu' || item.type === 'lxc') && 
+                   (item.vmid == UI.vmid)) {
+                   var url = "?" + UI.urlEncode({
+                       console: UI.consoletype,
+                       novnc: 1,
+                       vmid: UI.vmid,
+                       vmname: UI.vmname,
+                       node: item.node
+                   });
+                   location.href = url;        
+                   return false; // break
+               }
+               return true;
+           });
+       }
+    });
+},
 pve_vm_command: function(cmd, params, reload) {
     var baseUrl;
 
     if (UI.consoletype === 'kvm') {
        baseUrl = '/nodes/' + UI.nodename + '/qemu/' + UI.vmid;
-    } else if (UI.consoletype === 'openvz') {
-       baseUrl = '/nodes/' + UI.nodename + '/openvz/' + UI.vmid;
+    } else if (UI.consoletype === 'lxc') {
+       baseUrl = '/nodes/' + UI.nodename + '/lxc/' + UI.vmid;
     } else {
        throw "unknown VM type";
     }
@@ -246,6 +279,25 @@ pveReload: function() {
     location.reload();
 },
 
+pve_send_key: function(keyname) {
+    var baseUrl;
+
+    if (UI.consoletype === 'kvm') {
+       baseUrl = '/nodes/' + UI.nodename + '/qemu/' + UI.vmid;
+    } else {
+       throw "send key not implemented";
+    }
+
+    UI.API2Request({
+       params: { key: keyname },
+       url: baseUrl + '/sendkey',
+       method: 'PUT',
+       failure: function(msg) {
+            UI.pve_show_msg('noVNC_status_warn', msg);
+       }
+    });
+},
 pve_start: function(callback) {
     UI.consoletype = WebUtil.getQueryVar('console');
     UI.vmid = WebUtil.getQueryVar('vmid');
@@ -256,14 +308,158 @@ pve_start: function(callback) {
     var wsurl;
     var params = { websocket: 1 };
     var btn;
-
-    var vmcmd_btns = ['pveStartButton', 'pveShutdownButton', 'pveStopButton', 'pveResetButton', 'pveSuspendButton', 'pveResumeButton'];
-    vmcmd_btns.forEach(function(btn) {
-       var el = $D(btn);
-       el.style.display = "none";
-       el.value = gettext(el.value);
+    
+    // add pve command buttons
+    var cmdpanel = $D('noVNC_pve_command_menu');
+    var buttonlist = [
+       {
+           text: gettext('Start'), 
+           handler: UI.pveCmdStart,
+           enable: { kvm: 1, lxc: 1 }
+       },
+       {
+           text: gettext('Shutdown'), 
+           handler: UI.pveCmdShutdown,
+           enable: { kvm: 1, lxc: 1 }
+       },
+       {
+           text: gettext('Stop'),
+           handler: UI.pveCmdStop,
+           enable: { kvm: 1, lxc: 1 }
+       },
+       {
+           text: gettext('Reset'),
+           handler: UI.pveCmdReset,
+           enable: { kvm: 1 }
+       },
+       {
+           text: gettext('Suspend'),
+           handler: UI.pveCmdSuspend,
+           enable: { kvm: 1 }
+       },
+       {
+           text: gettext('Resume'),
+           handler: UI.pveCmdResume,
+           enable: { kvm: 1 }
+       },
+       {
+           text: gettext('Reload'),
+           handler: UI.pveCmdReload,
+           enable: { any: 1 }
+       }
+    ];
+    buttonlist.forEach(function(btn) {
+       if (btn.enable.any || btn.enable[UI.consoletype]) {
+           var el = document.createElement('input');
+           el.setAttribute('type', 'button');
+           el.setAttribute('value', btn.text);
+           el.onclick = btn.handler;
+           el.style.display = "block";
+           el.style.width = "100%";
+           el.style.minWidth = "150px";
+           cmdpanel.appendChild(el);
+       }
     });
 
+    // add sendKeys buttons
+    var skpanel = $D('noVNC_send_keys_panel');
+
+    buttonlist = [
+       {
+           text: 'Tab', handler: function() {
+               UI.pve_send_key('tab');
+           }
+       },
+       {
+           text: 'Ctrl-Alt-Delete', handler: function() {
+               UI.pve_send_key('ctrl-alt-delete');
+           }
+       },
+       {
+           text: 'Ctrl-Alt-Backspace', handler: function() {
+               UI.pve_send_key('ctrl-alt-backspace');  
+           }
+       },
+       {
+           text: 'Ctrl-Alt-F1', handler: function() {
+               UI.pve_send_key('ctrl-alt-f1');
+           }
+       },
+       {
+           text: 'Ctrl-Alt-F2', handler: function() {
+               UI.pve_send_key('ctrl-alt-f2');
+           }
+       },
+       {
+           text: 'Ctrl-Alt-F3', handler: function() {
+               UI.pve_send_key('ctrl-alt-f3');
+           }
+       },
+       {
+           text: 'Ctrl-Alt-F4', handler: function() {
+               UI.pve_send_key('ctrl-alt-f4');
+           }
+       },
+       {
+           text: 'Ctrl-Alt-F5', handler: function() {
+               UI.pve_send_key('ctrl-alt-f5');
+           }
+       },
+       {
+           text: 'Ctrl-Alt-F6', handler: function() {
+               UI.pve_send_key('ctrl-alt-f6');
+           }
+       },
+       {
+           text: 'Ctrl-Alt-F7', handler: function() {
+               UI.pve_send_key('ctrl-alt-f7');
+           }
+       },
+       {
+           text: 'Ctrl-Alt-F8', handler: function() {
+               UI.pve_send_key('ctrl-alt-f8');
+           }
+       },
+       {
+           text: 'Ctrl-Alt-F9', handler: function() {
+               UI.pve_send_key('ctrl-alt-f9');
+           }
+       },
+       {
+           text: 'Ctrl-Alt-F10', handler: function() {
+               UI.pve_send_key('ctrl-alt-f10');
+           }
+       },
+       {
+           text: 'Ctrl-Alt-F11', handler: function() {
+               UI.pve_send_key('ctrl-alt-f11');
+           }
+       },
+       {
+           text: 'Ctrl-Alt-F12', handler: function() {
+               UI.pve_send_key('ctrl-alt-f12');
+           }
+       }
+    ];
+
+    buttonlist.forEach(function(btn) {
+       var el = document.createElement('input');
+       el.setAttribute('type', 'button');
+       el.setAttribute('value', btn.text);
+       el.onclick = function(handler) {
+           return function() {
+               if (UI.sendKeysVisible === true) {
+                   UI.togglePVESendKeysPanel();
+               }
+
+               handler.call(this);
+           };
+       }(btn.handler);
+       el.style.display = "block";
+       el.style.width = "100%";
+       el.style.minWidth = "150px";
+       skpanel.appendChild(el);
+    });
 
     var title;
 
@@ -271,20 +467,14 @@ pve_start: function(callback) {
        var baseUrl = '/nodes/' + UI.nodename + '/qemu/' + UI.vmid;
        url =  baseUrl + '/vncproxy';
        wsurl = baseUrl + '/vncwebsocket';
-       vmcmd_btns.forEach(function(btn) {
-           $D(btn).style.display = "";
-       });
        title = "VM " + UI.vmid;
        if (UI.vmname) {
            title += " ('" + UI.vmname + "')";
        }
-    } else if (UI.consoletype === 'openvz') {
-       var baseUrl = '/nodes/' + UI.nodename + '/openvz/' + UI.vmid;
+    } else if (UI.consoletype === 'lxc') {
+       var baseUrl = '/nodes/' + UI.nodename + '/lxc/' + UI.vmid;
        url =  baseUrl + '/vncproxy';
        wsurl = baseUrl + '/vncwebsocket';
-       ['pveStartButton', 'pveShutdownButton', 'pveStopButton'].forEach(function(btn) {
-           $D(btn).style.display = "";
-       });
        title = "CT " + UI.vmid;
        if (UI.vmname) {
            title += " ('" + UI.vmname + "')";
@@ -314,7 +504,7 @@ pve_start: function(callback) {
        });
 
        UI.updateSetting('host', window.location.hostname);
-       UI.updateSetting('port', window.location.port);
+       UI.updateSetting('port', window.location.port || 443);
        UI.updateSetting('password', param.ticket);
        UI.updateSetting('encrypt', true);
        UI.updateSetting('true_color', true);
@@ -346,8 +536,10 @@ sizeUpdateTimer: undefined,
 
 updateFBSize: function(rfb, width, height) {
     try {
-       UI.lastFBWidth = width + 2;
-       UI.lastFBHeight = height + 6;
+       // Note1: CSS Canvas size is wrong by a few pixels in Chrome
+       // Note2: window size must be even number for firefox
+       UI.lastFBWidth = Math.floor((width + 1)/2)*2;;
+       UI.lastFBHeight = Math.floor((height + 6)/2)*2;
 
        if (UI.sizeUpdateTimer !== undefined) {
            clearInterval(UI.sizeUpdateTimer);
@@ -391,10 +583,13 @@ updateFBSize: function(rfb, width, height) {
     }
 },
 
-// Open/close PVE connand menu
+// Open/close PVE commandand menu
 togglePVECommandPanel: function() {
     // Close the description panel
     $D('noVNC_description').style.display = "none";
+    if (UI.sendKeysVisible === true) {
+       UI.togglePVESendKeysPanel();
+    }
     // Close clipboard panel if open
     if (UI.clipboardOpen === true) {
         UI.toggleClipboardPanel();
@@ -422,6 +617,40 @@ togglePVECommandPanel: function() {
     }
 },
 
+// Open/close PVE SendKeys menu
+togglePVESendKeysPanel: function() {
+    // Close the description panel
+    $D('noVNC_description').style.display = "none";
+    if (UI.pveCommandsOpen === true) {
+       UI.togglePVECommandPanel();
+    }
+    // Close clipboard panel if open
+    if (UI.clipboardOpen === true) {
+        UI.toggleClipboardPanel();
+    }
+    // Close connection settings if open
+    if (UI.connSettingsOpen === true) {
+        UI.toggleConnectPanel();
+    }
+    // Close popup status panel if open
+    if (UI.popupStatusOpen === true) {
+        UI.togglePopupStatusPanel();
+    }
+    // Close XVP panel if open
+    if (UI.xvpOpen === true) {
+        UI.toggleXvpPanel();
+    }
+    if (UI.sendKeysVisible) {
+       $D('noVNC_send_keys').style.display = "none";
+       $D('showSendKeysButton').className = "noVNC_status_button";
+        UI.sendKeysVisible = false;
+    } else {
+       $D('noVNC_send_keys').style.display = "block";
+       $D('showSendKeysButton').className = "noVNC_status_button_selected";
+        UI.sendKeysVisible = true;
+    }
+},
+
 // Render default UI and initialize settings menu
 start: function(callback) {
     var html = '', i, sheet, sheets, llevels, port, autoconnect;
@@ -481,12 +710,14 @@ start: function(callback) {
     if (UI.isTouchDevice) {
         // Show mobile buttons
         $D('noVNC_mobile_buttons').style.display = "inline";
+       $D('showSendKeysButton').style.display = "none";
         UI.setMouseButton();
         // Remove the address bar
         setTimeout(function() { window.scrollTo(0, 1); }, 100);
         UI.forceSetting('clip', true);
         $D('noVNC_clip').disabled = true;
     } else {
+       $D('showSendKeysButton').style.display = (UI.consoletype === 'kvm') ? "inline" : "none";
         UI.initSetting('clip', false);
     }
 
@@ -548,19 +779,14 @@ addMouseHandlers: function() {
     $D("sendTabButton").onclick = UI.sendTab;
     $D("sendEscButton").onclick = UI.sendEsc;
 
-    $D("pveStartButton").onclick = UI.pveCmdStart;
-    $D("pveShutdownButton").onclick = UI.pveCmdShutdown;
-    $D("pveStopButton").onclick = UI.pveCmdStop;
-    $D("pveResetButton").onclick = UI.pveCmdReset;
-    $D("pveSuspendButton").onclick = UI.pveCmdSuspend;
-    $D("pveResumeButton").onclick = UI.pveCmdResume;
-    $D("pveReloadButton").onclick = UI.pveCmdReload;
+    $D("showSendKeysButton").onclick = UI.togglePVESendKeysPanel;
 
     $D("sendCtrlAltDelButton").onclick = UI.sendCtrlAltDel;
     //$D("xvpShutdownButton").onclick = UI.xvpShutdown;
     //$D("xvpRebootButton").onclick = UI.xvpReboot;
     //$D("xvpResetButton").onclick = UI.xvpReset;
-    $D("noVNC_status").onclick = UI.togglePopupStatusPanel;
+    // disable popup, because it does not provide more info?
+    //$D("noVNC_status").onclick = UI.togglePopupStatusPanel;
     $D("noVNC_popup_status_panel").onclick = UI.togglePopupStatusPanel;
     //$D("xvpButton").onclick = UI.toggleXvpPanel;
     $D("clipboardButton").onclick = UI.toggleClipboardPanel;
@@ -723,6 +949,9 @@ toggleClipboardPanel: function() {
     if (UI.pveCommandsOpen === true) {
        UI.togglePVECommandPanel();
     }
+    if (UI.sendKeysVisible === true) {
+       UI.togglePVESendKeysPanel();
+    }
     // Close settings if open
     if (UI.settingsOpen === true) {
         UI.settingsApply();
@@ -948,10 +1177,15 @@ updateState: function(rfb, state, oldstate, msg) {
             break;
         case 'normal':
             klass = "noVNC_status_normal";
+           UI.pveAllowMigratedVMTest = true;
             break;
         case 'disconnected':
             $D('noVNC_logo').style.display = "block";
-            // Fall through
+           if (UI.pveAllowMigratedVMTest) {
+               UI.pveAllowMigratedVMTest = false;
+               UI.pve_detect_migrated_vm();
+           }
+           // Fall through
         case 'loaded':
             klass = "noVNC_status_normal";
             break;
@@ -1002,13 +1236,11 @@ updateVisualState: function() {
         $D('clipboardButton').style.display =  (UI.consoletype !== 'kvm') ? "inline" : "none";
         $D('showKeyboard').style.display = "inline";
         $D('noVNC_extra_keys').style.display = "";
-       $D('sendCtrlAltDelButton').style.display = (UI.consoletype === 'kvm') ? "inline" : "none";
     } else {
         UI.setMouseButton();
         $D('clipboardButton').style.display = "none";
         $D('showKeyboard').style.display = "none";
         $D('noVNC_extra_keys').style.display = "none";
-        $D('sendCtrlAltDelButton').style.display = "none";
         UI.updateXvpVisualState(0);
     }
     
@@ -1297,6 +1529,7 @@ showExtraKeys: function() {
         $D('toggleAltButton').style.display = "inline";
         $D('sendTabButton').style.display = "inline";
         $D('sendEscButton').style.display = "inline";
+       $D('sendCtrlAltDelButton').style.display = (UI.consoletype === 'kvm') ? "inline" : "none";
         $D('showExtraKeysButton').className = "noVNC_status_button_selected";
         UI.extraKeysVisible = true;
     } else if(UI.extraKeysVisible === true) {
@@ -1304,6 +1537,7 @@ showExtraKeys: function() {
         $D('toggleAltButton').style.display = "";
         $D('sendTabButton').style.display = "";
         $D('sendEscButton').style.display = "";
+        $D('sendCtrlAltDelButton').style.display = "";
         $D('showExtraKeysButton').className = "noVNC_status_button";
         UI.extraKeysVisible = false;
     }