From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from firstgate.proxmox.com (firstgate.proxmox.com [212.224.123.68]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by lists.proxmox.com (Postfix) with ESMTPS id 8303969BFD for ; Sun, 14 Feb 2021 13:08:50 +0100 (CET) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id 3812831DA2 for ; Sun, 14 Feb 2021 13:08:50 +0100 (CET) Received: from kvmformation1.odiso.net (globalOdiso.M6Lille.odiso.net [89.248.211.242]) by firstgate.proxmox.com (Proxmox) with ESMTP id C967F31D7A for ; Sun, 14 Feb 2021 13:08:43 +0100 (CET) Received: by kvmformation1.odiso.net (Postfix, from userid 0) id 6527CACB76; Sun, 14 Feb 2021 13:08:36 +0100 (CET) From: Alexandre Derumier To: pve-devel@lists.proxmox.com Date: Sun, 14 Feb 2021 13:08:30 +0100 Message-Id: <20210214120830.2154191-2-aderumier@odiso.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20210214120830.2154191-1-aderumier@odiso.com> References: <20210214120830.2154191-1-aderumier@odiso.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-SPAM-LEVEL: Spam detection results: 1 AWL -0.189 Adjusted score from AWL reputation of From: address HEADER_FROM_DIFFERENT_DOMAINS 0.25 From and EnvelopeFrom 2nd level mail domains are different KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment KAM_LAZY_DOMAIN_SECURITY 1 Sending domain does not have any anti-forgery methods KHOP_HELO_FCRDNS 0.4 Relay HELO differs from its IP's reverse DNS NO_DNS_FOR_FROM 0.379 Envelope sender has no MX or A DNS records SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_NONE 0.001 SPF: sender does not publish an SPF Record Subject: [pve-devel] [PATCH V11 pve-manager 1/1] sdn: add subnet/ipam/sdn management X-BeenThere: pve-devel@lists.proxmox.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: Proxmox VE development discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 14 Feb 2021 12:08:50 -0000 Signed-off-by: Alexandre Derumier --- www/manager6/Makefile | 16 +++ www/manager6/Utils.js | 104 ++++++++++++++ www/manager6/dc/Config.js | 18 +-- www/manager6/form/SDNDnsSelector.js | 52 +++++++ www/manager6/form/SDNIpamSelector.js | 52 +++++++ www/manager6/form/SDNVnetSelector.js | 68 +++++++++ www/manager6/sdn/Browser.js | 4 +- www/manager6/sdn/ControllerView.js | 43 +++++- www/manager6/sdn/DnsView.js | 132 ++++++++++++++++++ www/manager6/sdn/IpamView.js | 133 ++++++++++++++++++ www/manager6/sdn/OptionsPanel.js | 41 ++++++ www/manager6/sdn/Status.js | 2 +- www/manager6/sdn/SubnetEdit.js | 104 ++++++++++++++ www/manager6/sdn/SubnetView.js | 169 +++++++++++++++++++++++ www/manager6/sdn/VnetEdit.js | 37 ++--- www/manager6/sdn/VnetPanel.js | 39 ++++++ www/manager6/sdn/VnetView.js | 77 ++++++----- www/manager6/sdn/ZoneContentView.js | 15 +- www/manager6/sdn/ZoneView.js | 76 +++++++++- www/manager6/sdn/controllers/BgpEdit.js | 62 +++++++++ www/manager6/sdn/controllers/EvpnEdit.js | 13 -- www/manager6/sdn/dns/Base.js | 73 ++++++++++ www/manager6/sdn/dns/PowerdnsEdit.js | 52 +++++++ www/manager6/sdn/ipams/Base.js | 73 ++++++++++ www/manager6/sdn/ipams/NetboxEdit.js | 46 ++++++ www/manager6/sdn/ipams/PVEIpamEdit.js | 34 +++++ www/manager6/sdn/ipams/PhpIpamEdit.js | 52 +++++++ www/manager6/sdn/zones/Base.js | 60 ++++++-- www/manager6/sdn/zones/EvpnEdit.js | 105 +++++++------- www/manager6/sdn/zones/SimpleEdit.js | 16 +-- www/manager6/sdn/zones/VlanEdit.js | 14 +- www/manager6/sdn/zones/VxlanEdit.js | 81 ++++++----- 32 files changed, 1646 insertions(+), 217 deletions(-) create mode 100644 www/manager6/form/SDNDnsSelector.js create mode 100644 www/manager6/form/SDNIpamSelector.js create mode 100644 www/manager6/form/SDNVnetSelector.js create mode 100644 www/manager6/sdn/DnsView.js create mode 100644 www/manager6/sdn/IpamView.js create mode 100644 www/manager6/sdn/OptionsPanel.js create mode 100644 www/manager6/sdn/SubnetEdit.js create mode 100644 www/manager6/sdn/SubnetView.js create mode 100644 www/manager6/sdn/VnetPanel.js create mode 100644 www/manager6/sdn/controllers/BgpEdit.js create mode 100644 www/manager6/sdn/dns/Base.js create mode 100644 www/manager6/sdn/dns/PowerdnsEdit.js create mode 100644 www/manager6/sdn/ipams/Base.js create mode 100644 www/manager6/sdn/ipams/NetboxEdit.js create mode 100644 www/manager6/sdn/ipams/PVEIpamEdit.js create mode 100644 www/manager6/sdn/ipams/PhpIpamEdit.js diff --git a/www/manager6/Makefile b/www/manager6/Makefile index 85f90ecd..b4419f07 100644 --- a/www/manager6/Makefile +++ b/www/manager6/Makefile @@ -52,6 +52,9 @@ JSSRC= \ form/QemuBiosSelector.js \ form/SDNControllerSelector.js \ form/SDNZoneSelector.js \ + form/SDNVnetSelector.js \ + form/SDNIpamSelector.js \ + form/SDNDnsSelector.js \ form/ScsiHwSelector.js \ form/SecurityGroupSelector.js \ form/SnapshotSelector.js \ @@ -226,10 +229,23 @@ JSSRC= \ sdn/StatusView.js \ sdn/VnetEdit.js \ sdn/VnetView.js \ + sdn/VnetPanel.js \ + sdn/SubnetEdit.js \ + sdn/SubnetView.js \ sdn/ZoneContentView.js \ sdn/ZoneView.js \ + sdn/OptionsPanel.js \ sdn/controllers/Base.js \ sdn/controllers/EvpnEdit.js \ + sdn/controllers/BgpEdit.js \ + sdn/IpamView.js \ + sdn/ipams/Base.js \ + sdn/ipams/NetboxEdit.js \ + sdn/ipams/PVEIpamEdit.js \ + sdn/ipams/PhpIpamEdit.js \ + sdn/DnsView.js \ + sdn/dns/Base.js \ + sdn/dns/PowerdnsEdit.js \ sdn/zones/Base.js \ sdn/zones/EvpnEdit.js \ sdn/zones/QinQEdit.js \ diff --git a/www/manager6/Utils.js b/www/manager6/Utils.js index ab4988b0..2225e5ad 100644 --- a/www/manager6/Utils.js +++ b/www/manager6/Utils.js @@ -175,6 +175,54 @@ Ext.define('PVE.Utils', { 'HEALTH_ERR': 'critical', }, + render_sdn_pending: function(rec,value,key, index) { + if (rec.data.state === undefined || rec.data.state === null) { + return value; + } + + if (rec.data.state === 'deleted') { + if (value === undefined) { + return ' '; + } else { + return '
'+ value +'
'; + } + } else { + + if (rec.data.pending[key] !== undefined && rec.data.pending[key] !== null) { + if (rec.data.pending[key] === 'deleted') { + return ' '; + } else { + return rec.data.pending[key]; + } + } else { + return value; + } + } + return value; + }, + + render_sdn_pending_state: function(rec,value) { + + if (value === undefined || value === null) { + return ' '; + } + + let icon = ``; + + if (value === 'deleted') { + return '' + icon + value + ''; + } + + let tip = 'Pending apply:
'; + + for (const [key, keyvalue] of Object.entries(rec.data.pending)) { + if (((rec.data[key] !== undefined && rec.data.pending[key] !== rec.data[key]) || rec.data[key] === undefined)) { + tip = tip + `${key}: ${keyvalue}
`; + } + } + return ''+ icon + value + ''; + }, + render_ceph_health: function(healthObj) { var state = { iconCls: PVE.Utils.get_health_icon(), @@ -851,6 +899,46 @@ Ext.define('PVE.Utils', { ipanel: 'EvpnInputPanel', faIcon: 'crosshairs', }, + bgp: { + name: 'bgp', + ipanel: 'BgpInputPanel', + faIcon: 'crosshairs' + }, + }, + + sdnipamSchema: { + ipam: { + name: 'ipam', + hideAdd: true + }, + pve: { + name: 'PVE', + ipanel: 'PVEIpamInputPanel', + faIcon: 'th', + hideAdd: true + }, + netbox: { + name: 'Netbox', + ipanel: 'NetboxInputPanel', + faIcon: 'th' + }, + phpipam: { + name: 'PhpIpam', + ipanel: 'PhpIpamInputPanel', + faIcon: 'th' + }, + }, + + sdndnsSchema: { + dns: { + name: 'dns', + hideAdd: true + }, + powerdns: { + name: 'powerdns', + ipanel: 'PowerdnsInputPanel', + faIcon: 'th' + }, }, format_sdnvnet_type: function(value, md, record) { @@ -877,6 +965,22 @@ Ext.define('PVE.Utils', { return Proxmox.Utils.unknownText; }, + format_sdnipam_type: function(value, md, record) { + var schema = PVE.Utils.sdnipamSchema[value]; + if (schema) { + return schema.name; + } + return Proxmox.Utils.unknownText; + }, + + format_sdndns_type: function(value, md, record) { + var schema = PVE.Utils.sdndnsSchema[value]; + if (schema) { + return schema.name; + } + return Proxmox.Utils.unknownText; + }, + format_storage_type: function(value, md, record) { if (value === 'rbd') { value = !record || record.get('monhost') ? 'rbd' : 'pveceph'; diff --git a/www/manager6/dc/Config.js b/www/manager6/dc/Config.js index 24ecabb6..8c850a23 100644 --- a/www/manager6/dc/Config.js +++ b/www/manager6/dc/Config.js @@ -153,14 +153,6 @@ Ext.define('PVE.dc.Config', { itemId: 'sdn', expandedOnInit: true, }, - { - xtype: 'pveSDNControllerView', - groups: ['sdn'], - title: gettext('Controllers'), - hidden: true, - iconCls: 'fa fa-crosshairs', - itemId: 'sdncontroller', - }, { xtype: 'pveSDNZoneView', groups: ['sdn'], @@ -170,12 +162,20 @@ Ext.define('PVE.dc.Config', { itemId: 'sdnzone', }, { - xtype: 'pveSDNVnetView', + xtype: 'pveSDNVnet', groups: ['sdn'], title: gettext('Vnets'), hidden: true, iconCls: 'fa fa-network-wired', itemId: 'sdnvnet', + }, + { + xtype: 'pveSDNOptions', + groups: ['sdn'], + title: gettext('Options'), + hidden: true, + iconCls: 'fa fa-gear', + itemId: 'sdnoptions' }); } diff --git a/www/manager6/form/SDNDnsSelector.js b/www/manager6/form/SDNDnsSelector.js new file mode 100644 index 00000000..7abb1f01 --- /dev/null +++ b/www/manager6/form/SDNDnsSelector.js @@ -0,0 +1,52 @@ +Ext.define('PVE.form.SDNDnsSelector', { + extend: 'Proxmox.form.ComboGrid', + alias: ['widget.pveSDNDnsSelector'], + + allowBlank: false, + valueField: 'dns', + displayField: 'dns', + + initComponent: function() { + var me = this; + + var store = new Ext.data.Store({ + model: 'pve-sdn-dns', + sorters: { + property: 'dns', + order: 'DESC' + }, + }); + + Ext.apply(me, { + store: store, + autoSelect: false, + listConfig: { + columns: [ + { + header: gettext('dns'), + sortable: true, + dataIndex: 'dns', + flex: 1 + }, + ] + } + }); + + me.callParent(); + + store.load(); + } + +}, function() { + + Ext.define('pve-sdn-dns', { + extend: 'Ext.data.Model', + fields: [ 'dns' ], + proxy: { + type: 'proxmox', + url: "/api2/json/cluster/sdn/dns" + }, + idProperty: 'dns' + }); + +}); diff --git a/www/manager6/form/SDNIpamSelector.js b/www/manager6/form/SDNIpamSelector.js new file mode 100644 index 00000000..5520d0fe --- /dev/null +++ b/www/manager6/form/SDNIpamSelector.js @@ -0,0 +1,52 @@ +Ext.define('PVE.form.SDNIpamSelector', { + extend: 'Proxmox.form.ComboGrid', + alias: ['widget.pveSDNIpamSelector'], + + allowBlank: false, + valueField: 'ipam', + displayField: 'ipam', + + initComponent: function() { + var me = this; + + var store = new Ext.data.Store({ + model: 'pve-sdn-ipam', + sorters: { + property: 'ipam', + order: 'DESC' + }, + }); + + Ext.apply(me, { + store: store, + autoSelect: false, + listConfig: { + columns: [ + { + header: gettext('Ipam'), + sortable: true, + dataIndex: 'ipam', + flex: 1 + }, + ] + } + }); + + me.callParent(); + + store.load(); + } + +}, function() { + + Ext.define('pve-sdn-ipam', { + extend: 'Ext.data.Model', + fields: [ 'ipam' ], + proxy: { + type: 'proxmox', + url: "/api2/json/cluster/sdn/ipams" + }, + idProperty: 'ipam' + }); + +}); diff --git a/www/manager6/form/SDNVnetSelector.js b/www/manager6/form/SDNVnetSelector.js new file mode 100644 index 00000000..0f9a6613 --- /dev/null +++ b/www/manager6/form/SDNVnetSelector.js @@ -0,0 +1,68 @@ +Ext.define('PVE.form.SDNVnetSelector', { + extend: 'Proxmox.form.ComboGrid', + alias: ['widget.pveSDNVnetSelector'], + + allowBlank: false, + valueField: 'vnet', + displayField: 'vnet', + + initComponent: function() { + var me = this; + + var store = new Ext.data.Store({ + model: 'pve-sdn-vnet', + sorters: { + property: 'vnet', + order: 'DESC' + }, + }); + + Ext.apply(me, { + store: store, + autoSelect: false, + listConfig: { + columns: [ + { + header: gettext('Vnet'), + sortable: true, + dataIndex: 'vnet', + flex: 1 + }, + { + header: gettext('Alias'), + flex: 1, + dataIndex: 'alias', + }, + { + header: gettext('Tag'), + flex: 1, + dataIndex: 'tag', + } + ] + } + }); + + me.callParent(); + + store.load(); + } + +}, function() { + + Ext.define('pve-sdn-vnet', { + extend: 'Ext.data.Model', + fields: [ + 'alias', + 'tag', + 'type', + 'vnet', + 'zone', + ], + proxy: { + type: 'proxmox', + url: "/api2/json/cluster/sdn/vnets" + }, + idProperty: 'vnet' + }); + +}); diff --git a/www/manager6/sdn/Browser.js b/www/manager6/sdn/Browser.js index 35a5d13a..bb30cbe0 100644 --- a/www/manager6/sdn/Browser.js +++ b/www/manager6/sdn/Browser.js @@ -2,8 +2,10 @@ Ext.define('PVE.sdn.Browser', { extend: 'PVE.panel.Config', alias: 'widget.PVE.sdn.Browser', + onlineHelp: 'chapter_pvesdn', + initComponent: function() { - var me = this; + var me = this; var nodename = me.pveSelNode.data.node; if (!nodename) { diff --git a/www/manager6/sdn/ControllerView.js b/www/manager6/sdn/ControllerView.js index 90a76df3..ee4b6853 100644 --- a/www/manager6/sdn/ControllerView.js +++ b/www/manager6/sdn/ControllerView.js @@ -2,7 +2,7 @@ Ext.define('PVE.sdn.ControllerView', { extend: 'Ext.grid.GridPanel', alias: ['widget.pveSDNControllerView'], - onlineHelp: 'pvesdn_controller_plugins', + onlineHelp: 'pvesdn_config_controllers', stateful: true, stateId: 'grid-sdn-controller', @@ -30,8 +30,8 @@ Ext.define('PVE.sdn.ControllerView', { var store = new Ext.data.Store({ model: 'pve-sdn-controller', proxy: { - type: 'proxmox', - url: "/api2/json/cluster/sdn/controllers", + type: 'proxmox', + url: "/api2/json/cluster/sdn/controllers?pending=1", }, sorters: { property: 'controller', @@ -45,6 +45,16 @@ Ext.define('PVE.sdn.ControllerView', { var sm = Ext.create('Ext.selection.RowModel', {}); + var set_button_status = function() { + var rec = me.selModel.getSelection()[0]; + + if (!rec || rec.data.state === 'deleted') { + edit_btn.disable(); + remove_btn.disable(); + return; + } + }; + var run_editor = function() { var rec = sm.getSelection()[0]; if (!rec) { @@ -110,21 +120,44 @@ Ext.define('PVE.sdn.ControllerView', { flex: 2, sortable: true, dataIndex: 'controller', + dataIndex: 'controller', + renderer: function(value, metaData, rec) { + return PVE.Utils.render_sdn_pending(rec, value, 'controller', 1); + } }, { header: gettext('Type'), flex: 1, sortable: true, dataIndex: 'type', - renderer: PVE.Utils.format_sdncontroller_type, + renderer: function(value, metaData, rec) { + return PVE.Utils.render_sdn_pending(rec, value, 'type', 1); + } }, + { + header: gettext('Node'), + flex: 1, + sortable: true, + dataIndex: 'node', + renderer: function(value, metaData, rec) { + return PVE.Utils.render_sdn_pending(rec, value, 'node', 1); + } + }, + { + header: gettext('State'), + width: 100, + dataIndex: 'state', + renderer: function(value, metaData, rec) { + return PVE.Utils.render_sdn_pending_state(rec, value); + } + } ], listeners: { activate: reload, itemdblclick: run_editor, }, }); - + store.load(); me.callParent(); }, }); diff --git a/www/manager6/sdn/DnsView.js b/www/manager6/sdn/DnsView.js new file mode 100644 index 00000000..2b36b0e0 --- /dev/null +++ b/www/manager6/sdn/DnsView.js @@ -0,0 +1,132 @@ +Ext.define('PVE.sdn.DnsView', { + extend: 'Ext.grid.GridPanel', + alias: ['widget.pveSDNDnsView'], + + stateful: true, + stateId: 'grid-sdn-dns', + + createSDNEditWindow: function(type, sid) { + let schema = PVE.Utils.sdndnsSchema[type]; + if (!schema || !schema.ipanel) { + throw "no editor registered for dns type: " + type; + } + + Ext.create('PVE.sdn.dns.BaseEdit', { + paneltype: 'PVE.sdn.dns.' + schema.ipanel, + type: type, + dns: sid, + autoShow: true, + listeners: { + destroy: this.reloadStore + } + }); + }, + + initComponent : function() { + let me = this; + + let store = new Ext.data.Store({ + model: 'pve-sdn-dns', + proxy: { + type: 'proxmox', + url: "/api2/json/cluster/sdn/dns" + }, + sorters: { + property: 'dns', + order: 'DESC' + }, + }); + + let reload = function() { + store.load(); + }; + + let sm = Ext.create('Ext.selection.RowModel', {}); + + let run_editor = function() { + let rec = sm.getSelection()[0]; + if (!rec) { + return; + } + let type = rec.data.type, + dns = rec.data.dns; + + me.createSDNEditWindow(type, dns); + }; + + let edit_btn = new Proxmox.button.Button({ + text: gettext('Edit'), + disabled: true, + selModel: sm, + handler: run_editor + }); + + let remove_btn = Ext.create('Proxmox.button.StdRemoveButton', { + selModel: sm, + baseurl: '/cluster/sdn/dns/', + callback: reload + }); + + // else we cannot dynamically generate the add menu handlers + let addHandleGenerator = function(type) { + return function() { me.createSDNEditWindow(type); }; + }; + let addMenuItems = [], type; + + for (type in PVE.Utils.sdndnsSchema) { + let dns = PVE.Utils.sdndnsSchema[type]; + if (dns.hideAdd) { + continue; + } + addMenuItems.push({ + text: PVE.Utils.format_sdndns_type(type), + iconCls: 'fa fa-fw fa-' + dns.faIcon, + handler: addHandleGenerator(type) + }); + } + + Ext.apply(me, { + store: store, + reloadStore: reload, + selModel: sm, + viewConfig: { + trackOver: false + }, + tbar: [ + { + text: gettext('Add'), + menu: new Ext.menu.Menu({ + items: addMenuItems + }) + }, + remove_btn, + edit_btn, + ], + columns: [ + { + header: 'ID', + flex: 2, + dataIndex: 'dns' + }, + { + header: gettext('Type'), + flex: 1, + dataIndex: 'type', + renderer: PVE.Utils.format_sdndns_type + }, + { + header: 'url', + flex: 1, + dataIndex: 'url', + }, + ], + listeners: { + activate: reload, + itemdblclick: run_editor + } + }); + + store.load(); + me.callParent(); + } +}); diff --git a/www/manager6/sdn/IpamView.js b/www/manager6/sdn/IpamView.js new file mode 100644 index 00000000..0abf144a --- /dev/null +++ b/www/manager6/sdn/IpamView.js @@ -0,0 +1,133 @@ +Ext.define('PVE.sdn.IpamView', { + extend: 'Ext.grid.GridPanel', + alias: ['widget.pveSDNIpamView'], + + stateful: true, + stateId: 'grid-sdn-ipam', + + createSDNEditWindow: function(type, sid) { + let schema = PVE.Utils.sdnipamSchema[type]; + if (!schema || !schema.ipanel) { + throw "no editor registered for ipam type: " + type; + } + + Ext.create('PVE.sdn.ipams.BaseEdit', { + paneltype: 'PVE.sdn.ipams.' + schema.ipanel, + type: type, + ipam: sid, + autoShow: true, + listeners: { + destroy: this.reloadStore + } + }); + }, + + initComponent : function() { + let me = this; + + let store = new Ext.data.Store({ + model: 'pve-sdn-ipam', + proxy: { + type: 'proxmox', + url: "/api2/json/cluster/sdn/ipams" + }, + sorters: { + property: 'ipam', + order: 'DESC' + }, + }); + + let reload = function() { + store.load(); + }; + + let sm = Ext.create('Ext.selection.RowModel', {}); + + let run_editor = function() { + let rec = sm.getSelection()[0]; + if (!rec) { + return; + } + let type = rec.data.type, + ipam = rec.data.ipam; + + me.createSDNEditWindow(type, ipam); + }; + + let edit_btn = new Proxmox.button.Button({ + text: gettext('Edit'), + disabled: true, + selModel: sm, + handler: run_editor + }); + + let remove_btn = Ext.create('Proxmox.button.StdRemoveButton', { + selModel: sm, + baseurl: '/cluster/sdn/ipams/', + callback: reload + }); + + // else we cannot dynamically generate the add menu handlers + let addHandleGenerator = function(type) { + return function() { me.createSDNEditWindow(type); }; + }; + let addMenuItems = [], type; + + for (type in PVE.Utils.sdnipamSchema) { + let ipam = PVE.Utils.sdnipamSchema[type]; + if (ipam.hideAdd) { + continue; + } + addMenuItems.push({ + text: PVE.Utils.format_sdnipam_type(type), + iconCls: 'fa fa-fw fa-' + ipam.faIcon, + handler: addHandleGenerator(type) + }); + } + + Ext.apply(me, { + store: store, + reloadStore: reload, + selModel: sm, + viewConfig: { + trackOver: false + }, + tbar: [ + { + text: gettext('Add'), + menu: new Ext.menu.Menu({ + items: addMenuItems + }) + }, + remove_btn, + edit_btn, + ], + columns: [ + { + header: 'ID', + flex: 2, + dataIndex: 'ipam' + }, + { + header: gettext('Type'), + flex: 1, + dataIndex: 'type', + renderer: PVE.Utils.format_sdnipam_type + }, + { + header: 'url', + flex: 1, + dataIndex: 'url', + }, + ], + listeners: { + activate: reload, + itemdblclick: run_editor + } + }); + + store.load(); + me.callParent(); + + } +}); diff --git a/www/manager6/sdn/OptionsPanel.js b/www/manager6/sdn/OptionsPanel.js new file mode 100644 index 00000000..5f3b583f --- /dev/null +++ b/www/manager6/sdn/OptionsPanel.js @@ -0,0 +1,41 @@ +Ext.define('PVE.sdn.Options', { + extend: 'Ext.panel.Panel', + alias: 'widget.pveSDNOptions', + + title: 'Options', + + layout: { + type: 'vbox', + align: 'stretch' + }, + + onlineHelp: 'pvesdn_config_controllers', + + initComponent: function() { + var me = this; + + me.items = [ + { + xtype: 'pveSDNControllerView', + title: gettext('Controllers'), + border: 0, + collapsible: true, + padding: '0 0 20 0' + }, + { + xtype: 'pveSDNIpamView', + title: gettext('Ipams'), + border: 0, + collapsible: true, + padding: '0 0 20 0' + },{ + xtype: 'pveSDNDnsView', + flex: 1, + collapsible: true, + title: gettext('Dns'), + border: 0, + }]; + + me.callParent(); + } +}); diff --git a/www/manager6/sdn/Status.js b/www/manager6/sdn/Status.js index 858d09bd..0fdcfda0 100644 --- a/www/manager6/sdn/Status.js +++ b/www/manager6/sdn/Status.js @@ -18,7 +18,7 @@ Ext.define('PVE.sdn.Status', { storeid: 'pve-store-' + ++Ext.idSeed, groupField: 'type', proxy: { - type: 'proxmox', + type: 'proxmox', url: '/api2/json/cluster/resources', }, }); diff --git a/www/manager6/sdn/SubnetEdit.js b/www/manager6/sdn/SubnetEdit.js new file mode 100644 index 00000000..83c6961c --- /dev/null +++ b/www/manager6/sdn/SubnetEdit.js @@ -0,0 +1,104 @@ +Ext.define('PVE.sdn.SubnetInputPanel', { + extend: 'Proxmox.panel.InputPanel', + mixins: ['Proxmox.Mixin.CBind'], + + onGetValues: function(values) { + let me = this; + + if (me.isCreate) { + values.type = 'subnet'; + values.subnet = values.cidr; + delete values.cidr; + } + + if (!values.gateway) { + delete values.gateway; + } + if (!values.snat) { + delete values.snat; + } + + return values; + }, + + items: [ + { + xtype: 'pmxDisplayEditField', + name: 'cidr', + cbind: { + editable: '{isCreate}', + }, + flex: 1, + allowBlank: false, + fieldLabel: gettext('Subnet'), + }, + { + xtype: 'textfield', + name: 'gateway', + vtype: 'IP64Address', + fieldLabel: gettext('Gateway'), + allowBlank: true, + }, + { + xtype: 'proxmoxcheckbox', + name: 'snat', + uncheckedValue: 0, + checked: false, + fieldLabel: 'SNAT' + }, + { + xtype: 'proxmoxtextfield', + name: 'dnszoneprefix', + skipEmptyText: true, + fieldLabel: gettext('DNS zone prefix'), + allowBlank: true + } + ] +}); + +Ext.define('PVE.sdn.SubnetEdit', { + extend: 'Proxmox.window.Edit', + + subject: gettext('Subnet'), + + subnet: undefined, + + width: 350, + + base_url: undefined, + + initComponent: function() { + var me = this; + + me.isCreate = me.subnet === undefined; + + if (me.isCreate) { + me.url = me.base_url; + me.method = 'POST'; + } else { + me.url = me.base_url + '/' + me.subnet; + me.method = 'PUT'; + } + + let ipanel = Ext.create('PVE.sdn.SubnetInputPanel', { + isCreate: me.isCreate, + }); + + Ext.apply(me, { + items: [ + ipanel, + ], + }); + + me.callParent(); + + if (!me.isCreate) { + me.load({ + success: function(response, options) { + let values = response.result.data; + ipanel.setValues(values); + }, + }); + } + }, +}); diff --git a/www/manager6/sdn/SubnetView.js b/www/manager6/sdn/SubnetView.js new file mode 100644 index 00000000..9a85bbbc --- /dev/null +++ b/www/manager6/sdn/SubnetView.js @@ -0,0 +1,169 @@ +Ext.define('PVE.sdn.SubnetView', { + extend: 'Ext.grid.GridPanel', + alias: 'widget.pveSDNSubnetView', + + stateful: true, + stateId: 'grid-sdn-subnet', + + base_url: undefined, + + remove_btn: undefined, + + setBaseUrl: function(url) { + var me = this; + + me.base_url = url; + + if (url === undefined) { + me.store.removeAll(); + } else { + me.remove_btn.baseurl = url + '/'; + me.store.setProxy({ + type: 'proxmox', + url: '/api2/json/' + url + '?pending=1' + }); + + me.store.load(); + } + }, + + initComponent : function() { + let me = this; + + var store = new Ext.data.Store({ + model: 'pve-sdn-subnet' + }); + + var reload = function() { + store.load(); + }; + + let sm = Ext.create('Ext.selection.RowModel', {}); + + var set_button_status = function() { + var rec = me.selModel.getSelection()[0]; + + if (!rec || rec.data.state === 'deleted') { + edit_btn.disable(); + remove_btn.disable(); + return; + } + }; + + let run_editor = function() { + let rec = sm.getSelection()[0]; + + let win = Ext.create('PVE.sdn.SubnetEdit',{ + autoShow: true, + subnet: rec.data.subnet, + base_url: me.base_url, + }); + win.on('destroy', reload); + }; + + let edit_btn = new Proxmox.button.Button({ + text: gettext('Edit'), + disabled: true, + selModel: sm, + handler: run_editor, + }); + + me.remove_btn = Ext.create('Proxmox.button.StdRemoveButton', { + selModel: sm, + baseurl: me.base_url + '/', + callback: function() { + reload(); + }, + }); + + Ext.apply(me, { + store: store, + reloadStore: reload, + selModel: sm, + viewConfig: { + trackOver: false + }, + tbar: [ + { + text: gettext('Create'), + handler: function() { + let win = Ext.create('PVE.sdn.SubnetEdit', { + autoShow: true, + base_url: me.base_url, + type: 'subnet', + }); + win.on('destroy', reload); + } + }, + me.remove_btn, + edit_btn, + ], + columns: [ + { + header: 'ID', + flex: 2, + dataIndex: 'cidr', + renderer: function(value, metaData, rec) { + return PVE.Utils.render_sdn_pending(rec, value, 'cidr', 1); + } + }, + { + header: gettext('Gateway'), + flex: 1, + dataIndex: 'gateway', + renderer: function(value, metaData, rec) { + return PVE.Utils.render_sdn_pending(rec, value, 'gateway'); + } + }, + { + header: 'SNAT', + flex: 1, + dataIndex: 'snat', + renderer: function(value, metaData, rec) { + return PVE.Utils.render_sdn_pending(rec, value, 'snat'); + } + }, + { + header: gettext('Dns prefix'), + flex: 1, + dataIndex: 'dnszoneprefix', + renderer: function(value, metaData, rec) { + return PVE.Utils.render_sdn_pending(rec, value, 'dnszoneprefix'); + } + }, + { + header: gettext('State'), + width: 100, + dataIndex: 'state', + renderer: function(value, metaData, rec) { + return PVE.Utils.render_sdn_pending_state(rec, value); + } + } + + ], + listeners: { + activate: reload, + itemdblclick: run_editor, + selectionchange: set_button_status + } + }); + + me.callParent(); + + if (me.base_url) { + me.setBaseUrl(me.base_url); // load + } + } +}, function() { + + Ext.define('pve-sdn-subnet', { + extend: 'Ext.data.Model', + fields: [ + 'cidr', + 'gateway', + 'snat', + ], + idProperty: 'subnet' + }); + +}); diff --git a/www/manager6/sdn/VnetEdit.js b/www/manager6/sdn/VnetEdit.js index e959ffd1..1ed20994 100644 --- a/www/manager6/sdn/VnetEdit.js +++ b/www/manager6/sdn/VnetEdit.js @@ -9,12 +9,10 @@ Ext.define('PVE.sdn.VnetInputPanel', { values.type = 'vnet'; } - if (!values.ipv6) { - delete values.ipv6; - } - if (!values.ipv4) { - delete values.ipv4; + if (!values.vlanaware) { + delete values.vlanaware; } + if (!values.mac) { delete values.mac; } @@ -61,35 +59,16 @@ Ext.define('PVE.sdn.VnetInputPanel', { uncheckedValue: 0, checked: false, fieldLabel: gettext('VLAN Aware'), - }, - { - xtype: 'textfield', - name: 'mac', - fieldLabel: gettext('MAC Address'), - vtype: 'MacAddress', - skipEmptyText: true, - allowBlank: true, - emptyText: 'auto', - }, + } ], advancedItems: [ { xtype: 'textfield', - name: 'ipv4', - vtype: 'IPCIDRAddress', - fieldLabel: 'IPv4/CIDR', // do not localize - emptyText: 'Optional anycast addr. for BGP', - skipEmptyText: true, - allowBlank: true, - }, - { - xtype: 'textfield', - name: 'ipv6', - vtype: 'IP6CIDRAddress', - fieldLabel: 'IPv6/CIDR', // do not localize - emptyText: 'Optional anycast addr. for BGP', - skipEmptyText: true, + name: 'mac', + fieldLabel: gettext('MAC address'), + vtype: 'MacAddress', allowBlank: true, + emptyText: 'auto' }, ], }); diff --git a/www/manager6/sdn/VnetPanel.js b/www/manager6/sdn/VnetPanel.js new file mode 100644 index 00000000..414b6095 --- /dev/null +++ b/www/manager6/sdn/VnetPanel.js @@ -0,0 +1,39 @@ +Ext.define('PVE.sdn.Vnet', { + extend: 'Ext.panel.Panel', + alias: 'widget.pveSDNVnet', + + title: 'Vnet', + + onlineHelp: 'pvesdn_config_vnet', + + initComponent: function() { + var me = this; + + var subnetview_panel = Ext.createWidget('pveSDNSubnetView', { + title: gettext('Subnets'), + region: 'center', + border: false + }); + + var vnetview_panel = Ext.createWidget('pveSDNVnetView', { + title: 'Vnets', + region: 'west', + subnetview_panel: subnetview_panel, + width: '50%', + border: false, + split: true + }); + + Ext.apply(me, { + layout: 'border', + items: [ vnetview_panel, subnetview_panel ], + listeners: { + show: function() { + subnetview_panel.fireEvent('show', subnetview_panel); + } + } + }); + + me.callParent(); + } +}); diff --git a/www/manager6/sdn/VnetView.js b/www/manager6/sdn/VnetView.js index e2897c9f..e8ad4410 100644 --- a/www/manager6/sdn/VnetView.js +++ b/www/manager6/sdn/VnetView.js @@ -7,6 +7,8 @@ Ext.define('PVE.sdn.VnetView', { stateful: true, stateId: 'grid-sdn-vnet', + subnetview_panel: undefined, + initComponent: function() { let me = this; @@ -14,17 +16,28 @@ Ext.define('PVE.sdn.VnetView', { model: 'pve-sdn-vnet', proxy: { type: 'proxmox', - url: "/api2/json/cluster/sdn/vnets", + url: "/api2/json/cluster/sdn/vnets?pending=1", }, sorters: { property: 'vnet', order: 'DESC', }, }); + let reload = () => store.load(); let sm = Ext.create('Ext.selection.RowModel', {}); + var set_button_status = function() { + var rec = me.selModel.getSelection()[0]; + + if (!rec || rec.data.state === 'deleted') { + edit_btn.disable(); + remove_btn.disable(); + return; + } + }; + let run_editor = function() { let rec = sm.getSelection()[0]; @@ -76,64 +89,66 @@ Ext.define('PVE.sdn.VnetView', { header: 'ID', flex: 2, dataIndex: 'vnet', + renderer: function(value, metaData, rec) { + return PVE.Utils.render_sdn_pending(rec, value, 'vnet', 1); + } }, { header: gettext('Alias'), flex: 1, dataIndex: 'alias', + renderer: function(value, metaData, rec) { + return PVE.Utils.render_sdn_pending(rec, value, 'alias'); + } }, { header: gettext('Zone'), flex: 1, dataIndex: 'zone', + renderer: function(value, metaData, rec) { + return PVE.Utils.render_sdn_pending(rec, value, 'zone'); + } }, { header: gettext('Tag'), flex: 1, dataIndex: 'tag', + renderer: function(value, metaData, rec) { + return PVE.Utils.render_sdn_pending(rec, value, 'tag'); + } }, { header: gettext('VLAN Aware'), flex: 1, dataIndex: 'vlanaware', + renderer: function(value, metaData, rec) { + return PVE.Utils.render_sdn_pending(rec, value, 'vlanaware'); + } }, { - header: 'IPv4/CIDR', - flex: 1, - dataIndex: 'ipv4', - }, - { - header: 'IPv6/CIDR', - flex: 1, - dataIndex: 'ipv6', - }, - { - header: 'MAC', - flex: 1, - dataIndex: 'mac', - }, + header: gettext('State'), + width: 100, + dataIndex: 'state', + renderer: function(value, metaData, rec) { + return PVE.Utils.render_sdn_pending_state(rec, value); + } + } ], listeners: { activate: reload, itemdblclick: run_editor, + selectionchange: set_button_status, + show: reload, + select: function(sm, rec) { + var url = '/cluster/sdn/vnets/' + rec.data.vnet + '/subnets'; + me.subnetview_panel.setBaseUrl(url); + }, + deselect: function() { + me.subnetview_panel.setBaseUrl(undefined); + }, }, }); - + store.load(); me.callParent(); }, -}, function() { - Ext.define('pve-sdn-vnet', { - extend: 'Ext.data.Model', - fields: [ - 'alias', - 'ipv4', - 'ipv6', - 'mac', - 'tag', - 'type', - 'vnet', - 'zone', - ], - idProperty: 'vnet', - }); }); diff --git a/www/manager6/sdn/ZoneContentView.js b/www/manager6/sdn/ZoneContentView.js index ac9f58fc..d2fb605e 100644 --- a/www/manager6/sdn/ZoneContentView.js +++ b/www/manager6/sdn/ZoneContentView.js @@ -32,7 +32,7 @@ Ext.define('PVE.sdn.ZoneContentView', { model: 'pve-sdnzone-content', groupField: 'content', proxy: { - type: 'proxmox', + type: 'proxmox', url: '/api2/json' + baseurl, }, sorters: { @@ -57,18 +57,25 @@ Ext.define('PVE.sdn.ZoneContentView', { columns: [ { header: 'VNet', - flex: 1, + width: 100, sortable: true, dataIndex: 'vnet', }, + { + header: 'Alias', + width: 300, + sortable: true, + dataIndex: 'alias' + }, { header: gettext('Status'), - width: 20, + width: 100, + sortable: true, dataIndex: 'status', }, { header: gettext('Details'), - width: 20, + flex: 1, dataIndex: 'statusmsg', }, ], diff --git a/www/manager6/sdn/ZoneView.js b/www/manager6/sdn/ZoneView.js index 4d03a7e7..7016948f 100644 --- a/www/manager6/sdn/ZoneView.js +++ b/www/manager6/sdn/ZoneView.js @@ -2,7 +2,7 @@ Ext.define('PVE.sdn.ZoneView', { extend: 'Ext.grid.GridPanel', alias: ['widget.pveSDNZoneView'], - onlineHelp: 'pvesdn_zone_plugins', + onlineHelp: 'pvesdn_config_zone', stateful: true, stateId: 'grid-sdn-zone', @@ -31,7 +31,7 @@ Ext.define('PVE.sdn.ZoneView', { model: 'pve-sdn-zone', proxy: { type: 'proxmox', - url: "/api2/json/cluster/sdn/zones", + url: "/api2/json/cluster/sdn/zones?pending=1", }, sorters: { property: 'zone', @@ -45,13 +45,23 @@ Ext.define('PVE.sdn.ZoneView', { let sm = Ext.create('Ext.selection.RowModel', {}); + var set_button_status = function() { + var rec = me.selModel.getSelection()[0]; + + if (!rec || rec.data.state === 'deleted') { + edit_btn.disable(); + remove_btn.disable(); + return; + } + }; + let run_editor = function() { let rec = sm.getSelection()[0]; if (!rec) { return; } let type = rec.data.type, - zone = rec.data.zone; + zone = rec.data.zone; me.createSDNEditWindow(type, zone); }; @@ -107,29 +117,81 @@ Ext.define('PVE.sdn.ZoneView', { columns: [ { header: 'ID', - flex: 2, + width: 100, dataIndex: 'zone', + renderer: function(value, metaData, rec) { + return PVE.Utils.render_sdn_pending(rec, value, 'zone', 1); + } }, { header: gettext('Type'), - flex: 1, + width: 100, dataIndex: 'type', - renderer: PVE.Utils.format_sdnzone_type, + renderer: function(value, metaData, rec) { + return PVE.Utils.render_sdn_pending(rec, value, 'type', 1); + } }, { header: 'MTU', - flex: 1, + width: 50, dataIndex: 'mtu', + renderer: function(value, metaData, rec) { + return PVE.Utils.render_sdn_pending(rec, value, 'mtu'); + } + }, + { + header: 'Ipam', + flex: 3, + dataIndex: 'ipam', + renderer: function(value, metaData, rec) { + return PVE.Utils.render_sdn_pending(rec, value, 'ipam'); + } + }, + { + header: gettext('Domain'), + flex: 3, + dataIndex: 'dnszone', + renderer: function(value, metaData, rec) { + return PVE.Utils.render_sdn_pending(rec, value, 'dnszone'); + } + }, + { + header: gettext('Dns'), + flex: 3, + dataIndex: 'dns', + renderer: function(value, metaData, rec) { + return PVE.Utils.render_sdn_pending(rec, value, 'dns'); + } + }, + { + header: gettext('Reverse dns'), + flex: 3, + dataIndex: 'reversedns', + renderer: function(value, metaData, rec) { + return PVE.Utils.render_sdn_pending(rec, value, 'reversedns'); + } }, { header: gettext('Nodes'), flex: 3, dataIndex: 'nodes', + renderer: function(value, metaData, rec) { + return PVE.Utils.render_sdn_pending(rec, value, 'nodes'); + } }, + { + header: gettext('State'), + width: 100, + dataIndex: 'state', + renderer: function(value, metaData, rec) { + return PVE.Utils.render_sdn_pending_state(rec, value); + } + } ], listeners: { activate: reload, itemdblclick: run_editor, + selectionchange: set_button_status }, }); diff --git a/www/manager6/sdn/controllers/BgpEdit.js b/www/manager6/sdn/controllers/BgpEdit.js new file mode 100644 index 00000000..2af7a7bd --- /dev/null +++ b/www/manager6/sdn/controllers/BgpEdit.js @@ -0,0 +1,62 @@ +Ext.define('PVE.sdn.controllers.BgpInputPanel', { + extend: 'PVE.panel.SDNControllerBase', + + onlineHelp: 'pvesdn_controller_plugin_evpn', + + initComponent : function() { + var me = this; + + me.items = [ + { + xtype: me.isCreate ? 'textfield' : 'displayfield', + name: 'controller', + maxLength: 8, + value: me.controllerid || '', + fieldLabel: 'ID', + allowBlank: false + }, + { + xtype: 'proxmoxintegerfield', + name: 'asn', + minValue: 1, + maxValue: 4294967295, + value: 65000, + fieldLabel: 'ASN #', + allowBlank: false + }, + { + xtype: 'textfield', + name: 'peers', + fieldLabel: gettext('Peers'), + allowBlank: false + }, + { + xtype: 'proxmoxcheckbox', + name: 'ebgp', + uncheckedValue: 0, + checked: false, + fieldLabel: 'EBGP' + }, + { + xtype: 'pveNodeSelector', + name: 'node', + fieldLabel: gettext('Node'), + multiSelect: false, + autoSelect: false, + allowBlank: false + }, + + ]; + + me.advancedItems = [ + + { + xtype: 'textfield', + name: 'loopback', + fieldLabel: gettext('Loopback Interface'), + }, + ]; + + me.callParent(); + } +}); diff --git a/www/manager6/sdn/controllers/EvpnEdit.js b/www/manager6/sdn/controllers/EvpnEdit.js index 6c90f818..d04b3e54 100644 --- a/www/manager6/sdn/controllers/EvpnEdit.js +++ b/www/manager6/sdn/controllers/EvpnEdit.js @@ -30,19 +30,6 @@ Ext.define('PVE.sdn.controllers.EvpnInputPanel', { fieldLabel: gettext('Peers'), allowBlank: false, }, - { - xtype: 'textfield', - name: 'gateway-external-peers', - fieldLabel: gettext('External Gateway Peers'), - allowBlank: true, - }, - { - xtype: 'pveNodeSelector', - name: 'gateway-nodes', - fieldLabel: gettext('Gateway Nodes'), - multiSelect: true, - autoSelect: false, - }, ]; me.callParent(); diff --git a/www/manager6/sdn/dns/Base.js b/www/manager6/sdn/dns/Base.js new file mode 100644 index 00000000..18d93c9f --- /dev/null +++ b/www/manager6/sdn/dns/Base.js @@ -0,0 +1,73 @@ +Ext.define('PVE.panel.SDNDnsBase', { + extend: 'Proxmox.panel.InputPanel', + + type: '', + + onGetValues: function(values) { + var me = this; + + if (me.isCreate) { + values.type = me.type; + } else { + delete values.dns; + } + + return values; + }, + + initComponent : function() { + var me = this; + + me.callParent(); + } +}); + +Ext.define('PVE.sdn.dns.BaseEdit', { + extend: 'Proxmox.window.Edit', + + initComponent : function() { + var me = this; + + me.isCreate = !me.dns; + + if (me.isCreate) { + me.url = '/api2/extjs/cluster/sdn/dns'; + me.method = 'POST'; + } else { + me.url = '/api2/extjs/cluster/sdn/dns/' + me.dns; + me.method = 'PUT'; + } + + var ipanel = Ext.create(me.paneltype, { + type: me.type, + isCreate: me.isCreate, + dns: me.dns + }); + + Ext.apply(me, { + subject: PVE.Utils.format_sdndns_type(me.type), + isAdd: true, + items: [ ipanel ] + }); + + me.callParent(); + + if (!me.isCreate) { + me.load({ + success: function(response, options) { + var values = response.result.data; + var ctypes = values.content || ''; + + values.content = ctypes.split(','); + + if (values.nodes) { + values.nodes = values.nodes.split(','); + } + values.enable = values.disable ? 0 : 1; + + ipanel.setValues(values); + } + }); + } + } +}); diff --git a/www/manager6/sdn/dns/PowerdnsEdit.js b/www/manager6/sdn/dns/PowerdnsEdit.js new file mode 100644 index 00000000..3834693c --- /dev/null +++ b/www/manager6/sdn/dns/PowerdnsEdit.js @@ -0,0 +1,52 @@ +Ext.define('PVE.sdn.dns.PowerdnsInputPanel', { + extend: 'PVE.panel.SDNDnsBase', + + onlineHelp: 'pvesdn_dns_plugin_powerdns', + + onGetValues: function(values) { + var me = this; + + if (me.isCreate) { + values.type = me.type; + } else { + delete values.dns; + } + + return values; + }, + + initComponent : function() { + var me = this; + + me.items = [ + { + xtype: me.isCreate ? 'textfield' : 'displayfield', + name: 'dns', + maxLength: 10, + value: me.dns || '', + fieldLabel: 'ID', + allowBlank: false + }, + { + xtype: 'textfield', + name: 'url', + fieldLabel: 'url', + allowBlank: false, + }, + { + xtype: 'textfield', + name: 'key', + fieldLabel: gettext('api key'), + allowBlank: false, + }, + { + xtype: 'proxmoxintegerfield', + name: 'ttl', + fieldLabel: 'ttl', + allowBlank: true + }, + ]; + + me.callParent(); + } +}); diff --git a/www/manager6/sdn/ipams/Base.js b/www/manager6/sdn/ipams/Base.js new file mode 100644 index 00000000..0874eaf3 --- /dev/null +++ b/www/manager6/sdn/ipams/Base.js @@ -0,0 +1,73 @@ +Ext.define('PVE.panel.SDNIpamBase', { + extend: 'Proxmox.panel.InputPanel', + + type: '', + + onGetValues: function(values) { + var me = this; + + if (me.isCreate) { + values.type = me.type; + } else { + delete values.ipam; + } + + return values; + }, + + initComponent : function() { + var me = this; + + me.callParent(); + } +}); + +Ext.define('PVE.sdn.ipams.BaseEdit', { + extend: 'Proxmox.window.Edit', + + initComponent : function() { + var me = this; + + me.isCreate = !me.ipam; + + if (me.isCreate) { + me.url = '/api2/extjs/cluster/sdn/ipams'; + me.method = 'POST'; + } else { + me.url = '/api2/extjs/cluster/sdn/ipams/' + me.ipam; + me.method = 'PUT'; + } + + var ipanel = Ext.create(me.paneltype, { + type: me.type, + isCreate: me.isCreate, + ipam: me.ipam + }); + + Ext.apply(me, { + subject: PVE.Utils.format_sdnipam_type(me.type), + isAdd: true, + items: [ ipanel ] + }); + + me.callParent(); + + if (!me.isCreate) { + me.load({ + success: function(response, options) { + var values = response.result.data; + var ctypes = values.content || ''; + + values.content = ctypes.split(','); + + if (values.nodes) { + values.nodes = values.nodes.split(','); + } + values.enable = values.disable ? 0 : 1; + + ipanel.setValues(values); + } + }); + } + } +}); diff --git a/www/manager6/sdn/ipams/NetboxEdit.js b/www/manager6/sdn/ipams/NetboxEdit.js new file mode 100644 index 00000000..50de571a --- /dev/null +++ b/www/manager6/sdn/ipams/NetboxEdit.js @@ -0,0 +1,46 @@ +Ext.define('PVE.sdn.ipams.NetboxInputPanel', { + extend: 'PVE.panel.SDNIpamBase', + + onlineHelp: 'pvesdn_ipam_plugin_netbox', + + onGetValues: function(values) { + var me = this; + + if (me.isCreate) { + values.type = me.type; + } else { + delete values.ipam; + } + + return values; + }, + + initComponent : function() { + var me = this; + + me.items = [ + { + xtype: me.isCreate ? 'textfield' : 'displayfield', + name: 'ipam', + maxLength: 10, + value: me.zone || '', + fieldLabel: 'ID', + allowBlank: false + }, + { + xtype: 'textfield', + name: 'url', + fieldLabel: gettext('Url'), + allowBlank: false, + }, + { + xtype: 'textfield', + name: 'token', + fieldLabel: gettext('Token'), + allowBlank: false, + }, + ]; + + me.callParent(); + } +}); diff --git a/www/manager6/sdn/ipams/PVEIpamEdit.js b/www/manager6/sdn/ipams/PVEIpamEdit.js new file mode 100644 index 00000000..43b70106 --- /dev/null +++ b/www/manager6/sdn/ipams/PVEIpamEdit.js @@ -0,0 +1,34 @@ +Ext.define('PVE.sdn.ipams.PVEIpamInputPanel', { + extend: 'PVE.panel.SDNIpamBase', + + onlineHelp: 'pvesdn_ipam_plugin_pveipam', + + onGetValues: function(values) { + var me = this; + + if (me.isCreate) { + values.type = me.type; + } else { + delete values.ipam; + } + + return values; + }, + + initComponent : function() { + var me = this; + + me.items = [ + { + xtype: me.isCreate ? 'textfield' : 'displayfield', + name: 'ipam', + maxLength: 10, + value: me.zone || '', + fieldLabel: 'ID', + allowBlank: false + }, + ]; + + me.callParent(); + } +}); diff --git a/www/manager6/sdn/ipams/PhpIpamEdit.js b/www/manager6/sdn/ipams/PhpIpamEdit.js new file mode 100644 index 00000000..8a974fb3 --- /dev/null +++ b/www/manager6/sdn/ipams/PhpIpamEdit.js @@ -0,0 +1,52 @@ +Ext.define('PVE.sdn.ipams.PhpIpamInputPanel', { + extend: 'PVE.panel.SDNIpamBase', + + onlineHelp: 'pvesdn_ipam_plugin_phpipam', + + onGetValues: function(values) { + var me = this; + + if (me.isCreate) { + values.type = me.type; + } else { + delete values.ipam; + } + + return values; + }, + + initComponent : function() { + var me = this; + + me.items = [ + { + xtype: me.isCreate ? 'textfield' : 'displayfield', + name: 'ipam', + maxLength: 10, + value: me.zone || '', + fieldLabel: 'ID', + allowBlank: false + }, + { + xtype: 'textfield', + name: 'url', + fieldLabel: gettext('Url'), + allowBlank: false, + }, + { + xtype: 'textfield', + name: 'token', + fieldLabel: gettext('Token'), + allowBlank: false, + }, + { + xtype: 'textfield', + name: 'section', + fieldLabel: gettext('Section'), + allowBlank: false, + }, + ]; + + me.callParent(); + } +}); diff --git a/www/manager6/sdn/zones/Base.js b/www/manager6/sdn/zones/Base.js index 1d99ca64..168ba54b 100644 --- a/www/manager6/sdn/zones/Base.js +++ b/www/manager6/sdn/zones/Base.js @@ -4,28 +4,59 @@ Ext.define('PVE.panel.SDNZoneBase', { type: '', onGetValues: function(values) { - var me = this; + var me = this; - if (me.isCreate) { - values.type = me.type; - } else { - delete values.zone; - } + if (me.isCreate) { + values.type = me.type; + } else { + delete values.zone; + } - return values; + return values; }, initComponent: function() { - var me = this; + var me = this; - me.callParent(); - }, + me.advancedItems = [ + { + xtype: 'pveSDNIpamSelector', + fieldLabel: gettext('Ipam'), + name: 'ipam', + value: 'pve', + allowBlank: false, + }, + { + xtype: 'pveSDNDnsSelector', + fieldLabel: gettext('Dns server'), + name: 'dns', + value: '', + allowBlank: true, + }, + { + xtype: 'pveSDNDnsSelector', + fieldLabel: gettext('Reverse Dns server'), + name: 'reversedns', + value: '', + allowBlank: true, + }, + { + xtype: 'proxmoxtextfield', + name: 'dnszone', + skipEmptyText: true, + fieldLabel: gettext('DNS zone'), + allowBlank: true + }, + ]; + + me.callParent(); + } }); Ext.define('PVE.sdn.zones.BaseEdit', { extend: 'Proxmox.window.Edit', - initComponent: function() { + initComponent : function() { var me = this; me.isCreate = !me.zone; @@ -45,7 +76,7 @@ Ext.define('PVE.sdn.zones.BaseEdit', { }); Ext.apply(me, { - subject: PVE.Utils.format_sdnzone_type(me.type), + subject: PVE.Utils.format_sdnzone_type(me.type), isAdd: true, items: [ipanel], }); @@ -63,6 +94,11 @@ Ext.define('PVE.sdn.zones.BaseEdit', { if (values.nodes) { values.nodes = values.nodes.split(','); } + + if (values.exitnodes) { + values.exitnodes = values.exitnodes.split(','); + } + values.enable = values.disable ? 0 : 1; ipanel.setValues(values); diff --git a/www/manager6/sdn/zones/EvpnEdit.js b/www/manager6/sdn/zones/EvpnEdit.js index d930b95d..65777190 100644 --- a/www/manager6/sdn/zones/EvpnEdit.js +++ b/www/manager6/sdn/zones/EvpnEdit.js @@ -4,62 +4,69 @@ Ext.define('PVE.sdn.zones.EvpnInputPanel', { onlineHelp: 'pvesdn_zone_plugin_evpn', onGetValues: function(values) { - var me = this; + var me = this; - if (me.isCreate) { - values.type = me.type; - } else { - delete values.zone; - } + if (me.isCreate) { + values.type = me.type; + } else { + delete values.zone; + } - return values; + return values; }, initComponent: function() { var me = this; - me.items = [ - { - xtype: me.isCreate ? 'textfield' : 'displayfield', - name: 'zone', - maxLength: 8, - value: me.zone || '', - fieldLabel: 'ID', - allowBlank: false, - }, - { - xtype: 'proxmoxintegerfield', - name: 'vrf-vxlan', - minValue: 1, - maxValue: 16000000, - fieldLabel: 'VRF-VXLAN Tag', - allowBlank: false, - }, - { - xtype: 'pveSDNControllerSelector', - fieldLabel: gettext('Controller'), - name: 'controller', - value: '', - allowBlank: false, - }, - { - xtype: 'proxmoxintegerfield', - name: 'mtu', - minValue: 100, - maxValue: 65000, - fieldLabel: 'MTU', - skipEmptyText: true, - allowBlank: true, - emptyText: 'auto', - }, - { - xtype: 'pveNodeSelector', - name: 'nodes', - fieldLabel: gettext('Nodes'), - emptyText: gettext('All') + ' (' + gettext('No restrictions') +')', - multiSelect: true, - autoSelect: false, - }, + me.items = [ + { + xtype: me.isCreate ? 'textfield' : 'displayfield', + name: 'zone', + maxLength: 8, + value: me.zone || '', + fieldLabel: 'ID', + allowBlank: false, + }, + { + xtype: 'proxmoxintegerfield', + name: 'vrf-vxlan', + minValue: 1, + maxValue: 16000000, + fieldLabel: 'VRF-VXLAN Tag', + allowBlank: false, + }, + { + xtype: 'pveNodeSelector', + name: 'exitnodes', + fieldLabel: gettext('Exit Nodes'), + multiSelect: true, + autoSelect: false + }, + { + xtype: 'pveSDNControllerSelector', + fieldLabel: gettext('Controller'), + name: 'controller', + value: '', + allowBlank: false, + }, + { + xtype: 'proxmoxintegerfield', + name: 'mtu', + minValue: 100, + maxValue: 65000, + fieldLabel: 'MTU', + skipEmptyText: true, + allowBlank: true, + emptyText: 'auto', + }, + { + xtype: 'pveNodeSelector', + name: 'nodes', + fieldLabel: gettext('Nodes'), + emptyText: gettext('All') + ' (' + gettext('No restrictions') +')', + multiSelect: true, + autoSelect: false, + }, ]; diff --git a/www/manager6/sdn/zones/SimpleEdit.js b/www/manager6/sdn/zones/SimpleEdit.js index 8cff5e16..56df7952 100644 --- a/www/manager6/sdn/zones/SimpleEdit.js +++ b/www/manager6/sdn/zones/SimpleEdit.js @@ -1,18 +1,18 @@ Ext.define('PVE.sdn.zones.SimpleInputPanel', { extend: 'PVE.panel.SDNZoneBase', - //onlineHelp: 'pvesdn_zone_plugin_simple', // FIXME uncomment once doc-gen is updated + onlineHelp: 'pvesdn_zone_plugin_simple', onGetValues: function(values) { - var me = this; + var me = this; - if (me.isCreate) { - values.type = me.type; - } else { - delete values.zone; - } + if (me.isCreate) { + values.type = me.type; + } else { + delete values.zone; + } - return values; + return values; }, initComponent: function() { diff --git a/www/manager6/sdn/zones/VlanEdit.js b/www/manager6/sdn/zones/VlanEdit.js index db1587b7..93d2bede 100644 --- a/www/manager6/sdn/zones/VlanEdit.js +++ b/www/manager6/sdn/zones/VlanEdit.js @@ -4,15 +4,15 @@ Ext.define('PVE.sdn.zones.VlanInputPanel', { onlineHelp: 'pvesdn_zone_plugin_vlan', onGetValues: function(values) { - var me = this; + var me = this; - if (me.isCreate) { - values.type = me.type; - } else { - delete values.zone; - } + if (me.isCreate) { + values.type = me.type; + } else { + delete values.zone; + } - return values; + return values; }, initComponent: function() { diff --git a/www/manager6/sdn/zones/VxlanEdit.js b/www/manager6/sdn/zones/VxlanEdit.js index 5c5b2675..41cc7e68 100644 --- a/www/manager6/sdn/zones/VxlanEdit.js +++ b/www/manager6/sdn/zones/VxlanEdit.js @@ -4,56 +4,55 @@ Ext.define('PVE.sdn.zones.VxlanInputPanel', { onlineHelp: 'pvesdn_zone_plugin_vxlan', onGetValues: function(values) { - var me = this; + var me = this; - if (me.isCreate) { - values.type = me.type; - } else { - delete values.zone; - } + if (me.isCreate) { + values.type = me.type; + } else { + delete values.zone; + } delete values.mode; - return values; + return values; }, initComponent: function() { var me = this; - me.items = [ - { - xtype: me.isCreate ? 'textfield' : 'displayfield', - maxLength: 8, - name: 'zone', - value: me.zone || '', - fieldLabel: 'ID', - allowBlank: false, - }, - { - xtype: 'textfield', - name: 'peers', - fieldLabel: gettext('Peer Address List'), - allowBlank: false, - }, - { - xtype: 'proxmoxintegerfield', - name: 'mtu', - minValue: 100, - maxValue: 65000, - fieldLabel: 'MTU', - skipEmptyText: true, - allowBlank: true, - emptyText: 'auto', - }, - { - xtype: 'pveNodeSelector', - name: 'nodes', - fieldLabel: gettext('Nodes'), - emptyText: gettext('All') + ' (' + gettext('No restrictions') +')', - multiSelect: true, - autoSelect: false, - }, - + me.items = [ + { + xtype: me.isCreate ? 'textfield' : 'displayfield', + maxLength: 8, + name: 'zone', + value: me.zone || '', + fieldLabel: 'ID', + allowBlank: false, + }, + { + xtype: 'textfield', + name: 'peers', + fieldLabel: gettext('Peer Address List'), + allowBlank: false, + }, + { + xtype: 'proxmoxintegerfield', + name: 'mtu', + minValue: 100, + maxValue: 65000, + fieldLabel: 'MTU', + skipEmptyText: true, + allowBlank: true, + emptyText: 'auto', + }, + { + xtype: 'pveNodeSelector', + name: 'nodes', + fieldLabel: gettext('Nodes'), + emptyText: gettext('All') + ' (' + gettext('No restrictions') +')', + multiSelect: true, + autoSelect: false, + }, ]; me.callParent(); -- 2.20.1