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 DC92D6179C for ; Fri, 20 Nov 2020 14:32:59 +0100 (CET) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id CB968125BE for ; Fri, 20 Nov 2020 14:32:29 +0100 (CET) Received: from proxmox-new.maurer-it.com (proxmox-new.maurer-it.com [212.186.127.180]) (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 firstgate.proxmox.com (Proxmox) with ESMTPS id 2598C1259D for ; Fri, 20 Nov 2020 14:32:26 +0100 (CET) Received: from proxmox-new.maurer-it.com (localhost.localdomain [127.0.0.1]) by proxmox-new.maurer-it.com (Proxmox) with ESMTP id D5C1D43B27 for ; Fri, 20 Nov 2020 14:32:25 +0100 (CET) To: Proxmox VE development discussion , Dominik Csapak References: <20201120095049.15194-1-d.csapak@proxmox.com> <20201120095049.15194-5-d.csapak@proxmox.com> From: Thomas Lamprecht Message-ID: <247e7342-8f89-adcf-740b-9ba1767c2822@proxmox.com> Date: Fri, 20 Nov 2020 14:32:24 +0100 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:83.0) Gecko/20100101 Thunderbird/83.0 MIME-Version: 1.0 In-Reply-To: <20201120095049.15194-5-d.csapak@proxmox.com> Content-Type: text/plain; charset=UTF-8 Content-Language: en-US Content-Transfer-Encoding: quoted-printable X-SPAM-LEVEL: Spam detection results: 0 AWL -0.086 Adjusted score from AWL reputation of From: address KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment NICE_REPLY_A -0.001 Looks like a legit reply (A) RCVD_IN_DNSWL_MED -2.3 Sender listed at https://www.dnswl.org/, medium trust SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_PASS -0.001 SPF: sender matches SPF record URIBL_BLOCKED 0.001 ADMINISTRATOR NOTICE: The query to URIBL was blocked. See http://wiki.apache.org/spamassassin/DnsBlocklists#dnsbl-block for more information. [data.id] Subject: Re: [pve-devel] [PATCH manager 4/4] ui: add MetricServerView to Datacenter 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: Fri, 20 Nov 2020 13:32:59 -0000 On 20.11.20 10:50, Dominik Csapak wrote: > adds ui support for configuring the External Metric servers. > for now, influxdb and graphite edit windows do not share code, > it would be ideal to do that once we add more plugins >=20 > Signed-off-by: Dominik Csapak > --- > www/manager6/Makefile | 1 + > www/manager6/dc/Config.js | 6 + > www/manager6/dc/MetricServerView.js | 397 ++++++++++++++++++++++++++++= > 3 files changed, 404 insertions(+) > create mode 100644 www/manager6/dc/MetricServerView.js >=20 > diff --git a/www/manager6/Makefile b/www/manager6/Makefile > index 4fa8e1a3..a2514464 100644 > --- a/www/manager6/Makefile > +++ b/www/manager6/Makefile > @@ -146,6 +146,7 @@ JSSRC=3D \ > dc/TokenView.js \ > dc/UserEdit.js \ > dc/UserView.js \ > + dc/MetricServerView.js \ > lxc/CmdMenu.js \ > lxc/Config.js \ > lxc/CreateWizard.js \ > diff --git a/www/manager6/dc/Config.js b/www/manager6/dc/Config.js > index 905c3dc0..2fdba743 100644 > --- a/www/manager6/dc/Config.js > +++ b/www/manager6/dc/Config.js > @@ -231,6 +231,12 @@ Ext.define('PVE.dc.Config', { > list_refs_url: '/cluster/firewall/refs', > itemId: 'firewall-ipset' > }, > + { > + xtype: 'pveMetricServerView', > + title: gettext('Metric Server'), > + iconCls: 'fa fa-bar-chart', > + itemId: 'metricservers', > + }, > { > xtype: 'pveDcSupport', > title: gettext('Support'), > diff --git a/www/manager6/dc/MetricServerView.js b/www/manager6/dc/Metr= icServerView.js > new file mode 100644 > index 00000000..894cd18a > --- /dev/null > +++ b/www/manager6/dc/MetricServerView.js > @@ -0,0 +1,397 @@ > +Ext.define('PVE.dc.MetricServerView', { > + extend: 'Ext.grid.Panel', > + alias: ['widget.pveMetricServerView'], > + > + stateful: true, > + stateId: 'grid-metricserver', > + > + controller: { > + xclass: 'Ext.app.ViewController', > + > + render_type: function(value) { > + switch(value) { > + case 'influxdb': return "InfluxDB"; > + case 'graphite': return "Graphite"; > + default: break; > + } > + return Proxmox.Utils.unknownText; nit, that catch-all return could be in the switch default arm - so all fu= nction exits are there - it's a short function and no hard feeling, but stood ou= t to me. > + }, > + > + addInfluxDB: function() { > + let me =3D this; > + Ext.create(`PVE.dc.InfluxDBEdit`, { > + url: `/api2/extjs/cluster/metricserver`, > + listeners: { > + destroy: function() { > + me.reload(); > + } could be a single line arrow function, for such short definitions they ar= e still visible enough, IMO. destroy: () =3D> me.reload(), > + } > + }).show(); you could use autoShow: true instead > + }, > + > + addGraphite: function() { > + let me =3D this; > + Ext.create(`PVE.dc.GraphiteEdit`, { > + url: `/api2/extjs/cluster/metricserver`, > + listeners: { > + destroy: function() { > + me.reload(); > + } same with reload as arrow function > + } > + }).show(); same as above (autoShow) > + }, > + > + editServer: function() { > + let me =3D this; > + let view =3D me.getView(); > + let selection =3D view.getSelection(); > + if (!selection || selection.length < 1) { return; } please format above if nicely, return and closing } on it's one line. > + > + let rec =3D selection[0]; > + > + let xtype =3D me.render_type(rec.data.type); > + Ext.create(`PVE.dc.${xtype}Edit`, { > + url: `/api2/extjs/cluster/metricserver/${rec.data.id}`, > + serverid: rec.data.id, > + listeners: { > + destroy: function() { > + me.reload(); same with reload as arrow function=20 > + } > + } > + }).show(); could be autoShow > + }, > + > + reload: function() { this.getView().getStore().load(); }, please format in new lines > + }, > + > + store: { > + autoLoad: true, > + id: 'metricservers', > + proxy: { > + type: 'proxmox', > + url: '/api2/json/cluster/metricserver', > + }, > + }, > + > + columns: [ > + { > + text: gettext('Name'), > + flex: 1, > + dataIndex: 'id', > + }, > + { > + text: gettext('Type'), > + flex: 1, > + dataIndex: 'type', > + renderer: 'render_type', > + }, > + { > + text: gettext('Enabled'), > + dataIndex: 'disable', > + width: 100, > + renderer: Proxmox.Utils.format_neg_boolean, > + }, > + { > + text: gettext('Server'), > + flex: 1, > + dataIndex: 'server', > + }, > + { > + text: gettext('Port'), > + flex: 1, avoid flex for things we know there are fixed boundaries, while I am a fa= n of defining flex having all flexed is most of the time also "bad", as in, in= creases space between information needlessly so that there's much eye movement re= quired for getting it on bigger screens. I discussed this with Dietmar a bit ago for some PBS job grids, and there= he was right and making fixed length columns exactly that, fixed :) Sometimes a combination of flex and maxWidth can have really good results= too. > + dataIndex: 'port', > + }, > + ], > + > + tbar: [ > + { > + text: gettext('Add'), > + menu: [ > + { > + text: 'Graphite', > + handler: 'addGraphite', > + }, > + { > + text: 'InfluxDB', > + handler: 'addInfluxDB', > + }, > + ] > + }, > + { > + text: gettext('Edit'), > + xtype: 'proxmoxButton', > + handler: 'editServer', > + disabled: true, > + }, > + { > + xtype: 'proxmoxStdRemoveButton', > + baseurl: `/api2/extjs/cluster/metricserver`, > + callback: 'reload', > + } > + ], > + > + listeners: { > + itemdblclick: 'editServer', > + }, > + > + initComponent : function() { > + var me =3D this; > + > + me.callParent(); > + > + Proxmox.Utils.monStoreErrors(me, me.getStore()); > + } > +}); > + > +Ext.define('PVE.dc.InfluxDBEdit', { > + extend: 'Proxmox.window.Edit', > + mixins: ['Proxmox.Mixin.CBind'], > + > + subject: 'InfluxDB', > + > + cbindData: function() { > + let me =3D this; > + me.isCreate =3D !me.serverid; > + me.serverid =3D me.serverid || ""; > + me.method =3D me.isCreate ? 'POST' : 'PUT'; > + if (!me.isCreate) { > + me.subject =3D `InfluxDB: ${me.serverid}`; > + } > + return {}; > + }, > + > + items: [ > + { > + xtype: 'inputpanel', > + > + onGetValues: function(values) { > + values.disable =3D values.enable ? 0 : 1; > + delete values.enable; > + return values; > + }, > + > + column1: [ > + { > + xtype: 'hidden', > + name: 'type', > + value: 'influxdb', > + cbind: { > + submitValue: '{isCreate}', > + }, > + }, > + { > + fieldLabel: gettext('Name'), > + xtype: 'pmxDisplayEditField', > + name: 'id', > + allowBlank: false, > + cbind: { > + editable: '{isCreate}', > + value: '{serverid}', > + }, > + }, > + { > + fieldLabel: gettext('Enabled'), > + xtype: 'checkbox', > + inputValue: 1, > + uncheckedValue: 0, > + checked: true, > + name: 'enable', > + }, > + ], > + > + column2: [ > + { > + fieldLabel: gettext('Server'), > + xtype: 'proxmoxtextfield', > + name: 'server', > + allowBlank: false, > + }, > + { > + fieldLabel: gettext('Port'), > + xtype: 'proxmoxintegerfield', > + minValue: 1, > + maximum: 65536, > + name: 'port', > + allowBlank: false, > + }, > + ], > + > + advancedColumn1: [], // has to exists to render any advanced colu= mns > + > + advancedColumn2: [ > + { > + fieldLabel: 'MTU', > + xtype: 'proxmoxintegerfield', > + name: 'mtu', > + minValue: 1, > + emptyText: '1500', > + submitEmpty: false, > + cbind: { > + deleteEmpty: '{!isCreate}', > + }, > + }, > + ] > + }, > + ], > + > + initComponent: function() { > + let me =3D this; > + me.callParent(); > + if (!me.serverid) { return; } > + > + me.load({ > + success: function(response, options) { > + let values =3D response.result.data; > + values.enable =3D !values.disable; > + me.down('inputpanel').setValues(values); > + } > + }) > + } > +}); > + > +Ext.define('PVE.dc.GraphiteEdit', { > + extend: 'Proxmox.window.Edit', > + mixins: ['Proxmox.Mixin.CBind'], > + > + subject: 'Graphite', > + > + cbindData: function() { > + let me =3D this; > + me.isCreate =3D !me.serverid; > + me.serverid =3D me.serverid || ""; > + me.method =3D me.isCreate ? 'POST' : 'PUT'; > + if (!me.isCreate) { > + me.subject =3D `Graphite: ${me.serverid}`; > + } > + return {}; > + }, > + > + items: [ > + { > + xtype: 'inputpanel', > + > + onGetValues: function(values) { > + values.disable =3D values.enable ? 0 : 1; > + delete values.enable; > + return values; > + }, > + > + column1: [ > + { > + xtype: 'hidden', > + name: 'type', > + value: 'graphite', > + cbind: { > + submitValue: '{isCreate}', > + }, > + }, > + { > + fieldLabel: gettext('Name'), > + xtype: 'pmxDisplayEditField', > + name: 'id', > + allowBlank: false, > + cbind: { > + editable: '{isCreate}', > + value: '{serverid}', > + }, > + }, > + { > + fieldLabel: gettext('Enabled'), > + xtype: 'checkbox', > + inputValue: 1, > + uncheckedValue: 0, > + checked: true, > + name: 'enable', > + }, > + ], > + > + column2: [ > + { > + fieldLabel: gettext('Server'), > + xtype: 'proxmoxtextfield', > + name: 'server', > + allowBlank: false, > + }, > + { > + fieldLabel: gettext('Port'), > + xtype: 'proxmoxintegerfield', > + minimum: 1, > + maximum: 65536, > + name: 'port', > + allowBlank: false, > + }, > + { > + fieldLabel: gettext('Path'), > + xtype: 'proxmoxtextfield', > + emptyText: 'proxmox', > + name: 'path', > + cbind: { > + deleteEmpty: '{!isCreate}', > + }, > + } > + ], > + > + advancedColumn1: [ > + { > + fieldLabel: gettext('Protocol'), > + xtype: 'proxmoxKVComboBox', > + name: 'proto', > + value: '__default__', > + cbind: { > + deleteEmpty: '{!isCreate}', > + }, > + comboItems: [ > + ['__default__', 'UDP'], > + ['tcp', 'TCP'], > + ], > + listeners: { > + change: function(field, value) { > + let me =3D this; > + me.up('inputpanel').down('field[name=3Dtimeout]').setDisabled(v= alue !=3D=3D 'tcp'); > + me.up('inputpanel').down('field[name=3Dmtu]').setDisabled(value= =3D=3D=3D 'tcp'); > + }, > + }, > + }, > + ], > + > + advancedColumn2: [ > + { > + fieldLabel: 'MTU', > + xtype: 'proxmoxintegerfield', > + name: 'mtu', > + minimum: 1, > + emptyText: '1500', > + submitEmpty: false, > + cbind: { > + deleteEmpty: '{!isCreate}', > + }, > + }, > + { > + fieldLabel: gettext('TCP Timeout'), > + xtype: 'proxmoxintegerfield', > + name: 'timeout', > + disabled: true, > + cbind: { > + deleteEmpty: '{!isCreate}', > + }, > + minValue: 1, > + emptyText: 1, > + }, > + ], > + }, > + ], > + > + initComponent: function() { > + let me =3D this; > + me.callParent(); > + if (!me.serverid) { return; } > + > + me.load({ > + success: function(response, options) { > + let values =3D response.result.data; > + values.enable =3D !values.disable; > + me.down('inputpanel').setValues(values); > + } > + }) > + } > +}); >=20