]> git.proxmox.com Git - pve-manager.git/blobdiff - www/manager6/lxc/Network.js
ui: lxc/MPEdit: add updateVMConfig
[pve-manager.git] / www / manager6 / lxc / Network.js
index 80ba9dc67727eca852b906a2bfdec8b275ae4861..7b6437c5a414a0e36f995c0f327e9c2f4da249e3 100644 (file)
@@ -1,5 +1,5 @@
 Ext.define('PVE.lxc.NetworkInputPanel', {
-    extend: 'PVE.panel.InputPanel',
+    extend: 'Proxmox.panel.InputPanel',
     alias: 'widget.pveLxcNetworkInputPanel',
 
     insideWizard: false,
@@ -7,59 +7,55 @@ Ext.define('PVE.lxc.NetworkInputPanel', {
     onlineHelp: 'pct_container_network',
 
     setNodename: function(nodename) {
-       var me = this;
-       
-       if (!nodename || (me.nodename === nodename)) {
+       let me = this;
+
+       if (!nodename || me.nodename === nodename) {
            return;
        }
-
        me.nodename = nodename;
 
-       var bridgesel = me.query("[isFormField][name=bridge]")[0];
-       bridgesel.setNodename(nodename);
+       let bridgeSelector = me.query("[isFormField][name=bridge]")[0];
+       bridgeSelector.setNodename(nodename);
     },
-    
+
     onGetValues: function(values) {
-       var me = this;
+       let me = this;
 
-       var id;
+       let id;
        if (me.isCreate) {
            id = values.id;
            delete values.id;
        } else {
            id = me.ifname;
        }
-
-       if (!id) {
-           return {};
-       }
-
-       var newdata = {};
-
-       if (values.ipv6mode !== 'static') {
-           values.ip6 = values.ipv6mode;
-       }
-       if (values.ipv4mode !== 'static') {
-           values.ip = values.ipv4mode;
+       let newdata = {};
+       if (id) {
+           if (values.ipv6mode !== 'static') {
+               values.ip6 = values.ipv6mode;
+           }
+           if (values.ipv4mode !== 'static') {
+               values.ip = values.ipv4mode;
+           }
+           newdata[id] = PVE.Parser.printLxcNetwork(values);
        }
-       newdata[id] = PVE.Parser.printLxcNetwork(values);
        return newdata;
     },
 
-    initComponent : function() {
-       var me = this;
-
-       if (!me.dataCache) {
-           throw "no dataCache specified";
-       }
-       
-       var cdata = {};
+    initComponent: function() {
+       let me = this;
 
+       let cdata = {};
        if (me.insideWizard) {
            me.ifname = 'net0';
            cdata.name = 'eth0';
+           me.dataCache = {};
+       }
+       cdata.firewall = me.insideWizard || me.isCreate;
+
+       if (!me.dataCache) {
+           throw "no dataCache specified";
        }
-       
+
        if (!me.isCreate) {
            if (!me.ifname) {
                throw "no interface name specified";
@@ -67,51 +63,42 @@ Ext.define('PVE.lxc.NetworkInputPanel', {
            if (!me.dataCache[me.ifname]) {
                throw "no such interface '" + me.ifname + "'";
            }
-
            cdata = PVE.Parser.parseLxcNetwork(me.dataCache[me.ifname]);
        }
 
-       var i;
-       for (i = 0; i < 10; i++) {
-           if (me.isCreate && !me.dataCache['net'+i.toString()]) {
-               me.ifname = 'net' + i.toString();
+       for (let i = 0; i < 32; i++) {
+           let ifname = 'net' + i.toString();
+           if (me.isCreate && !me.dataCache[ifname]) {
+               me.ifname = ifname;
                break;
            }
        }
 
-       var idselector = {
-           xtype: 'hidden',
-           name: 'id',
-           value: me.ifname
-       };
-
        me.column1 = [
-           idselector,
+           {
+               xtype: 'hidden',
+               name: 'id',
+               value: me.ifname,
+           },
            {
                xtype: 'textfield',
                name: 'name',
-               fieldLabel: gettext('Name') + ' (i.e. eth0)',
+               fieldLabel: gettext('Name'),
+               emptyText: '(e.g., eth0)',
                allowBlank: false,
                value: cdata.name,
                validator: function(value) {
-                   var result = '';
-                   Ext.Object.each(me.dataCache, function(key, netstr) {
+                   for (const [key, netRaw] of Object.entries(me.dataCache)) {
                        if (!key.match(/^net\d+/) || key === me.ifname) {
-                           return; // continue
+                           continue;
                        }
-                       var net = PVE.Parser.parseLxcNetwork(netstr);
+                       let net = PVE.Parser.parseLxcNetwork(netRaw);
                        if (net.name === value) {
-                           result = "interface name already in use";
-                           return false;
+                           return "interface name already in use";
                        }
-                   });
-                   if (result !== '') {
-                       return result;
                    }
-                   // validator can return bool/string
-                   /*jslint confusion:true*/
                    return true;
-               }
+               },
            },
            {
                xtype: 'textfield',
@@ -120,7 +107,7 @@ Ext.define('PVE.lxc.NetworkInputPanel', {
                vtype: 'MacAddress',
                value: cdata.hwaddr,
                allowBlank: true,
-               emptyText: 'auto'
+               emptyText: 'auto',
            },
            {
                xtype: 'PVE.form.BridgeSelector',
@@ -128,12 +115,12 @@ Ext.define('PVE.lxc.NetworkInputPanel', {
                nodename: me.nodename,
                fieldLabel: gettext('Bridge'),
                value: cdata.bridge,
-               allowBlank: false
+               allowBlank: false,
            },
            {
                xtype: 'pveVlanField',
                name: 'tag',
-               value: cdata.tag
+               value: cdata.tag,
            },
            {
                xtype: 'numberfield',
@@ -143,41 +130,41 @@ Ext.define('PVE.lxc.NetworkInputPanel', {
                maxValue: 10*1024,
                value: cdata.rate,
                emptyText: 'unlimited',
-               allowBlank: true
+               allowBlank: true,
            },
            {
-               xtype: 'pvecheckbox',
+               xtype: 'proxmoxcheckbox',
                fieldLabel: gettext('Firewall'),
                name: 'firewall',
-               checked: cdata.firewall
-           }
+               value: cdata.firewall,
+           },
        ];
 
-       var dhcp4 = (cdata.ip === 'dhcp');
+       let dhcp4 = cdata.ip === 'dhcp';
        if (dhcp4) {
            cdata.ip = '';
            cdata.gw = '';
        }
 
-       var auto6 = (cdata.ip6 === 'auto');
-       var dhcp6 = (cdata.ip6 === 'dhcp');
+       let auto6 = cdata.ip6 === 'auto';
+       let dhcp6 = cdata.ip6 === 'dhcp';
        if (auto6 || dhcp6) {
            cdata.ip6 = '';
            cdata.gw6 = '';
        }
-       
+
        me.column2 = [
            {
                layout: {
                    type: 'hbox',
-                   align: 'middle'
+                   align: 'middle',
                },
                border: false,
                margin: '0 0 5 0',
                items: [
                    {
                        xtype: 'label',
-                       text: 'IPv4:' // do not localize
+                       text: 'IPv4:', // do not localize
                    },
                    {
                        xtype: 'radiofield',
@@ -188,10 +175,13 @@ Ext.define('PVE.lxc.NetworkInputPanel', {
                        margin: '0 0 0 10',
                        listeners: {
                            change: function(cb, value) {
+                               me.down('field[name=ip]').setEmptyText(
+                                   value ? Proxmox.Utils.NoneText : "",
+                               );
                                me.down('field[name=ip]').setDisabled(!value);
                                me.down('field[name=gw]').setDisabled(!value);
-                           }
-                       }
+                           },
+                       },
                    },
                    {
                        xtype: 'radiofield',
@@ -199,17 +189,18 @@ Ext.define('PVE.lxc.NetworkInputPanel', {
                        name: 'ipv4mode',
                        inputValue: 'dhcp',
                        checked: dhcp4,
-                       margin: '0 0 0 10'
-                   }
-               ]
+                       margin: '0 0 0 10',
+                   },
+               ],
            },
            {
                xtype: 'textfield',
                name: 'ip',
                vtype: 'IPCIDRAddress',
                value: cdata.ip,
+               emptyText: dhcp4 ? '' : Proxmox.Utils.NoneText,
                disabled: dhcp4,
-               fieldLabel: 'IPv4/CIDR' // do not localize
+               fieldLabel: 'IPv4/CIDR', // do not localize
            },
            {
                xtype: 'textfield',
@@ -218,24 +209,24 @@ Ext.define('PVE.lxc.NetworkInputPanel', {
                vtype: 'IPAddress',
                disabled: dhcp4,
                fieldLabel: gettext('Gateway') + ' (IPv4)',
-               margin: '0 0 3 0' // override bottom margin to account for the menuseparator
+               margin: '0 0 3 0', // override bottom margin to account for the menuseparator
            },
            {
                xtype: 'menuseparator',
                height: '3',
-               margin: '0'
+               margin: '0',
            },
            {
                layout: {
                    type: 'hbox',
-                   align: 'middle'
+                   align: 'middle',
                },
                border: false,
                margin: '0 0 5 0',
                items: [
                    {
                        xtype: 'label',
-                       text: 'IPv6:' // do not localize
+                       text: 'IPv6:', // do not localize
                    },
                    {
                        xtype: 'radiofield',
@@ -246,10 +237,13 @@ Ext.define('PVE.lxc.NetworkInputPanel', {
                        margin: '0 0 0 10',
                        listeners: {
                            change: function(cb, value) {
+                               me.down('field[name=ip6]').setEmptyText(
+                                   value ? Proxmox.Utils.NoneText : "",
+                               );
                                me.down('field[name=ip6]').setDisabled(!value);
                                me.down('field[name=gw6]').setDisabled(!value);
-                           }
-                       }
+                           },
+                       },
                    },
                    {
                        xtype: 'radiofield',
@@ -257,7 +251,7 @@ Ext.define('PVE.lxc.NetworkInputPanel', {
                        name: 'ipv6mode',
                        inputValue: 'dhcp',
                        checked: dhcp6,
-                       margin: '0 0 0 10'
+                       margin: '0 0 0 10',
                    },
                    {
                        xtype: 'radiofield',
@@ -265,64 +259,64 @@ Ext.define('PVE.lxc.NetworkInputPanel', {
                        name: 'ipv6mode',
                        inputValue: 'auto',
                        checked: auto6,
-                       margin: '0 0 0 10'
-                   }
-               ]
+                       margin: '0 0 0 10',
+                   },
+               ],
            },
            {
                xtype: 'textfield',
                name: 'ip6',
                value: cdata.ip6,
+               emptyText: dhcp6 || auto6 ? '' : Proxmox.Utils.NoneText,
                vtype: 'IP6CIDRAddress',
-               disabled: (dhcp6 || auto6),
-               fieldLabel: 'IPv6/CIDR' // do not localize
+               disabled: dhcp6 || auto6,
+               fieldLabel: 'IPv6/CIDR', // do not localize
            },
            {
                xtype: 'textfield',
                name: 'gw6',
                vtype: 'IP6Address',
                value: cdata.gw6,
-               disabled: (dhcp6 || auto6),
-               fieldLabel: gettext('Gateway') + ' (IPv6)'
-           }
+               disabled: dhcp6 || auto6,
+               fieldLabel: gettext('Gateway') + ' (IPv6)',
+           },
        ];
 
        me.callParent();
-    }
+    },
 });
-       
 
 Ext.define('PVE.lxc.NetworkEdit', {
-    extend: 'PVE.window.Edit',
+    extend: 'Proxmox.window.Edit',
 
     isAdd: true,
 
-    initComponent : function() {
-       var me = this;
+    initComponent: function() {
+       let me = this;
 
        if (!me.dataCache) {
            throw "no dataCache specified";
        }
-
        if (!me.nodename) {
            throw "no node name specified";
        }
 
-       var ipanel = Ext.create('PVE.lxc.NetworkInputPanel', {
-           ifname: me.ifname,
-           nodename: me.nodename,
-           dataCache: me.dataCache,
-           isCreate: me.isCreate
-       });
-          
        Ext.apply(me, {
            subject: gettext('Network Device') + ' (veth)',
            digest: me.dataCache.digest,
-           items: [ ipanel ]
+           items: [
+               {
+                   xtype: 'pveLxcNetworkInputPanel',
+                   ifname: me.ifname,
+                   nodename: me.nodename,
+                   dataCache: me.dataCache,
+                   isCreate: me.isCreate,
+               },
+           ],
        });
 
        me.callParent();
-    }
+    },
 });
 
 Ext.define('PVE.lxc.NetworkView', {
@@ -337,7 +331,7 @@ Ext.define('PVE.lxc.NetworkView', {
     stateId: 'grid-lxc-network',
 
     load: function() {
-       var me = this;
+       let me = this;
 
        Proxmox.Utils.setErrorMask(me, true);
 
@@ -348,113 +342,69 @@ Ext.define('PVE.lxc.NetworkView', {
            },
            success: function(response, opts) {
                Proxmox.Utils.setErrorMask(me, false);
-               var result = Ext.decode(response.responseText);
-               var data = result.data || {};
-               me.dataCache = data;
-               var records = [];
-               Ext.Object.each(data, function(key, value) {
-                   if (!key.match(/^net\d+/)) {
-                       return; // continue
+               let result = Ext.decode(response.responseText);
+               me.dataCache = result.data || {};
+               let records = [];
+               for (const [key, value] of Object.entries(me.dataCache)) {
+                   if (key.match(/^net\d+/)) {
+                       let net = PVE.Parser.parseLxcNetwork(value);
+                       net.id = key;
+                       records.push(net);
                    }
-                   var net = PVE.Parser.parseLxcNetwork(value);
-                   net.id = key;
-                   records.push(net);
-               });
+               }
                me.store.loadData(records);
-               me.down('button[name=addButton]').setDisabled((records.length >= 10));
-           }
+               me.down('button[name=addButton]').setDisabled(records.length >= 32);
+           },
        });
     },
 
-    initComponent : function() {
-       var me = this;
+    initComponent: function() {
+       let me = this;
 
-       var nodename = me.pveSelNode.data.node;
+       let nodename = me.pveSelNode.data.node;
        if (!nodename) {
            throw "no node name specified";
        }
 
-       var vmid = me.pveSelNode.data.vmid;
+       let vmid = me.pveSelNode.data.vmid;
        if (!vmid) {
            throw "no VM ID specified";
        }
 
-       var caps = Ext.state.Manager.get('GuiCap');
+       let caps = Ext.state.Manager.get('GuiCap');
 
-       me.url = '/nodes/' + nodename + '/lxc/' + vmid + '/config';
+       me.url = `/nodes/${nodename}/lxc/${vmid}/config`;
 
-       var store = new Ext.data.Store({
+       let store = new Ext.data.Store({
            model: 'pve-lxc-network',
            sorters: [
                {
-                   property : 'id',
-                   direction: 'ASC'
-               }
-           ]
-       });
-
-       var sm = Ext.create('Ext.selection.RowModel', {});
-
-       var remove_btn = new Proxmox.button.Button({
-           text: gettext('Remove'),
-           disabled: true,
-           selModel: sm,
-           enableFn: function(rec) {
-               return !!caps.vms['VM.Config.Network'];
-           },
-           confirmMsg: function (rec) {
-               return Ext.String.format(gettext('Are you sure you want to remove entry {0}'),
-                                        "'" + rec.data.id + "'");
-           },
-           handler: function(btn, event, rec) {
-               Proxmox.Utils.API2Request({
-                   url: me.url,
-                   waitMsgTarget: me,
-                   method: 'PUT',
-                   params: { 'delete': rec.data.id,  digest: me.dataCache.digest },
-                   callback: function() {
-                       me.load();
-                   },
-                   failure: function (response, opts) {
-                       Ext.Msg.alert(gettext('Error'), response.htmlStatus);
-                   }
-               });
-           }
+                   property: 'id',
+                   direction: 'ASC',
+               },
+           ],
        });
 
-       var run_editor = function() {
-           var rec = sm.getSelection()[0];
-           if (!rec) {
-               return;
-           }
+       let sm = Ext.create('Ext.selection.RowModel', {});
 
-           if (!caps.vms['VM.Config.Network']) {
-               return false;
+       let run_editor = function() {
+           let rec = sm.getSelection()[0];
+           if (!rec || !caps.vms['VM.Config.Network']) {
+               return false; // disable default-propagation when triggered by grid dblclick
            }
-
-           var win = Ext.create('PVE.lxc.NetworkEdit', {
+           Ext.create('PVE.lxc.NetworkEdit', {
                url: me.url,
                nodename: nodename,
                dataCache: me.dataCache,
-               ifname: rec.data.id
+               ifname: rec.data.id,
+               listeners: {
+                   destroy: () => me.load(),
+               },
+               autoShow: true,
            });
-           win.on('destroy', me.load, me);
-           win.show();
+           return undefined; // make eslint happier
        };
 
-       var edit_btn = new Proxmox.button.Button({
-           text: gettext('Edit'),
-           selModel: sm,
-           disabled: true,
-           enableFn: function(rec) {
-               if (!caps.vms['VM.Config.Network']) {
-                   return false;
-               }
-               return true;
-           },
-           handler: run_editor
-       });
-
        Ext.apply(me, {
            store: store,
            selModel: sm,
@@ -464,50 +414,82 @@ Ext.define('PVE.lxc.NetworkView', {
                    name: 'addButton',
                    disabled: !caps.vms['VM.Config.Network'],
                    handler: function() {
-                       var win = Ext.create('PVE.lxc.NetworkEdit', {
+                       Ext.create('PVE.lxc.NetworkEdit', {
                            url: me.url,
                            nodename: nodename,
                            isCreate: true,
-                           dataCache: me.dataCache
+                           dataCache: me.dataCache,
+                           listeners: {
+                               destroy: () => me.load(),
+                           },
+                           autoShow: true,
                        });
-                       win.on('destroy', me.load, me);
-                       win.show();
-                   }
+                   },
+               },
+               {
+                   xtype: 'proxmoxButton',
+                   text: gettext('Remove'),
+                   disabled: true,
+                   selModel: sm,
+                   enableFn: function(rec) {
+                       return !!caps.vms['VM.Config.Network'];
+                   },
+                   confirmMsg: ({ data }) =>
+                       Ext.String.format(gettext('Are you sure you want to remove entry {0}'), `'${data.id}'`),
+                   handler: function(btn, e, rec) {
+                       Proxmox.Utils.API2Request({
+                           url: me.url,
+                           waitMsgTarget: me,
+                           method: 'PUT',
+                           params: {
+                               'delete': rec.data.id,
+                               digest: me.dataCache.digest,
+                           },
+                           callback: () => me.load(),
+                           failure: (response, opts) => Ext.Msg.alert(gettext('Error'), response.htmlStatus),
+                       });
+                   },
+               },
+               {
+                   xtype: 'proxmoxButton',
+                   text: gettext('Edit'),
+                   selModel: sm,
+                   disabled: true,
+                   enableFn: rec => !!caps.vms['VM.Config.Network'],
+                   handler: run_editor,
                },
-               remove_btn,
-               edit_btn
            ],
            columns: [
                {
                    header: 'ID',
                    width: 50,
-                   dataIndex: 'id'
+                   dataIndex: 'id',
                },
                {
                    header: gettext('Name'),
                    width: 80,
-                   dataIndex: 'name'
+                   dataIndex: 'name',
                },
                {
                    header: gettext('Bridge'),
                    width: 80,
-                   dataIndex: 'bridge'
+                   dataIndex: 'bridge',
                },
                {
                    header: gettext('Firewall'),
                    width: 80,
                    dataIndex: 'firewall',
-                   renderer: Proxmox.Utils.format_boolean
+                   renderer: Proxmox.Utils.format_boolean,
                },
                {
                    header: gettext('VLAN Tag'),
                    width: 80,
-                   dataIndex: 'tag'
+                   dataIndex: 'tag',
                },
                {
                    header: gettext('MAC address'),
                    width: 110,
-                   dataIndex: 'hwaddr'
+                   dataIndex: 'hwaddr',
                },
                {
                    header: gettext('IP address'),
@@ -521,7 +503,7 @@ Ext.define('PVE.lxc.NetworkView', {
                        } else {
                            return rec.data.ip;
                        }
-                   }
+                   },
                },
                {
                    header: gettext('Gateway'),
@@ -535,25 +517,33 @@ Ext.define('PVE.lxc.NetworkView', {
                        } else {
                            return rec.data.gw;
                        }
-                   }
-               }
+                   },
+               },
            ],
            listeners: {
                activate: me.load,
-               itemdblclick: run_editor
-           }
+               itemdblclick: run_editor,
+           },
        });
 
        me.callParent();
-   }
+   },
 }, function() {
-
     Ext.define('pve-lxc-network', {
        extend: "Ext.data.Model",
        proxy: { type: 'memory' },
-       fields: [ 'id', 'name', 'hwaddr', 'bridge',
-                 'ip', 'gw', 'ip6', 'gw6', 'tag', 'firewall' ]
+       fields: [
+           'id',
+           'name',
+           'hwaddr',
+           'bridge',
+           'ip',
+           'gw',
+           'ip6',
+           'gw6',
+           'tag',
+           'firewall',
+       ],
     });
-
 });