modelled after the QEMU Guest Agent UI. We only show the first
non-loopback IP on the summary page itself.

Signed-off-by: Leo Nunner <l.nun...@proxmox.com>
---
 www/manager6/Makefile                 |   1 +
 www/manager6/lxc/ContainerIPView.js   | 194 ++++++++++++++++++++++++++
 www/manager6/panel/GuestStatusView.js |  12 +-
 www/manager6/panel/GuestSummary.js    |   2 +-
 4 files changed, 207 insertions(+), 2 deletions(-)
 create mode 100644 www/manager6/lxc/ContainerIPView.js

diff --git a/www/manager6/Makefile b/www/manager6/Makefile
index 71ab928ff..2e967d949 100644
--- a/www/manager6/Makefile
+++ b/www/manager6/Makefile
@@ -180,6 +180,7 @@ JSSRC=                                                      
\
        lxc/ResourceEdit.js                             \
        lxc/Resources.js                                \
        lxc/MultiMPEdit.js                              \
+       lxc/ContainerIPView.js                          \
        menu/MenuItem.js                                \
        menu/TemplateMenu.js                            \
        ceph/CephInstallWizard.js                       \
diff --git a/www/manager6/lxc/ContainerIPView.js 
b/www/manager6/lxc/ContainerIPView.js
new file mode 100644
index 000000000..69b107af3
--- /dev/null
+++ b/www/manager6/lxc/ContainerIPView.js
@@ -0,0 +1,194 @@
+Ext.define('PVE.window.ContainerIPInfo', {
+    extend: 'Ext.window.Window',
+    width: 600,
+    title: gettext('Container Network Information'),
+    height: 300,
+    layout: {
+       type: 'fit',
+    },
+    modal: true,
+    items: [
+       {
+           xtype: 'grid',
+           store: {},
+           emptyText: gettext('No network information'),
+           columns: [
+               {
+                   dataIndex: 'name',
+                   text: gettext('Name'),
+                   flex: 2,
+               },
+               {
+                   dataIndex: 'hwaddr',
+                   text: gettext('MAC address'),
+                   width: 140,
+               },
+               {
+                   dataIndex: 'inet',
+                   text: gettext('IPv4 address'),
+                   align: 'right',
+                   flex: 3,
+               },
+               {
+                   dataIndex: 'inet6',
+                   text: gettext('IPv6 address'),
+                   align: 'right',
+                   flex: 4,
+               },
+           ],
+       },
+    ],
+});
+
+Ext.define('PVE.lxc.IPView', {
+    extend: 'Ext.container.Container',
+    xtype: 'pveContainerIPView',
+
+    layout: {
+       type: 'hbox',
+       align: 'top',
+    },
+
+    items: [
+       {
+           xtype: 'box',
+           html: '<i class="fa fa-exchange"></i> IPs',
+       },
+       {
+           xtype: 'container',
+           flex: 1,
+           layout: {
+               type: 'vbox',
+               align: 'right',
+               pack: 'end',
+           },
+           items: [
+               {
+                   xtype: 'label',
+                   flex: 1,
+                   itemId: 'ipBox',
+                   style: {
+                       'text-align': 'right',
+                   },
+               },
+               {
+                   xtype: 'button',
+                   itemId: 'moreBtn',
+                   hidden: true,
+                   ui: 'default-toolbar',
+                   handler: function(btn) {
+                       let view = this.up('pveContainerIPView');
+
+                       var win = Ext.create('PVE.window.ContainerIPInfo');
+                       win.down('grid').getStore().setData(view.ifaces);
+                       win.show();
+                   },
+                   text: gettext('More'),
+               },
+           ],
+       },
+    ],
+
+    getDefaultIps: function(ifaces) {
+       var me = this;
+       var ips = [];
+       ifaces.forEach(function(iface) {
+           // We only want to show the first non-loopback interface
+           if (!ips.length &&
+               iface.data.hwaddr &&
+               iface.data.hwaddr !== '00:00:00:00:00:00' &&
+               iface.data.hwaddr !== '0:0:0:0:0:0') {
+               ips.push(iface.data.inet);
+               ips.push(iface.data.inet6);
+           }
+       });
+
+       return ips;
+    },
+
+    startIPStore: function(store, records, success) {
+       var me = this;
+       let state = store.getById('status');
+
+       me.running = state && state.data.value === 'running';
+
+       var caps = Ext.state.Manager.get('GuiCap');
+
+       if (!caps.vms['VM.Monitor']) {
+           var errorText = gettext("Requires '{0}' Privileges");
+           me.updateStatus(false, Ext.String.format(errorText, 'VM.Monitor'));
+           return;
+       }
+
+       if (me.running && me.ipStore.isStopped) {
+           me.ipStore.startUpdate();
+       } else if (me.ipStore.isStopped) {
+           me.updateStatus();
+       }
+    },
+
+    updateStatus: function(unsuccessful, defaulttext) {
+       var me = this;
+       var text = defaulttext || gettext('No network information');
+       var more = false;
+       if (Ext.isArray(me.ifaces) && me.ifaces.length) {
+           more = true;
+           var ips = me.getDefaultIps(me.ifaces);
+           if (ips.length !== 0) {
+               text = ips.join('<br>');
+           }
+       }
+
+       var ipBox = me.down('#ipBox');
+       ipBox.update(text);
+
+       var moreBtn = me.down('#moreBtn');
+       moreBtn.setVisible(more);
+    },
+
+    initComponent: function() {
+       var me = this;
+
+       if (!me.rstore) {
+           throw 'rstore not given';
+       }
+
+       if (!me.pveSelNode) {
+           throw 'pveSelNode not given';
+       }
+
+       var nodename = me.pveSelNode.data.node;
+       var vmid = me.pveSelNode.data.vmid;
+
+       me.ipStore = Ext.create('Proxmox.data.UpdateStore', {
+           interval: 10000,
+           storeid: 'lxc-interfaces-' + vmid,
+           method: 'GET',
+           proxy: {
+               type: 'proxmox',
+               url: '/api2/json/nodes/' + nodename + '/lxc/' + vmid + 
'/interfaces',
+           },
+       });
+
+       me.callParent();
+
+       me.mon(me.ipStore, 'load', function(store, records, success) {
+           if (records && records.length) {
+               me.ifaces = records;
+           } else {
+               me.ifaces = undefined;
+           }
+           me.updateStatus(!success);
+       });
+
+       me.on('destroy', me.ipStore.stopUpdate, me.ipStore);
+
+       // if we already have info about the guest, use it immediately
+       if (me.rstore.getCount()) {
+           me.startIPStore(me.rstore, me.rstore.getData(), false);
+       }
+
+       // check if the guest agent is there on every statusstore load
+       me.mon(me.rstore, 'load', me.startIPStore, me);
+    },
+});
diff --git a/www/manager6/panel/GuestStatusView.js 
b/www/manager6/panel/GuestStatusView.js
index 8db1f492c..7a093bb34 100644
--- a/www/manager6/panel/GuestStatusView.js
+++ b/www/manager6/panel/GuestStatusView.js
@@ -113,7 +113,7 @@ Ext.define('PVE.panel.GuestStatusView', {
            height: 15,
        },
        {
-           itemId: 'ips',
+           itemId: 'agentIPs',
            xtype: 'pveAgentIPView',
            cbind: {
                rstore: '{rstore}',
@@ -122,6 +122,16 @@ Ext.define('PVE.panel.GuestStatusView', {
                disabled: '{isLxc}',
            },
        },
+       {
+           itemId: 'ctIPS',
+           xtype: 'pveContainerIPView',
+           cbind: {
+               rstore: '{rstore}',
+               pveSelNode: '{pveSelNode}',
+               hidden: '{!isLxc}',
+               disabled: '{!isLxc}',
+           },
+       },
     ],
 
     updateTitle: function() {
diff --git a/www/manager6/panel/GuestSummary.js 
b/www/manager6/panel/GuestSummary.js
index 1565db3f6..049b63aa9 100644
--- a/www/manager6/panel/GuestSummary.js
+++ b/www/manager6/panel/GuestSummary.js
@@ -54,7 +54,7 @@ Ext.define('PVE.guest.Summary', {
            items = [
                {
                    xtype: 'container',
-                   height: 300,
+                   height: 350,
                    layout: {
                        type: 'hbox',
                        align: 'stretch',
-- 
2.30.2



_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel

Reply via email to