]> git.proxmox.com Git - pve-manager.git/blobdiff - www/manager6/VNCConsole.js
rename manager5 to manager6
[pve-manager.git] / www / manager6 / VNCConsole.js
diff --git a/www/manager6/VNCConsole.js b/www/manager6/VNCConsole.js
new file mode 100644 (file)
index 0000000..db90388
--- /dev/null
@@ -0,0 +1,591 @@
+Ext.define('PVE.noVncConsole', {
+    extend: 'Ext.panel.Panel',
+    alias: 'widget.pveNoVncConsole',
+
+    nodename: undefined,
+
+    vmid: undefined,
+
+    consoleType: undefined, // lxc or kvm
+    
+    initComponent : function() {
+       var me = this;
+
+       if (!me.nodename) {
+           throw "no node name specified";
+       }
+
+       if (!me.consoleType) {
+           throw "no console type specified";
+       }
+
+       if (!me.vmid && me.consoleType !== 'shell') {
+           throw "no VM ID specified";
+       }
+       
+       // always use same iframe, to avoid running several noVnc clients
+       // at same time (to avoid performance problems)
+       var box = Ext.create('widget.uxiframe', { id: "vncconsole" });
+
+       Ext.apply(me, {
+           layout: { type: 'fit' },
+           border: false,
+           items: box,
+           listeners: {
+               show: function() {
+                   var url = '/?console=' + me.consoleType + '&novnc=1&node=' + me.nodename + '&resize=scale';
+                   if (me.vmid) {
+                       url += '&vmid='+ me.vmid;
+                   }
+                   box.load(url);
+               }
+           }
+       });             
+
+       me.callParent();
+    }
+});
+
+PVE_vnc_console_event = function(appletid, action, err) {
+    //console.log("TESTINIT param1 " + appletid + " action " + action);
+
+    if (action === "error") {
+       var compid = appletid.replace("-vncapp", "");
+       var comp = Ext.getCmp(compid);
+
+       if (!comp || !comp.vmid || !comp.toplevel) {
+           return;
+       }
+
+       comp.detectMigratedVM();
+    }
+
+    return;
+ };
+
+Ext.define('PVE.VNCConsole', {
+    extend: 'Ext.panel.Panel',
+    alias: ['widget.pveVNCConsole'],
+
+    novnc: false,
+
+    last_novnc_state: undefined,
+    last_novnc_msg: undefined,
+
+    detectMigratedVM: function() {
+       var me = this;
+       
+       if (!me.vmid) {
+           return;
+       }
+
+       // try to detect migrated VM
+       PVE.Utils.API2Request({
+           url: '/cluster/resources',
+           method: 'GET',
+           success: function(response) {
+               var list = response.result.data;
+               Ext.Array.each(list, function(item) {
+                   if (item.type === 'qemu' && item.vmid == me.vmid) {
+                       if (item.node !== me.nodename) {
+                           me.nodename = item.node;
+                           me.url = "/nodes/" + me.nodename + "/" + item.type + "/" + me.vmid + "/vncproxy";
+                           me.wsurl = "/nodes/" + me.nodename + "/" + item.type + "/" + me.vmid + "/vncwebsocket";
+                           me.reloadApplet();
+                       }
+                       return false; // break
+                   }
+               });
+           }
+       });
+    },
+
+    initComponent : function() {
+       var me = this;
+
+       if (!me.url) {
+           throw "no url specified";
+       }
+
+       var myid = me.id + "-vncapp";
+
+       me.appletID = myid;
+
+       var box;
+
+       if (me.novnc) {
+           if (!me.wsurl) {
+               throw "no web socket url specified";
+           }
+           box = Ext.create('widget.uxiframe', { id: myid });
+       } else {
+           box = Ext.create('Ext.Component', { border: false, html: "" });
+       }
+
+       var resize_window = function() {
+           //console.log("resize");
+
+           var aw;
+           var ah;
+           var applet;
+
+           if (me.novnc) {
+               var novnciframe = box.getFrame();
+               // noVNC_canvas
+               var innerDoc = novnciframe.contentDocument || novnciframe.contentWindow.document;
+               aw = innerDoc.getElementById('noVNC_canvas').width;
+               ah = innerDoc.getElementById('noVNC_canvas').height + 8;
+
+               var novnc_state = innerDoc.getElementById('noVNC_status_state').innerHTML;
+               var novnc_msg = innerDoc.getElementById('noVNC_status_msg').innerHTML;
+
+               if (novnc_state !== me.last_novnc_state || novnc_msg !== me.last_novnc_msg) {
+                   me.last_novnc_state = novnc_state; 
+                   me.last_novnc_msg = novnc_msg; 
+
+                   if (novnc_state !== 'normal') {
+                       PVE.Utils.setErrorMask(box, novnc_msg || 'unknown');
+                   } else {
+                       PVE.Utils.setErrorMask(box); // clear mask
+                   }
+
+                   if (novnc_state === 'disconnected') {
+                       me.detectMigratedVM();
+                   }
+               }
+
+           } else {
+               applet = Ext.getDom(myid);
+           
+               // try again when dom element is available
+               if (!(applet && Ext.isFunction(applet.getPreferredSize))) {
+                   return Ext.Function.defer(resize_window, 1000);
+               }
+
+               var ps = applet.getPreferredSize();
+               aw = ps.width;
+               ah = ps.height;
+           }
+
+           if (aw < 640) { aw = 640; }
+           if (ah < 400) { ah = 400; }
+
+           var tbar = me.getDockedItems("[dock=top]")[0];
+           var tbh = tbar ? tbar.getHeight() : 0;
+
+           var oh;
+           var ow;
+
+           //console.log("size0 " + aw + " " + ah + " tbh " + tbh);
+
+           if (window.innerHeight) {
+               oh = window.innerHeight;
+               ow = window.innerWidth;
+           } else if (document.documentElement && 
+                      document.documentElement.clientHeight) {
+               oh = document.documentElement.clientHeight;
+               ow = document.documentElement.clientWidth;
+           } else if (document.body) {
+               oh = document.body.clientHeight;
+               ow = document.body.clientWidth;
+           }  else {
+               throw "can't get window size";
+           }
+
+           if (!me.novnc) {
+               Ext.fly(applet).setSize(aw, ah + tbh);
+           }
+
+           var offsetw = aw - ow;
+           var offseth = ah + tbh - oh;
+
+           if (offsetw !== 0 || offseth !== 0) {
+               //console.log("try resize by " + offsetw + " " + offseth);
+               try { window.resizeBy(offsetw, offseth); } catch (e) {}
+           }
+
+           Ext.Function.defer(resize_window, 1000);
+       };
+
+       var resize_box = function() {
+           if (me.novnc) {
+               throw "implement me";
+           } else {
+               var applet = Ext.getDom(myid);
+
+               if ((applet && Ext.isFunction(applet.getPreferredSize))) {
+                   var ps = applet.getPreferredSize();
+                   Ext.fly(applet).setSize(ps.width, ps.height);
+               }
+           }
+
+           Ext.Function.defer(resize_box, 1000);
+       };
+
+       var start_vnc_viewer = function(param) {
+           
+           if (me.novnc) {
+               
+               var pveparams = Ext.urlEncode({
+                   port: param.port,
+                   vncticket: param.ticket
+               });
+
+               var urlparams = Ext.urlEncode({
+                   encrypt: 1,
+                   path: "api2/json" + me.wsurl + "?" + pveparams,
+                   password: param.ticket
+               });
+               box.load('/novnc/vnc_pve.html?' + urlparams);
+           
+           } else {
+
+               var cert = param.cert;
+               cert = cert.replace(/\n/g, "|");
+
+               box.update({
+                   id: myid,
+                   border: false,
+                   tag: 'applet',
+                   code: 'com.tigervnc.vncviewer.VncViewer',
+                   archive: '/vncterm/VncViewer.jar',
+                   // NOTE: set size to '100%' -  else resize does not work
+                   width: "100%",
+                   height: "100%", 
+                   cn: [
+                       {tag: 'param', name: 'id', value: myid},
+                       {tag: 'param', name: 'PORT', value: param.port},
+                       {tag: 'param', name: 'PASSWORD', value: param.ticket},
+                       {tag: 'param', name: 'USERNAME', value: param.user},
+                       {tag: 'param', name: 'Show Controls', value: 'No'},
+                       {tag: 'param', name: 'Offer Relogin', value: 'No'},
+                       {tag: 'param', name: 'PVECert', value: cert}
+                   ]
+               });
+           }
+
+            if (me.toplevel) {
+               Ext.Function.defer(resize_window, 1000);
+            } else {
+               Ext.Function.defer(resize_box, 1000);
+            }
+       };
+
+       Ext.apply(me, {
+           layout: 'fit',
+           border: false,
+           autoScroll: me.toplevel ? false : true,
+           items: box,
+           reloadApplet: function() {
+               var params = Ext.apply({}, me.params);
+               if (me.novnc) {
+                   params.websocket = 1;
+               } 
+               PVE.Utils.API2Request({
+                   url: me.url,
+                   params: params,
+                   method: me.method || 'POST',
+                   failure: function(response, opts) {
+                       box.update(gettext('Error') + ' ' + response.htmlStatus);
+                   },
+                   success: function(response, opts) {
+                       start_vnc_viewer(response.result.data);
+                   }
+               });
+           }
+       });
+
+       me.callParent();
+
+       if (me.toplevel) {
+           me.on("render", me.reloadApplet);
+       } else {
+           me.on("show", me.reloadApplet);
+           me.on("hide", function() { box.update(""); });
+       }
+    }
+});
+
+Ext.define('PVE.KVMConsole', {
+    extend: 'PVE.VNCConsole',
+    alias: ['widget.pveKVMConsole'],
+
+    initComponent : function() {
+       var me = this;
+       if (!me.nodename) { 
+           throw "no node name specified";
+       }
+
+       if (!me.vmid) {
+           throw "no VM ID specified";
+       }
+
+       var baseUrl = "/nodes/" + me.nodename + "/qemu/" + me.vmid;
+
+       var vm_command = function(cmd, params, reload_applet) {
+           PVE.Utils.API2Request({
+               params: params,
+               url: baseUrl + "/status/" + cmd,
+               method: 'POST',
+               waitMsgTarget: me,
+               failure: function(response, opts) {
+                   Ext.Msg.alert('Error', response.htmlStatus);
+               },
+               success: function() {
+                   if (reload_applet) {
+                       Ext.Function.defer(me.reloadApplet, 1000, me);
+                   }
+               }
+           });
+       };
+
+       var tbar = [ 
+           { 
+               text: gettext('Start'),
+               handler: function() { 
+                   vm_command("start", {}, 1);
+               }
+           },
+           { 
+               text: gettext('Shutdown'),
+               handler: function() {
+                   var msg = Ext.String.format(gettext("Do you really want to shutdown VM {0}?"), me.vmid);
+                   Ext.Msg.confirm(gettext('Confirm'), msg, function(btn) {
+                       if (btn !== 'yes') {
+                           return;
+                       }
+                       vm_command('shutdown');
+                   });
+               }                           
+           }, 
+           { 
+               text: gettext('Stop'),
+               handler: function() {
+                   var msg = Ext.String.format(gettext("Do you really want to stop VM {0}?"), me.vmid);
+                   Ext.Msg.confirm(gettext('Confirm'), msg, function(btn) {
+                       if (btn !== 'yes') {
+                           return;
+                       }
+                       vm_command("stop");
+                   }); 
+               }
+           },
+           { 
+               xtype: 'pveQemuSendKeyMenu',
+               nodename: me.nodename,
+               vmid: me.vmid
+           },
+           { 
+               text: gettext('Reset'),
+               handler: function() { 
+                   var msg = Ext.String.format(gettext("Do you really want to reset VM {0}?"), me.vmid);
+                   Ext.Msg.confirm(gettext('Confirm'), msg, function(btn) {
+                       if (btn !== 'yes') {
+                           return;
+                       }
+                       vm_command("reset");
+                   });
+               }
+           },
+           { 
+               text: gettext('Suspend'),
+               handler: function() {
+                   var msg = Ext.String.format(gettext("Do you really want to suspend VM {0}?"), me.vmid);
+                   Ext.Msg.confirm(gettext('Confirm'), msg, function(btn) {
+                       if (btn !== 'yes') {
+                           return;
+                       }
+                       vm_command("suspend");
+                   }); 
+               }
+           },
+           { 
+               text: gettext('Resume'),
+               handler: function() {
+                   vm_command("resume"); 
+               }
+           },
+           // Note: no migrate here, because we can't display migrate log
+            { 
+                text: gettext('Console'),
+                handler: function() {
+                   PVE.Utils.openVNCViewer('kvm', me.vmid, me.nodename, me.vmname, me.novnc);
+               }
+            },
+            '->',
+           {
+                text: gettext('Refresh'),
+               hidden: me.novnc ? true : false,
+               handler: function() { 
+                   var applet = Ext.getDom(me.appletID);
+                   applet.sendRefreshRequest();
+               }
+           },
+           {
+                text: gettext('Reload'),
+                handler: function () { 
+                   me.reloadApplet(); 
+               }
+           }
+       ];
+
+       
+       Ext.apply(me, {
+           tbar: tbar,
+           url: baseUrl + "/vncproxy",
+           wsurl: baseUrl + "/vncwebsocket"
+       });
+
+       me.callParent();
+    }
+});
+
+Ext.define('PVE.LxcConsole', {
+    extend: 'PVE.VNCConsole',
+    alias: ['widget.pveLxcConsole'],
+
+    initComponent : function() {
+       var me = this;
+       if (!me.nodename) { 
+           throw "no node name specified";
+       }
+
+       if (!me.vmid) {
+           throw "no VM ID specified";
+       }
+
+       var baseUrl = "/nodes/" + me.nodename + "/lxc/" + me.vmid;
+       var vm_command = function(cmd, params, reload_applet) {
+           PVE.Utils.API2Request({
+               params: params,
+               url: baseUrl + "/status/" + cmd,
+               waitMsgTarget: me,
+               method: 'POST',
+               failure: function(response, opts) {
+                   Ext.Msg.alert('Error', response.htmlStatus);
+               },
+               success: function() {
+                   if (reload_applet) {
+                       Ext.Function.defer(me.reloadApplet, 1000, me);
+                   }
+               }
+           });
+       };
+
+       var tbar = [ 
+           { 
+               text: gettext('Start'),
+               handler: function() { 
+                   vm_command("start");
+               }
+           },
+           { 
+               text: gettext('Shutdown'),
+               handler: function() {
+                   var msg = Ext.String.format(gettext("Do you really want to shutdown VM {0}?"), me.vmid);
+                   Ext.Msg.confirm(gettext('Confirm'), msg, function(btn) {
+                       if (btn !== 'yes') {
+                           return;
+                       }
+                       vm_command("shutdown");
+                   }); 
+               }
+           },
+           { 
+               text: gettext('Stop'),
+               handler: function() {
+                   var msg = Ext.String.format(gettext("Do you really want to stop VM {0}?"), me.vmid);
+                   Ext.Msg.confirm(gettext('Confirm'), msg, function(btn) {
+                       if (btn !== 'yes') {
+                           return;
+                       }
+                       vm_command("stop");
+                   }); 
+               }
+           },
+           // Note: no migrate here, because we can't display migrate log
+            '->',
+           {
+                text: gettext('Refresh'),
+               hidden: me.novnc ? true : false,
+               handler: function() { 
+                   var applet = Ext.getDom(me.appletID);
+                   applet.sendRefreshRequest();
+               }
+           },
+           {
+                text: gettext('Reload'),
+                handler: function () { 
+                   me.reloadApplet(); 
+               }
+           }
+       ];
+
+       Ext.apply(me, {
+           tbar: tbar,
+           url: baseUrl + "/vncproxy",
+           wsurl: baseUrl + "/vncwebsocket"
+       });
+
+       me.callParent();
+    }
+});
+
+Ext.define('PVE.Shell', {
+    extend: 'PVE.VNCConsole',
+    alias: ['widget.pveShell'],
+
+    ugradeSystem: false, // set to true to run "apt-get dist-upgrade"
+
+    initComponent : function() {
+       var me = this;
+       if (!me.nodename) { 
+           throw "no node name specified";
+       }
+
+       var tbar = [ '->' ];
+
+       if (!me.novnc) {
+           tbar.push({
+                text: gettext('Refresh'),
+               handler: function() { 
+                   var applet = Ext.getDom(me.appletID);
+                   applet.sendRefreshRequest();
+               }
+           });
+       }
+
+       if (!me.ugradeSystem) {
+           // we dont want to restart the upgrade script
+           tbar.push({
+                text: gettext('Reload'),
+                handler: function () { me.reloadApplet(); }
+           });
+       }
+
+       tbar.push({ 
+           text: gettext('Shell'),
+           handler: function() {
+               PVE.Utils.openVNCViewer('shell', undefined, me.nodename, undefined, me.novnc);
+           }
+       });
+
+       var baseUrl = "/nodes/" + me.nodename;
+
+       Ext.apply(me, {
+           tbar: tbar,
+           url: baseUrl + "/vncshell",
+           wsurl: baseUrl + "/vncwebsocket"
+       });
+
+       if (me.ugradeSystem) {
+           me.params = { upgrade: 1 };     
+       }
+
+       me.callParent();
+    }
+});