[pve-devel] [PATCH xtermjs] termproxy: rewrite in rust

2020-07-06 Thread Dominik Csapak
termproxy is now completely written in rust (instead of perl) but
it is a drop-in replacement

this contains all other necessary changes to the build-system
for it to successfully build

Signed-off-by: Dominik Csapak 
---

changelog needs to be adapted to have 'rust-termproxy' as src
package, since it seems that you cannot have a 'pve-xtermjs' package with
a 'pve-xtermjs' crate but the binary is named 'termproxy'

so we have a 'termproxy' crate+binary and a binary package with name
'pve-xtermjs'

also the version in Cargo.toml needs then to be bumped to 4.7.0

 .cargo/config   |   5 +
 Cargo.toml  |  14 ++
 Makefile|  52 +++--
 debian/compat   |   1 -
 debian/control  |  16 --
 debian/debcargo.toml|  14 ++
 debian/install  |   1 +
 debian/rules|   7 +-
 debian/source/format|   1 -
 debian/source/lintian-overrides |   4 +-
 src/Makefile|   7 -
 src/PVE/CLI/Makefile|   8 -
 src/PVE/CLI/termproxy.pm| 250 -
 src/PVE/Makefile|   3 -
 src/bin/Makefile|   7 -
 src/bin/termproxy   |   8 -
 src/main.rs | 378 
 src/www/Makefile|  21 --
 18 files changed, 458 insertions(+), 339 deletions(-)
 create mode 100644 .cargo/config
 create mode 100644 Cargo.toml
 delete mode 100644 debian/compat
 delete mode 100644 debian/control
 create mode 100644 debian/debcargo.toml
 create mode 100644 debian/install
 delete mode 100644 debian/source/format
 delete mode 100644 src/Makefile
 delete mode 100644 src/PVE/CLI/Makefile
 delete mode 100644 src/PVE/CLI/termproxy.pm
 delete mode 100644 src/PVE/Makefile
 delete mode 100644 src/bin/Makefile
 delete mode 100755 src/bin/termproxy
 create mode 100644 src/main.rs
 delete mode 100644 src/www/Makefile

diff --git a/.cargo/config b/.cargo/config
new file mode 100644
index 000..3b5b6e4
--- /dev/null
+++ b/.cargo/config
@@ -0,0 +1,5 @@
+[source]
+[source.debian-packages]
+directory = "/usr/share/cargo/registry"
+[source.crates-io]
+replace-with = "debian-packages"
diff --git a/Cargo.toml b/Cargo.toml
new file mode 100644
index 000..028ca23
--- /dev/null
+++ b/Cargo.toml
@@ -0,0 +1,14 @@
+[package]
+name = "termproxy"
+version = "4.3.0"
+authors = ["Dominik Csapak "]
+edition = "2018"
+license = "AGPL-3"
+
+exclude = [ "build", "debian" ]
+
+[dependencies]
+mio = "0.6"
+curl = "0.4"
+clap = "2.33"
+proxmox = "0.1.42"
diff --git a/Makefile b/Makefile
index d4aeee4..7a73fe7 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,8 @@
 include /usr/share/dpkg/pkg-info.mk
+include /usr/share/dpkg/architecture.mk
 
 PACKAGE=pve-xtermjs
+CRATENAME=termproxy
 
 export VERSION=${DEB_VERSION_UPSTREAM_REVISION}
 
@@ -11,31 +13,53 @@ FITADDONVER=0.4.0
 FITADDONTGZ=xterm-addon-fit-${FITADDONVER}.tgz
 
 SRCDIR=src
-BUILDDIR ?= ${PACKAGE}-${DEB_VERSION_UPSTREAM}
 GITVERSION:=$(shell git rev-parse HEAD)
 
-DEB=${PACKAGE}_${VERSION}_all.deb
-DSC=${PACKAGE}_${VERSION}.dsc
+DEB=${PACKAGE}_${DEB_VERSION_UPSTREAM_REVISION}_${DEB_BUILD_ARCH}.deb
+DSC=rust-${CRATENAME}_${DEB_VERSION_UPSTREAM_REVISION}.dsc
 
-all: ${DEB}
-   @echo ${DEB}
+ifeq ($(BUILD_MODE), release)
+CARGO_BUILD_ARGS += --release
+COMPILEDIR := target/release
+else
+COMPILEDIR := target/debug
+endif
+
+all: cargo-build $(SRCIDR)
+
+.PHONY: $(SUBDIRS)
+$(SUBDIRS):
+   make -C $@
+
+.PHONY: cargo-build
+cargo-build:
+   cargo build $(CARGO_BUILD_ARGS)
 
-${BUILDDIR}: ${SRCDIR} debian
-   rm -rf ${BUILDDIR}
-   rsync -a ${SRCDIR}/ debian ${BUILDDIR}
-   echo "git clone git://git.proxmox.com/git/pve-xtermjs.git\\ngit 
checkout ${GITVERSION}" > ${BUILDDIR}/debian/SOURCE
+.PHONY: build
+build:
+   rm -rf build
+   debcargo package \
+   --config debian/debcargo.toml \
+   --changelog-ready \
+   --no-overlay-write-back \
+   --directory build \
+   $(CRATENAME) \
+   $(shell dpkg-parsechangelog -l debian/changelog -SVersion | sed -e 
's/-.*//')
+   rm build/Cargo.lock
+   find build/debian -name "*.hint" -delete
+   echo "git clone git://git.proxmox.com/git/pve-xtermjs.git\\ngit 
checkout ${GITVERSION}" > build/debian/SOURCE
 
 .PHONY: deb
 deb: ${DEB}
-${DEB}: ${BUILDDIR}
-   cd ${BUILDDIR}; dpkg-buildpackage -b -uc -us
+$(DEB): build
+   cd build; dpkg-buildpackage -b -uc -us --no-pre-clean
lintian ${DEB}
@echo ${DEB}
 
 .PHONY: dsc
 dsc: ${DSC}
-${DSC}: ${BUILDDIR}
-   cd ${BUILDDIR}; dpkg-buildpackage -S -us -uc -d
+$(DSC): build
+   cd build; dpkg-buildpackage -S -us -uc -d -nc
lintian ${DSC}
 
 X_EXCLUSIONS=--exclude=addons/attach --exclude=addons/full

[pve-devel] [PATCH manager 1/1] ui: use ZFS components and functions from widget-toolkit

2020-06-25 Thread Dominik Csapak
render_zfs_health is now in widget-toolkit
as well as the 'MultiDiskSelector' and the Detailwindow

and drop the now unnecessary classes

Signed-off-by: Dominik Csapak 
---
 www/manager6/Utils.js|  26 
 www/manager6/node/ZFS.js | 255 +--
 2 files changed, 6 insertions(+), 275 deletions(-)

diff --git a/www/manager6/Utils.js b/www/manager6/Utils.js
index 1dae292e..37327ded 100644
--- a/www/manager6/Utils.js
+++ b/www/manager6/Utils.js
@@ -193,32 +193,6 @@ Ext.define('PVE.Utils', { utilities: {
return state;
 },
 
-render_zfs_health: function(value) {
-   if (typeof value == 'undefined'){
-   return "";
-   }
-   var iconCls = 'question-circle';
-   switch (value) {
-   case 'AVAIL':
-   case 'ONLINE':
-   iconCls = 'check-circle good';
-   break;
-   case 'REMOVED':
-   case 'DEGRADED':
-   iconCls = 'exclamation-circle warning';
-   break;
-   case 'UNAVAIL':
-   case 'FAULTED':
-   case 'OFFLINE':
-   iconCls = 'times-circle critical';
-   break;
-   default: //unknown
-   }
-
-   return ' ' + value;
-
-},
-
 get_kvm_osinfo: function(value) {
var info = { base: 'Other' }; // default
if (value) {
diff --git a/www/manager6/node/ZFS.js b/www/manager6/node/ZFS.js
index 0b63ccd7..3c83361f 100644
--- a/www/manager6/node/ZFS.js
+++ b/www/manager6/node/ZFS.js
@@ -19,24 +19,6 @@ Ext.define('PVE.node.CreateZFS', {
 
me.isCreate = true;
 
-   var update_disklist = function() {
-   var grid = me.down('#disklist');
-   var disks = grid.getSelection();
-
-   var val = [];
-   disks.sort(function(a,b) {
-   var aorder = a.get('order') || 0;
-   var border = b.get('order') || 0;
-   return (aorder - border);
-   });
-
-   disks.forEach(function(disk) {
-   val.push(disk.get('devpath'));
-   });
-
-   me.down('field[name=devices]').setValue(val.join(','));
-   };
-
Ext.apply(me, {
url: '/nodes/' + me.nodename + '/disks/zfs',
method: 'POST',
@@ -47,12 +29,6 @@ Ext.define('PVE.node.CreateZFS', {
return values;
},
column1: [
-   {
-   xtype: 'textfield',
-   hidden: true,
-   name: 'devices',
-   allowBlank: false
-   },
{
xtype: 'proxmoxtextfield',
name: 'name',
@@ -106,62 +82,11 @@ Ext.define('PVE.node.CreateZFS', {
],
columnB: [
{
-   xtype: 'grid',
+   xtype: 'pmxMultiDiskSelector',
+   name: 'devices',
+   nodename: me.nodename,
height: 200,
emptyText: gettext('No Disks unused'),
-   itemId: 'disklist',
-   selModel: 'checkboxmodel',
-   listeners: {
-   selectionchange: update_disklist
-   },
-   store: {
-   proxy: {
-   type: 'proxmox',
-   url: '/api2/json/nodes/' + me.nodename + 
'/disks/list?type=unused'
-   }
-   },
-   columns: [
-   {
-   text: gettext('Device'),
-   dataIndex: 'devpath',
-   flex: 2,
-   },
-   {
-   text: gettext('Model'),
-   dataIndex: 'model',
-   flex: 2,
-   },
-   {
-   text: gettext('Serial'),
-   dataIndex: 'serial',
-   flex: 2,
-   },
-   {
-   text: gettext('Size'),
-   dataIndex: 'size',
-   renderer: PVE.Utils.render_size,
-   flex: 1,
-   },
-   {
-   header: gettext('Order'),
-   xtype: 'widgetcolumn',
-   dataInd

[pve-devel] [PATCH widget-toolkit 2/3] add form/MultiDiskSelector

2020-06-25 Thread Dominik Csapak
from pve's ZFSCreate window, refactored to be self-contained using
field mixin, as well as be configureable enough to be used by pve as
well as other products

Signed-off-by: Dominik Csapak 
---
 src/Makefile  |   1 +
 src/form/MultiDiskSelector.js | 164 ++
 2 files changed, 165 insertions(+)
 create mode 100644 src/form/MultiDiskSelector.js

diff --git a/src/Makefile b/src/Makefile
index 3311bbe..f4f8bf5 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -30,6 +30,7 @@ JSSRC=\
form/RealmComboBox.js   \
form/RoleSelector.js\
form/DiskSelector.js\
+   form/MultiDiskSelector.js   \
button/Button.js\
button/HelpButton.js\
grid/ObjectGrid.js  \
diff --git a/src/form/MultiDiskSelector.js b/src/form/MultiDiskSelector.js
new file mode 100644
index 000..9e989a4
--- /dev/null
+++ b/src/form/MultiDiskSelector.js
@@ -0,0 +1,164 @@
+Ext.define('Proxmox.form.MultiDiskSelector', {
+extend: 'Ext.grid.Panel',
+alias: 'widget.pmxMultiDiskSelector',
+
+mixins: {
+   field: 'Ext.form.field.Field',
+},
+
+selModel: 'checkboxmodel',
+
+store: {
+   data: [],
+   proxy: {
+   type: 'proxmox',
+   },
+},
+
+// which field of the disklist is used for getValue
+valueField: 'devpath',
+
+// which parameter is used for the type
+typeParameter: 'type',
+
+// the type of disks to show
+diskType: 'unused',
+
+disks: [],
+
+allowBlank: false,
+
+getValue: function() {
+   let me = this;
+   return me.disks;
+},
+
+setValue: function(value) {
+   let me = this;
+
+   if (!Ext.isArray(value)) {
+   value = value.split(/;, /);
+   }
+
+   let store = me.getStore();
+   let selection = [];
+
+   let keyField = me.valueField;
+
+   value.forEach(item => {
+   let rec = store.findRecord(keyField, item, 0, false, true, true);
+   if (rec) {
+   selection.push(rec);
+   }
+   });
+
+   me.setSelection(selection);
+
+   return me.mixins.field.setValue.call(me, value);
+},
+
+getErrors: function(value) {
+   let me = this;
+   if (me.allowBlank === false &&
+   me.getSelectionModel().getCount() === 0) {
+   me.addBodyCls(['x-form-trigger-wrap-default', 
'x-form-trigger-wrap-invalid']);
+   return [gettext('No Disk selected')];
+   }
+
+   me.removeBodyCls(['x-form-trigger-wrap-default', 
'x-form-trigger-wrap-invalid']);
+   return [];
+},
+
+update_disklist: function() {
+   var me = this;
+   var disks = me.getSelection();
+
+   var val = [];
+   disks.sort(function(a, b) {
+   var aorder = a.get('order') || 0;
+   var border = b.get('order') || 0;
+   return aorder - border;
+   });
+
+   disks.forEach(function(disk) {
+   val.push(disk.get(me.valueField));
+   });
+
+   me.validate();
+   me.disks = val;
+},
+
+columns: [
+   {
+   text: gettext('Device'),
+   dataIndex: 'devpath',
+   flex: 2,
+   },
+   {
+   text: gettext('Model'),
+   dataIndex: 'model',
+   flex: 2,
+   },
+   {
+   text: gettext('Serial'),
+   dataIndex: 'serial',
+   flex: 2,
+   },
+   {
+   text: gettext('Size'),
+   dataIndex: 'size',
+   renderer: Proxmox.Utils.format_size,
+   flex: 1,
+   },
+   {
+   header: gettext('Order'),
+   xtype: 'widgetcolumn',
+   dataIndex: 'order',
+   sortable: true,
+   flex: 1,
+   widget: {
+   xtype: 'proxmoxintegerfield',
+   minValue: 1,
+   isFormField: false,
+   listeners: {
+   change: function(numberfield, value, old_value) {
+   let grid = this.up('pmxMultiDiskSelector');
+   var record = numberfield.getWidgetRecord();
+   record.set('order', value);
+   grid.update_disklist(record);
+   },
+   },
+   },
+   },
+],
+
+listeners: {
+   selectionchange: function() {
+   this.update_disklist();
+   },
+},
+
+initComponent: function() {
+   let me = this;
+
+   if (!me.url) {
+   if (!me.nodename) {
+   throw "no url or nodename given";
+   }
+
+   let node = me.nodename;
+   let param = me.typeParameter;
+   let type = me.diskType;
+   me.url = `/api2/json/nodes/${node}/disks/list?${param}=${type}`;
+   }
+
+   me.disks = [];
+
+   me.callParent();
+   let store = me.getStore();
+   st

[pve-devel] [PATCH widget-toolkit 3/3] add window/ZFSDetail

2020-06-25 Thread Dominik Csapak
inspired by pve's detail window, which used two sub components
(ZFSStatus, ZFSDevices; which were never used elsewhere)
combined into one self-contained window

Signed-off-by: Dominik Csapak 
---
 src/Makefile|   1 +
 src/window/ZFSDetail.js | 152 
 2 files changed, 153 insertions(+)
 create mode 100644 src/window/ZFSDetail.js

diff --git a/src/Makefile b/src/Makefile
index f4f8bf5..12dda30 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -46,6 +46,7 @@ JSSRC=\
window/TaskViewer.js\
window/LanguageEdit.js  \
window/DiskSmart.js \
+   window/ZFSDetail.js \
node/APT.js \
node/NetworkEdit.js \
node/NetworkView.js \
diff --git a/src/window/ZFSDetail.js b/src/window/ZFSDetail.js
new file mode 100644
index 000..8eb6a87
--- /dev/null
+++ b/src/window/ZFSDetail.js
@@ -0,0 +1,152 @@
+Ext.define('Proxmox.window.ZFSDetail', {
+extend: 'Ext.window.Window',
+alias: 'widget.pmxZFSDetail',
+mixins: ['Proxmox.Mixin.CBind'],
+
+cbindData: function(initialConfig) {
+   let me = this;
+   me.url = 
`/nodes/${me.nodename}/disks/zfs/${encodeURIComponent(me.zpool)}`;
+   return {
+   zpoolUri: `/api2/json/${me.url}`,
+   title: `${gettext('Status')}: ${me.zpool}`,
+   };
+},
+
+controller: {
+   xclass: 'Ext.app.ViewController',
+
+   reload: function() {
+   let me = this;
+   let view = me.getView();
+   me.lookup('status').reload();
+
+   Proxmox.Utils.API2Request({
+   url: `/api2/extjs/${view.url}`,
+   waitMsgTarget: view,
+   method: 'GET',
+   failure: function(response, opts) {
+   Proxmox.Utils.setErrorMask(view, response.htmlStatus);
+   },
+   success: function(response, opts) {
+   let devices = me.lookup('devices');
+   devices.getSelectionModel().deselectAll();
+   devices.setRootNode(response.result.data);
+   devices.expandAll();
+   },
+   });
+   },
+
+   init: function(view) {
+   let me = this;
+   Proxmox.Utils.monStoreErrors(me, 
me.lookup('status').getStore().rstore);
+   me.reload();
+   },
+},
+
+modal: true,
+width: 800,
+height: 400,
+resizable: true,
+cbind: {
+   title: '{title}',
+},
+
+layout: {
+   type: 'vbox',
+   align: 'stretch',
+},
+defaults: {
+   layout: 'fit',
+   border: false,
+},
+
+tbar: [
+   {
+   text: gettext('Reload'),
+   iconCls: 'fa fa-refresh',
+   handler: 'reload',
+   },
+],
+
+items: [
+   {
+   xtype: 'proxmoxObjectGrid',
+   reference: 'status',
+   flex: 0,
+   cbind: {
+   url: '{zpoolUri}',
+   nodename: '{nodename}',
+   },
+   rows: {
+   scan: {
+   header: gettext('Scan'),
+   },
+   status: {
+   header: gettext('Status'),
+   },
+   action: {
+   header: gettext('Action'),
+   },
+   errors: {
+   header: gettext('Errors'),
+   },
+   },
+   },
+   {
+   xtype: 'treepanel',
+   reference: 'devices',
+   title: gettext('Devices'),
+   stateful: true,
+   stateId: 'grid-node-zfsstatus',
+   rootVisible: true,
+   fields: ['name', 'status',
+   {
+   type: 'string',
+   name: 'iconCls',
+   calculate: function(data) {
+   var txt = 'fa x-fa-tree fa-';
+   if (data.leaf) {
+   return txt + 'hdd-o';
+   }
+   return undefined;
+   },
+   },
+   ],
+   sorters: 'name',
+   flex: 1,
+   cbind: {
+   zpool: '{zpoolUri}',
+   nodename: '{nodename}',
+   },
+   columns: [
+   {
+   xtype: 'treecolumn',
+   text: gettext('Name'),
+   dataIndex: 'name',
+   flex: 1,
+   },
+   {
+   text: gettext('Health'),
+   renderer: Proxmox.Utils.render_zfs_health,
+   dataIndex: 'state',
+   },
+   {
+   text: 'READ',
+   dataIndex: 'read',
+   },
+   {
+   text: 'WRITE',
+   dataIndex: 'write

[pve-devel] [PATCH widget-toolkit/manager] move/refactor ZFS related gui components into widget-toolkit

2020-06-25 Thread Dominik Csapak
to be used outside of pve
includes some refactor/rewriting, but the components are not that big,
so it should be rather straightforward

manager patches depend on widget-toolkit, but they do not conflict
so we could apply manager sometime later

proxmox-widget-toolkit:

Dominik Csapak (3):
  Utils: add render_zfs_health
  add form/MultiDiskSelector
  add window/ZFSDetail

 src/Makefile  |   2 +
 src/Utils.js  |  25 ++
 src/form/MultiDiskSelector.js | 164 ++
 src/window/ZFSDetail.js   | 152 +++
 4 files changed, 343 insertions(+)
 create mode 100644 src/form/MultiDiskSelector.js
 create mode 100644 src/window/ZFSDetail.js

pve-manager:

Dominik Csapak (1):
  ui: use ZFS components and functions from widget-toolkit

 www/manager6/Utils.js|  26 
 www/manager6/node/ZFS.js | 255 +--
 2 files changed, 6 insertions(+), 275 deletions(-)

-- 
2.20.1


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


[pve-devel] [PATCH widget-toolkit 1/3] Utils: add render_zfs_health

2020-06-25 Thread Dominik Csapak
from pve-manager

Signed-off-by: Dominik Csapak 
---
 src/Utils.js | 25 +
 1 file changed, 25 insertions(+)

diff --git a/src/Utils.js b/src/Utils.js
index b5b1acb..d959dee 100644
--- a/src/Utils.js
+++ b/src/Utils.js
@@ -740,6 +740,31 @@ utilities: {
return Ext.Date.format(servertime, 'Y-m-d H:i:s');
 },
 
+render_zfs_health: function(value) {
+   if (typeof value === 'undefined') {
+   return "";
+   }
+   var iconCls = 'question-circle';
+   switch (value) {
+   case 'AVAIL':
+   case 'ONLINE':
+   iconCls = 'check-circle good';
+   break;
+   case 'REMOVED':
+   case 'DEGRADED':
+   iconCls = 'exclamation-circle warning';
+   break;
+   case 'UNAVAIL':
+   case 'FAULTED':
+   case 'OFFLINE':
+   iconCls = 'times-circle critical';
+   break;
+   default: //unknown
+   }
+
+   return ' ' + value;
+},
+
 get_help_info: function(section) {
let helpMap;
if (typeof proxmoxOnlineHelpInfo !== 'undefined') {
-- 
2.20.1


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


[pve-devel] [PATCH manager] fix #2810: reset state of mounts array in initComponent

2020-06-24 Thread Dominik Csapak
so that each new instance has an empty mounts list

Signed-off-by: Dominik Csapak 
---
@fabian @oguz, i remembered that i know this issue and had a fix already^^
 www/manager6/lxc/FeaturesEdit.js | 8 +++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/www/manager6/lxc/FeaturesEdit.js b/www/manager6/lxc/FeaturesEdit.js
index 1275a2e0..e0b851de 100644
--- a/www/manager6/lxc/FeaturesEdit.js
+++ b/www/manager6/lxc/FeaturesEdit.js
@@ -108,7 +108,13 @@ Ext.define('PVE.lxc.FeaturesInputPanel', {
}
this.callParent([res]);
}
-}
+},
+
+initComponent: function() {
+   let me = this;
+   me.mounts = []; // reset state
+   me.callParent();
+},
 });
 
 Ext.define('PVE.lxc.FeaturesEdit', {
-- 
2.20.1


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


Re: [pve-devel] [PATCH manager] ui: fw: Close #2815: Add warning if fw is disabled

2020-06-23 Thread Dominik Csapak

Looks mosty ok, but i noticed two things:

1. We use this grid also on datacenter and node level, so we should 
adapt the message for those somehow


2. is inline

On 6/23/20 11:31 AM, Dominic Jäger wrote:

Currently people add firewall rules but forget to activate the firewall on
guest level. This commit adds a warning to the top bar of the firewall panel to
make them aware of this if necessary.

It seems a little cheaper but still sufficient to check only if some rule
exists and not for every rule if it is really enabled.

Signed-off-by: Dominic Jäger 
---
  www/manager6/grid/FirewallRules.js | 32 --
  1 file changed, 30 insertions(+), 2 deletions(-)

diff --git a/www/manager6/grid/FirewallRules.js 
b/www/manager6/grid/FirewallRules.js
index ec2d1c84..7cb2baf0 100644
--- a/www/manager6/grid/FirewallRules.js
+++ b/www/manager6/grid/FirewallRules.js
@@ -483,8 +483,26 @@ Ext.define('PVE.FirewallRules', {
throw "no list_refs_url specified";
}
  
+	let checkWarning = function () {

+   Proxmox.Utils.API2Request({
+   url: me.base_url.replace('rules', 'options'),
+   method: 'GET',
+   failure: function (response) {
+   Ext.Msg.alert(gettext('Error'), response.htmlStatus);
+   },
+   success: function (response) {
+   let warningRequired = me.store.getCount() != 0 && 
!response.result.data.enable;
+   
me.down('displayfield[name=fw-warning]').setVisible(warningRequired)
+   },
+   });
+
+   };
+
var store = Ext.create('Ext.data.Store',{
-   model: 'pve-fw-rule'
+   model: 'pve-fw-rule',
+   listeners: {
+   'load': checkWarning,
+   },
});
  
  	var reload = function() {

@@ -606,12 +624,22 @@ Ext.define('PVE.FirewallRules', {
}
});
  
+	me.warningField = Ext.create('Ext.form.field.Display',{

+   xtype: 'displayfield',
+   dock: 'top',
+   userCls: 'pmx-hint',
+   name: 'fw-warning',
+   margin: '10 0 0 0',


i guess you wanted the margin on the left side not top?
the order is: top right bottom left, so you'd have to do
margin: '0 0 0 10'

with this currently the tbar changes height when the warning is 
displayed, which looks odd...


(i don't think we need any margin/padding in tbar)

also the 'dock' property is not necessary (the tbar is already docked)


+   value: gettext('Warning: Firewall still disabled at guest level! 
This can be changed in Firewall->Options.'),
+   hidden: true,
+   });
+
var tbar = me.tbar_prefix ? [ me.tbar_prefix ] : [];
tbar.push(me.addBtn, me.copyBtn);
if (me.groupBtn) {
tbar.push(me.groupBtn);
}
-   tbar.push(me.removeBtn, me.editBtn);
+   tbar.push(me.removeBtn, me.editBtn, me.warningField);
  
  	var render_errors = function(name, value, metaData, record) {

var errors = record.data.errors;




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


Re: [pve-devel] [PATCH qemu-server] vncproxy: allow to request a generated VNC password

2020-06-19 Thread Dominik Csapak

looks good to me and works as expected

if we wanted we could probably make this the default by either
* applying the novnc patch
* alternatively putting the generated password at the beginning of the 
vncticket and removing it before verifying in the websocket api call
this would be ok since the node where the api call is made is always the 
local node (tunneling is over ssh)


but since it really does not matter if we do it at all, we can
simply omit the novnc patch for now and leave it optional

Tested-By: Dominik Csapak 
Reviewed-By: Dominik Csapak 

On 6/18/20 6:20 PM, Thomas Lamprecht wrote:

We used the VNC API $ticket as password for VNC, but QEMU limits the
password to the first 8 chars and ignores the rest[0].
As our tickets start with a static string (e.g., "PVE") the entropy
was a bit limited.

For Proxmox VE this does not matters much as the noVNC viewer
provided by has to go always over the API call, and so a valid
ticket and correct permissions for the requested VM are enforced
anyway.

This patch helps external users, which often use NoVNC-Websockify,
circumventing the API and relying solely on the VNC password to avoid
snooping on VNC sessions.

A 'generate-password' parameter is added, if set a password from good
entropy (using libopenssl) is generated.

For simplicity of mapping random bits to ranges we extract 6 bit of
entropy per character and add the integer value of '!' (first
printable ASCII char) to that. This way we get 64^8 possibilities,
which even with millions of guesses per second one would need years
of guessing and mostly just DDOS the server with websocket upgrade
requests.

Signed-off-by: Thomas Lamprecht 
---

We could also extract the last 8 chars of the ticket, but as that ticket is
only secure as a whole, as seen with this issue, I'd like to avoid that

Initially I had a variant with using perls core rand and all 95 printable ascii
chars, but that wasn't crypthographical secure

  PVE/API2/Qemu.pm | 39 ---
  1 file changed, 36 insertions(+), 3 deletions(-)

diff --git a/PVE/API2/Qemu.pm b/PVE/API2/Qemu.pm
index 3e0d59f..dcb364d 100644
--- a/PVE/API2/Qemu.pm
+++ b/PVE/API2/Qemu.pm
@@ -7,6 +7,7 @@ use Net::SSLeay;
  use POSIX;
  use IO::Socket::IP;
  use URI::Escape;
+use Crypt::OpenSSL::Random;
  
  use PVE::Cluster qw (cfs_read_file cfs_write_file);;

  use PVE::RRD;
@@ -1589,6 +1590,19 @@ __PACKAGE__->register_method({
return undef;
  }});
  
+# uses good entropy, each char is limited to 6 bit to get printable chars simply

+my $gen_rand_chars = sub {
+my ($length) = @_;
+
+die "invalid length $length" if $length < 1;
+
+my $min = ord('!'); # first printable ascii
+my @rand_bytes = split '', Crypt::OpenSSL::Random::random_bytes($length);
+my $str = join('', map { chr((ord($_) & 0x3F) + $min) } @rand_bytes);
+
+return $str;
+};
+
  my $sslcert;
  
  __PACKAGE__->register_method({

@@ -1610,6 +1624,12 @@ __PACKAGE__->register_method({
type => 'boolean',
description => "starts websockify instead of vncproxy",
},
+   'generate-password' => {
+   optional => 1,
+   type => 'boolean',
+   default => 0,
+   description => "Generates a random password to be used as ticket 
instead of the API ticket.",
+   },
},
  },
  returns => {
@@ -1617,6 +1637,12 @@ __PACKAGE__->register_method({
properties => {
user => { type => 'string' },
ticket => { type => 'string' },
+   password => {
+   optional => 1,
+   description => "Returned if requested with 'generate-password' 
param."
+   ." Consists of printable ASCII characters ('!' .. '~').",
+   type => 'string',
+   },
cert => { type => 'string' },
port => { type => 'integer' },
upid => { type => 'string' },
@@ -1644,6 +1670,10 @@ __PACKAGE__->register_method({
my $authpath = "/vms/$vmid";
  
  	my $ticket = PVE::AccessControl::assemble_vnc_ticket($authuser, $authpath);

+   my $password = $ticket;
+   if ($param->{'generate-password'}) {
+   $password = $gen_rand_chars->(8);
+   }
  
  	$sslcert = PVE::Tools::file_get_contents("/etc/pve/pve-root-ca.pem", 8192)

if !$sslcert;
@@ -1680,7 +1710,7 @@ __PACKAGE__->register_method({
'-perm', 'Sys.Console'];
  
  		if ($param->{websocket}) {

-   $ENV{PVE_VNC_TICKET} = $ticket; # pass ticket to vncterm
+   $ENV{PVE_VNC_TICKET} = $password; # pass ticket to vncterm
push @$cmd, '-notls', '-listen', 'localhost';
}
  
@@ -1690,7 +1720,7 @@ __PACKAGE__-

Re: [pve-devel] [PATCH widget-toolkit v2 3/4] TaskViewer: show endtime and duration in status

2020-06-16 Thread Dominik Csapak

On 6/16/20 11:19 AM, Thomas Lamprecht wrote:

Am 6/15/20 um 4:07 PM schrieb Dominik Csapak:

but only when the caller gives us the endtime, since the status
api call does not give us the endtime

Signed-off-by: Dominik Csapak 
---
changes from v1:
* always show duration and calculate the endtime from 'now'

  src/node/Tasks.js|  1 +
  src/window/TaskViewer.js | 25 +
  2 files changed, 26 insertions(+)

diff --git a/src/node/Tasks.js b/src/node/Tasks.js
index 5aff06d..c41f0b5 100644
--- a/src/node/Tasks.js
+++ b/src/node/Tasks.js
@@ -60,6 +60,7 @@ Ext.define('Proxmox.node.Tasks', {
  
  	let win = Ext.create('Proxmox.window.TaskViewer', {

upid: rec.data.upid,
+   endtime: rec.data.endtime,
});
win.show();
};
diff --git a/src/window/TaskViewer.js b/src/window/TaskViewer.js
index 2f31023..51715f8 100644
--- a/src/window/TaskViewer.js
+++ b/src/window/TaskViewer.js
@@ -152,6 +152,31 @@ Ext.define('Proxmox.window.TaskViewer', {
},
};
  
+	if (me.endtime) {

+   if (typeof me.endtime === 'object') {
+   // convert to epoch
+   me.endtime = parseInt(me.endtime.getTime()/1000, 10);
+   }
+   rows.endtime = {
+   header: gettext('End Time'),
+   required: true,
+   renderer: function() {
+   return Proxmox.Utils.render_timestamp(me.endtime);
+   },
+   };
+   }
+
+   rows.duration = {
+   header: gettext('Duration'),
+   required: true,
+   renderer: function() {
+   let starttime = statgrid.getObjectValue('starttime');
+   let endtime = me.endtime || Date.now()/1000;


We'd need to check also the status (running or not) to know if we can still 
fallback
to the current time, or? As else, if a running task gets opened we never will 
get
supplied the endtime (as we only pass that once on window creation) even if the 
task
ends after a bit.
We could solve this by remembering the last duration and then fallback to that 
one
if we have no endtime and the task status switches from running to something 
else?


we already stop the store when the task is stopped, so the renderer will
also not be called then anymore and is stopped

the only thing i do not completely like is that we do not show the 
endtime in that case


i toyed with the idea to also always show
the endtime as '-' and then update it with the last update of the 
renderer, but this would then be probably not consistent with

the 'real' endtime and also i could not get it to work...




+   let duration = endtime - starttime;
+   return Proxmox.Utils.format_duration_human(duration);
+   },
+   };
+
let statstore = Ext.create('Proxmox.data.ObjectStore', {
  url: "/api2/json/nodes/" + task.node + "/tasks/" + me.upid + 
"/status",
interval: 1000,






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


[pve-devel] [PATCH widget-toolkit/manager] move diskrelated code to widget-toolkti

2020-06-16 Thread Dominik Csapak
so that we can reuse it.
where applicable i refactored some code or added some
mappings/properties, but nothing substantial

proxmox-widget-toolkit:

Dominik Csapak (2):
  add DiskSelector from PVE
  add DiskSmart window and DiskList from PVE

 src/Makefile |   3 +
 src/form/DiskSelector.js |  80 ++
 src/grid/DiskList.js | 233 +++
 src/window/DiskSmart.js  | 133 ++
 4 files changed, 449 insertions(+)
 create mode 100644 src/form/DiskSelector.js
 create mode 100644 src/grid/DiskList.js
 create mode 100644 src/window/DiskSmart.js

pve-manager:

Dominik Csapak (2):
  ui: use pmxDiskSelector from widget-toolkit
  ui: use pmxDiskList from widget-toolkit

 www/manager6/Makefile |   2 -
 www/manager6/ceph/OSD.js  |   6 +-
 www/manager6/form/DiskSelector.js |  80 --
 www/manager6/node/Config.js   |   3 +-
 www/manager6/node/Directory.js|   2 +-
 www/manager6/node/Disks.js| 387 --
 www/manager6/node/LVM.js  |   2 +-
 www/manager6/node/LVMThin.js  |   2 +-
 8 files changed, 8 insertions(+), 476 deletions(-)
 delete mode 100644 www/manager6/form/DiskSelector.js
 delete mode 100644 www/manager6/node/Disks.js

-- 
2.20.1


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


[pve-devel] [PATCH manager 1/2] ui: use pmxDiskSelector from widget-toolkit

2020-06-16 Thread Dominik Csapak
Signed-off-by: Dominik Csapak 
---
 www/manager6/Makefile |  1 -
 www/manager6/ceph/OSD.js  |  6 +--
 www/manager6/form/DiskSelector.js | 80 ---
 www/manager6/node/Directory.js|  2 +-
 www/manager6/node/LVM.js  |  2 +-
 www/manager6/node/LVMThin.js  |  2 +-
 6 files changed, 6 insertions(+), 87 deletions(-)
 delete mode 100644 www/manager6/form/DiskSelector.js

diff --git a/www/manager6/Makefile b/www/manager6/Makefile
index 5656ba27..7ebd4db3 100644
--- a/www/manager6/Makefile
+++ b/www/manager6/Makefile
@@ -30,7 +30,6 @@ JSSRC=
\
form/MemoryField.js \
form/NetworkCardSelector.js \
form/DiskFormatSelector.js  \
-   form/DiskSelector.js\
form/BusTypeSelector.js \
form/ControllerSelector.js  \
form/EmailNotificationSelector.js   \
diff --git a/www/manager6/ceph/OSD.js b/www/manager6/ceph/OSD.js
index ffdfbee7..88109315 100644
--- a/www/manager6/ceph/OSD.js
+++ b/www/manager6/ceph/OSD.js
@@ -34,7 +34,7 @@ Ext.define('PVE.CephCreateOsd', {
},
column1: [
{
-   xtype: 'pveDiskSelector',
+   xtype: 'pmxDiskSelector',
name: 'dev',
nodename: me.nodename,
diskType: 'unused',
@@ -44,7 +44,7 @@ Ext.define('PVE.CephCreateOsd', {
],
column2: [
{
-   xtype: 'pveDiskSelector',
+   xtype: 'pmxDiskSelector',
name: 'db_dev',
nodename: me.nodename,
diskType: 'journal_disks',
@@ -80,7 +80,7 @@ Ext.define('PVE.CephCreateOsd', {
],
advancedColumn2: [
{
-   xtype: 'pveDiskSelector',
+   xtype: 'pmxDiskSelector',
name: 'wal_dev',
nodename: me.nodename,
diskType: 'journal_disks',
diff --git a/www/manager6/form/DiskSelector.js 
b/www/manager6/form/DiskSelector.js
deleted file mode 100644
index a1ea02e7..
--- a/www/manager6/form/DiskSelector.js
+++ /dev/null
@@ -1,80 +0,0 @@
-Ext.define('PVE.form.DiskSelector', {
-extend: 'Proxmox.form.ComboGrid',
-xtype: 'pveDiskSelector',
-
-// can be
-// undefined: all
-// unused: only unused
-// journal_disk: all disks with gpt
-diskType: undefined,
-
-valueField: 'devpath',
-displayField: 'devpath',
-emptyText: gettext('No Disks unused'),
-listConfig: {
-   width: 600,
-   columns: [
-   {
-   header: gettext('Device'),
-   flex: 3,
-   sortable: true,
-   dataIndex: 'devpath'
-   },
-   {
-   header: gettext('Size'),
-   flex: 2,
-   sortable: false,
-   renderer: Proxmox.Utils.format_size,
-   dataIndex: 'size'
-   },
-   {
-   header: gettext('Serial'),
-   flex: 5,
-   sortable: true,
-   dataIndex: 'serial'
-   }
-   ]
-},
-
-initComponent: function() {
-   var me = this;
-
-   var nodename = me.nodename;
-   if (!nodename) {
-   throw "no node name specified";
-   }
-
-   var store = Ext.create('Ext.data.Store', {
-   filterOnLoad: true,
-   model: 'pve-disk-list',
-   proxy: {
-type: 'proxmox',
-url: "/api2/json/nodes/" + nodename + "/disks/list",
-   extraParams: { type: me.diskType }
-   },
-   sorters: [
-   {
-   property : 'devpath',
-   direction: 'ASC'
-   }
-   ]
-   });
-
-   Ext.apply(me, {
-   store: store
-   });
-
-me.callParent();
-
-   store.load();
-}
-}, function() {
-
-Ext.define('pve-disk-list', {
-   extend: 'Ext.data.Model',
-   fields: [ 'devpath', 'used', { name: 'size', type: 'number'},
- {name: 'osdid', type: 'number'},
- 'vendor', 'model', 'serial'],
-   idProperty: 'devpath'
-});
-});
diff --git a/www/manager6/node/Directory.js b/www/manager6/node/Directory.js
index e72ebe86..6e2e3c2f 100644
--- a/www/manager6/node/Directory.js
+++ b/www/manager6/node/Directory.js
@@ -22,7 +22,7 @@ Ext.define('PVE.node.CreateDirectory', {
method: 'POST',
items: [
{
-

[pve-devel] [PATCH widget-toolkit 1/2] add DiskSelector from PVE

2020-06-16 Thread Dominik Csapak
to be usable with other products.
also add a parameter 'typeProperty' to be able to configure
the backend property for the usage type

Signed-off-by: Dominik Csapak 
---
 src/Makefile |  1 +
 src/form/DiskSelector.js | 80 
 2 files changed, 81 insertions(+)
 create mode 100644 src/form/DiskSelector.js

diff --git a/src/Makefile b/src/Makefile
index 659e876..2696103 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -29,6 +29,7 @@ JSSRC=\
form/NetworkSelector.js \
form/RealmComboBox.js   \
form/RoleSelector.js\
+   form/DiskSelector.js\
button/Button.js\
button/HelpButton.js\
grid/ObjectGrid.js  \
diff --git a/src/form/DiskSelector.js b/src/form/DiskSelector.js
new file mode 100644
index 000..4552beb
--- /dev/null
+++ b/src/form/DiskSelector.js
@@ -0,0 +1,80 @@
+Ext.define('Proxmox.form.DiskSelector', {
+extend: 'Proxmox.form.ComboGrid',
+xtype: 'pmxDiskSelector',
+
+// can be
+// undefined: all
+// unused: only unused
+// journal_disk: all disks with gpt
+diskType: undefined,
+
+// the property the backend wnats for the type ('type' by default)
+typeProperty: 'type',
+
+valueField: 'devpath',
+displayField: 'devpath',
+emptyText: gettext('No Disks unused'),
+listConfig: {
+   width: 600,
+   columns: [
+   {
+   header: gettext('Device'),
+   flex: 3,
+   sortable: true,
+   dataIndex: 'devpath',
+   },
+   {
+   header: gettext('Size'),
+   flex: 2,
+   sortable: false,
+   renderer: Proxmox.Utils.format_size,
+   dataIndex: 'size',
+   },
+   {
+   header: gettext('Serial'),
+   flex: 5,
+   sortable: true,
+   dataIndex: 'serial',
+   },
+   ],
+},
+
+initComponent: function() {
+   var me = this;
+
+   var nodename = me.nodename;
+   if (!nodename) {
+   throw "no node name specified";
+   }
+
+   let extraParams = {};
+
+   if (me.diskType) {
+   extraParams[me.typeProperty] = me.diskType;
+   }
+
+   var store = Ext.create('Ext.data.Store', {
+   filterOnLoad: true,
+   model: 'pmx-disk-list',
+   proxy: {
+type: 'proxmox',
+url: `/api2/json/nodes/${nodename}/disks/list`,
+   extraParams,
+   },
+   sorters: [
+   {
+   property: 'devpath',
+   direction: 'ASC',
+   },
+   ],
+   });
+
+   Ext.apply(me, {
+   store: store,
+   });
+
+me.callParent();
+
+   store.load();
+},
+});
-- 
2.20.1


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


[pve-devel] [PATCH widget-toolkit 2/2] add DiskSmart window and DiskList from PVE

2020-06-16 Thread Dominik Csapak
for use with other produts.

the models are now all prefixed with 'pmx' instead of pve, so they
should not conflict

includes some changes to the model for remapping some fields and
some small refactors (change to controller for the DiskList,
some cleanup of the initComponent of the DiskSmart window)

Signed-off-by: Dominik Csapak 
---
 src/Makefile|   2 +
 src/grid/DiskList.js| 233 
 src/window/DiskSmart.js | 133 +++
 3 files changed, 368 insertions(+)
 create mode 100644 src/grid/DiskList.js
 create mode 100644 src/window/DiskSmart.js

diff --git a/src/Makefile b/src/Makefile
index 2696103..3311bbe 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -34,6 +34,7 @@ JSSRC=\
button/HelpButton.js\
grid/ObjectGrid.js  \
grid/PendingObjectGrid.js   \
+   grid/DiskList.js\
panel/InputPanel.js \
panel/LogView.js\
panel/JournalView.js\
@@ -43,6 +44,7 @@ JSSRC=\
window/PasswordEdit.js  \
window/TaskViewer.js\
window/LanguageEdit.js  \
+   window/DiskSmart.js \
node/APT.js \
node/NetworkEdit.js \
node/NetworkView.js \
diff --git a/src/grid/DiskList.js b/src/grid/DiskList.js
new file mode 100644
index 000..03d6725
--- /dev/null
+++ b/src/grid/DiskList.js
@@ -0,0 +1,233 @@
+Ext.define('pmx-disk-list', {
+extend: 'Ext.data.Model',
+fields: [
+   'devpath', 'used',
+   { name: 'size', type: 'number' },
+   { name: 'osdid', type: 'number' },
+   {
+   name: 'status',
+   convert: function(value, rec) {
+   if (value) return value;
+   if (rec.data.health) {
+   return rec.data.health;
+   }
+   return Proxmox.Utils.unknownText;
+   },
+   },
+   {
+   name: 'name',
+   convert: function(value, rec) {
+   if (value) return value;
+   if (rec.data.devpath) return rec.data.devpath;
+   return undefined;
+   },
+   },
+   {
+   name: 'disk-type',
+   convert: function(value, rec) {
+   if (value) return value;
+   if (rec.data.type) return rec.data.type;
+   return undefined;
+   },
+   },
+   'vendor', 'model', 'serial', 'rpm', 'type', 'wearout', 'health',
+],
+idProperty: 'devpath',
+});
+
+Ext.define('Proxmox.DiskList', {
+extend: 'Ext.grid.GridPanel',
+alias: 'widget.pmxDiskList',
+
+emptyText: gettext('No Disks found'),
+
+stateful: true,
+stateId: 'grid-node-disks',
+
+controller: {
+   xclass: 'Ext.app.ViewController',
+
+   reload: function() {
+   let me = this;
+   me.getView().getStore().load();
+   },
+
+   openSmartWindow: function() {
+   let me = this;
+   let view = me.getView();
+   let selection = view.getSelection();
+   if (!selection || selection.length < 1) return;
+
+   let rec = selection[0];
+   Ext.create('Proxmox.window.DiskSmart', {
+   baseurl: view.baseurl,
+   dev: rec.data.name,
+   }).show();
+   },
+
+   initGPT: function() {
+   let me = this;
+   let view = me.getView();
+   let selection = view.getSelection();
+   if (!selection || selection.length < 1) return;
+
+   let rec = selection[0];
+   Proxmox.Utils.API2Request({
+   url: `${view.baseurl}/initgpt`,
+   waitMsgTarget: view,
+   method: 'POST',
+   params: { disk: rec.data.devpath },
+   failure: function(response, options) {
+   Ext.Msg.alert(gettext('Error'), response.htmlStatus);
+   },
+   success: function(response, options) {
+   var upid = response.result.data;
+   var win = Ext.create('Proxmox.window.TaskProgress', {
+   upid: upid,
+   });
+   win.show();
+   },
+   });
+   },
+
+   init: function(view) {
+   Proxmox.Utils.monStoreErrors(view, view.getStore(), true);
+
+   let nodename = view.nodename || 'localhost';
+   view.baseurl = `/api2/json/nodes/${nodename}/disks`;
+   view.getStore().getProxy().setUrl(`${view.baseurl}/list`);
+   view.getStore().load();
+   },
+},
+
+store: {
+   model: 'pmx-disk-list',
+   proxy: {
+   type: 'proxmox',
+   },
+   sorters: [
+   {
+   property: 'dev',
+   direction

[pve-devel] [PATCH manager 2/2] ui: use pmxDiskList from widget-toolkit

2020-06-16 Thread Dominik Csapak
Signed-off-by: Dominik Csapak 
---
 www/manager6/Makefile   |   1 -
 www/manager6/node/Config.js |   3 +-
 www/manager6/node/Disks.js  | 387 
 3 files changed, 2 insertions(+), 389 deletions(-)
 delete mode 100644 www/manager6/node/Disks.js

diff --git a/www/manager6/Makefile b/www/manager6/Makefile
index 7ebd4db3..ff452184 100644
--- a/www/manager6/Makefile
+++ b/www/manager6/Makefile
@@ -116,7 +116,6 @@ JSSRC=  
\
ceph/Config.js  \
ceph/Log.js \
ceph/CephInstallWizard.js   \
-   node/Disks.js   \
node/LVM.js \
node/LVMThin.js \
node/Directory.js   \
diff --git a/www/manager6/node/Config.js b/www/manager6/node/Config.js
index b5e6fd1a..f45bd370 100644
--- a/www/manager6/node/Config.js
+++ b/www/manager6/node/Config.js
@@ -275,7 +275,8 @@ Ext.define('PVE.node.Config', {
itemId: 'storage',
expandedOnInit: true,
iconCls: 'fa fa-hdd-o',
-   xtype: 'pveNodeDiskList'
+   nodename: nodename,
+   xtype: 'pmxDiskList'
},
{
title: 'LVM',
diff --git a/www/manager6/node/Disks.js b/www/manager6/node/Disks.js
deleted file mode 100644
index e8ae2767..
--- a/www/manager6/node/Disks.js
+++ /dev/null
@@ -1,387 +0,0 @@
-Ext.define('PVE.node.DiskList', {
-extend: 'Ext.grid.GridPanel',
-alias: 'widget.pveNodeDiskList',
-
-emptyText: gettext('No Disks found'),
-
-stateful: true,
-stateId: 'grid-node-disks',
-
-columns: [
-   {
-   header: gettext('Device'),
-   width: 150,
-   sortable: true,
-   dataIndex: 'devpath'
-   },
-   {
-   header: gettext('Type'),
-   width: 80,
-   sortable: true,
-   dataIndex: 'type',
-   renderer: function(v) {
-   if (v === 'ssd') {
-   return 'SSD';
-   } else if (v === 'hdd') {
-   return 'Hard Disk';
-   } else if (v === 'usb'){
-   return 'USB';
-   } else {
-   return gettext('Unknown');
-   }
-   }
-   },
-   {
-   header: gettext('Usage'),
-   width: 150,
-   sortable: false,
-   renderer: function(v, metaData, rec) {
-   if (rec) {
-   if (rec.data.osdid >= 0) {
-   var bluestore = '';
-   if (rec.data.bluestore === 1) {
-   bluestore = ' (Bluestore)';
-   }
-   return "Ceph osd." + rec.data.osdid.toString() + 
bluestore;
-   }
-
-   var types = [];
-   if (rec.data.journals > 0) {
-   types.push('Journal');
-   }
-
-   if (rec.data.db > 0) {
-   types.push('DB');
-   }
-
-   if (rec.data.wal > 0) {
-   types.push('WAL');
-   }
-
-   if (types.length > 0) {
-   return 'Ceph (' + types.join(', ') + ')';
-   }
-   }
-
-   return v || Proxmox.Utils.noText;
-   },
-   dataIndex: 'used'
-   },
-   {
-   header: gettext('Size'),
-   width: 100,
-   align: 'right',
-   sortable: true,
-   renderer: Proxmox.Utils.format_size,
-   dataIndex: 'size'
-   },
-   {
-   header: 'GPT',
-   width: 60,
-   align: 'right',
-   renderer: Proxmox.Utils.format_boolean,
-   dataIndex: 'gpt'
-   },
-   {
-   header: gettext('Vendor'),
-   width: 100,
-   sortable: true,
-   hidden: true,
-   renderer: Ext.String.htmlEncode,
-   dataIndex: 'vendor'
-   },
-   {
-   header: gettext('Model'),
-   width: 200,
-   sortable: true,
-   renderer: Ext.String.htmlEncode,
-   dataIndex: 'model'
-   },
-   {
-   header: gettext('Serial'),
-   width: 200,
-   sortable: true,
-   renderer: Ext.String.htmlEncode,
-   dataIndex: 'serial'
-   },
-   {
-   header: 'S.M.A.R.T.',
-   width: 100,
-   sortable: true,
-   renderer: Ext.String.htmlEncode,
-   dataIndex: 'health'
-   },
-   {
-   header: 'Wearout',
-   width: 90,
-   sortable: true,
-   align: 'righ

[pve-devel] [PATCH widget-toolkit v2 2/4] show Task warnings differently

2020-06-15 Thread Dominik Csapak
tasks can now show also 'WARNINGS: '
filter it out and provide a 'parse_task_status' function for easy reuse

Signed-off-by: Dominik Csapak 
---
 src/Utils.js | 17 +
 src/css/ext6-pmx.css |  4 
 src/node/Tasks.js| 22 --
 3 files changed, 37 insertions(+), 6 deletions(-)

diff --git a/src/Utils.js b/src/Utils.js
index c3b13f4..2163794 100644
--- a/src/Utils.js
+++ b/src/Utils.js
@@ -711,6 +711,23 @@ utilities: {
return task;
 },
 
+parse_task_status: function(status) {
+   if (status === 'OK') {
+   return 'ok';
+   }
+
+   if (status === 'unknown') {
+   return 'unknown';
+   }
+
+   let match = status.match(/^WARNINGS: (.*)$/);
+   if (match) {
+   return 'warning';
+   }
+
+   return 'error';
+},
+
 render_duration: function(value) {
if (value === undefined) {
return '-';
diff --git a/src/css/ext6-pmx.css b/src/css/ext6-pmx.css
index a7d446b..df5c73d 100644
--- a/src/css/ext6-pmx.css
+++ b/src/css/ext6-pmx.css
@@ -14,6 +14,10 @@
 background-color: #f3d6d7;
 }
 
+.proxmox-warning-row {
+background-color: #f5e5d8;
+}
+
 /* some icons have to be color manually */
 .black {
 color: #000;
diff --git a/src/node/Tasks.js b/src/node/Tasks.js
index 3d9267e..5aff06d 100644
--- a/src/node/Tasks.js
+++ b/src/node/Tasks.js
@@ -81,8 +81,13 @@ Ext.define('Proxmox.node.Tasks', {
getRowClass: function(record, index) {
let status = record.get('status');
 
-   if (status && status !== 'OK') {
-   return "proxmox-invalid-row";
+   if (status) {
+   let parsed = Proxmox.Utils.parse_task_status(status);
+   if (parsed === 'error') {
+   return "proxmox-invalid-row";
+   } else if (parsed === 'warning') {
+   return "proxmox-warning-row";
+   }
}
return '';
},
@@ -162,14 +167,19 @@ Ext.define('Proxmox.node.Tasks', {
dataIndex: 'status',
width: 200,
renderer: function(value, metaData, record) {
-   if (value === 'OK') {
-   return 'OK';
-   }
if (value === undefined && !record.data.endtime) {
metaData.tdCls = "x-grid-row-loading";
return '';
}
-   return "ERROR: " + value;
+
+   let parsed = Proxmox.Utils.parse_task_status(value);
+   switch (parsed) {
+   case 'unknown': return Proxmox.Utils.unknownText;
+   case 'error': return Proxmox.Utils.errorText + ': ' 
+ value;
+   case 'ok': // fall-through
+   case 'warning': // fall-through
+   default: return value;
+   }
},
},
],
-- 
2.20.1


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


[pve-devel] [PATCH widget-toolkit v2 3/4] TaskViewer: show endtime and duration in status

2020-06-15 Thread Dominik Csapak
but only when the caller gives us the endtime, since the status
api call does not give us the endtime

Signed-off-by: Dominik Csapak 
---
changes from v1:
* always show duration and calculate the endtime from 'now'

 src/node/Tasks.js|  1 +
 src/window/TaskViewer.js | 25 +
 2 files changed, 26 insertions(+)

diff --git a/src/node/Tasks.js b/src/node/Tasks.js
index 5aff06d..c41f0b5 100644
--- a/src/node/Tasks.js
+++ b/src/node/Tasks.js
@@ -60,6 +60,7 @@ Ext.define('Proxmox.node.Tasks', {
 
let win = Ext.create('Proxmox.window.TaskViewer', {
upid: rec.data.upid,
+   endtime: rec.data.endtime,
});
win.show();
};
diff --git a/src/window/TaskViewer.js b/src/window/TaskViewer.js
index 2f31023..51715f8 100644
--- a/src/window/TaskViewer.js
+++ b/src/window/TaskViewer.js
@@ -152,6 +152,31 @@ Ext.define('Proxmox.window.TaskViewer', {
},
};
 
+   if (me.endtime) {
+   if (typeof me.endtime === 'object') {
+   // convert to epoch
+   me.endtime = parseInt(me.endtime.getTime()/1000, 10);
+   }
+   rows.endtime = {
+   header: gettext('End Time'),
+   required: true,
+   renderer: function() {
+   return Proxmox.Utils.render_timestamp(me.endtime);
+   },
+   };
+   }
+
+   rows.duration = {
+   header: gettext('Duration'),
+   required: true,
+   renderer: function() {
+   let starttime = statgrid.getObjectValue('starttime');
+   let endtime = me.endtime || Date.now()/1000;
+   let duration = endtime - starttime;
+   return Proxmox.Utils.format_duration_human(duration);
+   },
+   };
+
let statstore = Ext.create('Proxmox.data.ObjectStore', {
 url: "/api2/json/nodes/" + task.node + "/tasks/" + me.upid + 
"/status",
interval: 1000,
-- 
2.20.1


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


[pve-devel] [PATCH widget-toolkit v2 1/4] ProxmoxProxy: add duration fields for proxmox-tasks

2020-06-15 Thread Dominik Csapak
Signed-off-by: Dominik Csapak 
---
changes from v1:
* do not truncate the decimal places
 src/data/ProxmoxProxy.js | 12 
 1 file changed, 12 insertions(+)

diff --git a/src/data/ProxmoxProxy.js b/src/data/ProxmoxProxy.js
index 53e92f3..7df8f28 100644
--- a/src/data/ProxmoxProxy.js
+++ b/src/data/ProxmoxProxy.js
@@ -43,6 +43,18 @@ Ext.define('Proxmox.RestProxy', {
{ name: 'starttime', type: 'date', dateFormat: 'timestamp' },
{ name: 'endtime', type: 'date', dateFormat: 'timestamp' },
{ name: 'pid', type: 'int' },
+   {
+   name: 'duration',
+   sortType: 'asInt',
+   calculate: function(data) {
+   let endtime = data.endtime;
+   let starttime = data.starttime;
+   if (endtime !== undefined) {
+   return (endtime - starttime)/1000;
+   }
+   return 0;
+   },
+   },
'node', 'upid', 'user', 'status', 'type', 'id',
],
idProperty: 'upid',
-- 
2.20.1


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


[pve-devel] [PATCH widget-toolkit v2 4/4] format_duration_human: say <0.1s instead of 0s

2020-06-15 Thread Dominik Csapak
if we get a duration of <=0.1s it should actually be somewhere
betweeen 0 and 0.1 so return <0.1s

Signed-off-by: Dominik Csapak 
---
changes from v1:
* change <1s to <0.1s which is more inline with our normal display (e.g. 1.5s)

 src/Utils.js | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/Utils.js b/src/Utils.js
index 2163794..b5b1acb 100644
--- a/src/Utils.js
+++ b/src/Utils.js
@@ -157,8 +157,8 @@ utilities: {
 format_duration_human: function(ut) {
let seconds = 0, minutes = 0, hours = 0, days = 0;
 
-   if (ut <= 0) {
-   return '0s';
+   if (ut <= 0.1) {
+   return '<0.1s';
}
 
let remaining = ut;
-- 
2.20.1


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


[pve-devel] [PATCH widget-toolkit 2/4] show Task warnings differently

2020-06-12 Thread Dominik Csapak
tasks can now show also 'WARNINGS: '
filter it out and provide a 'parse_task_status' function for easy reuse

Signed-off-by: Dominik Csapak 
---
 src/Utils.js | 17 +
 src/css/ext6-pmx.css |  4 
 src/node/Tasks.js| 22 --
 3 files changed, 37 insertions(+), 6 deletions(-)

diff --git a/src/Utils.js b/src/Utils.js
index c3b13f4..2163794 100644
--- a/src/Utils.js
+++ b/src/Utils.js
@@ -711,6 +711,23 @@ utilities: {
return task;
 },
 
+parse_task_status: function(status) {
+   if (status === 'OK') {
+   return 'ok';
+   }
+
+   if (status === 'unknown') {
+   return 'unknown';
+   }
+
+   let match = status.match(/^WARNINGS: (.*)$/);
+   if (match) {
+   return 'warning';
+   }
+
+   return 'error';
+},
+
 render_duration: function(value) {
if (value === undefined) {
return '-';
diff --git a/src/css/ext6-pmx.css b/src/css/ext6-pmx.css
index a7d446b..df5c73d 100644
--- a/src/css/ext6-pmx.css
+++ b/src/css/ext6-pmx.css
@@ -14,6 +14,10 @@
 background-color: #f3d6d7;
 }
 
+.proxmox-warning-row {
+background-color: #f5e5d8;
+}
+
 /* some icons have to be color manually */
 .black {
 color: #000;
diff --git a/src/node/Tasks.js b/src/node/Tasks.js
index 3d9267e..5aff06d 100644
--- a/src/node/Tasks.js
+++ b/src/node/Tasks.js
@@ -81,8 +81,13 @@ Ext.define('Proxmox.node.Tasks', {
getRowClass: function(record, index) {
let status = record.get('status');
 
-   if (status && status !== 'OK') {
-   return "proxmox-invalid-row";
+   if (status) {
+   let parsed = Proxmox.Utils.parse_task_status(status);
+   if (parsed === 'error') {
+   return "proxmox-invalid-row";
+   } else if (parsed === 'warning') {
+   return "proxmox-warning-row";
+   }
}
return '';
},
@@ -162,14 +167,19 @@ Ext.define('Proxmox.node.Tasks', {
dataIndex: 'status',
width: 200,
renderer: function(value, metaData, record) {
-   if (value === 'OK') {
-   return 'OK';
-   }
if (value === undefined && !record.data.endtime) {
metaData.tdCls = "x-grid-row-loading";
return '';
}
-   return "ERROR: " + value;
+
+   let parsed = Proxmox.Utils.parse_task_status(value);
+   switch (parsed) {
+   case 'unknown': return Proxmox.Utils.unknownText;
+   case 'error': return Proxmox.Utils.errorText + ': ' 
+ value;
+   case 'ok': // fall-through
+   case 'warning': // fall-through
+   default: return value;
+   }
},
},
],
-- 
2.20.1


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


[pve-devel] [PATCH widget-toolkit 4/4] format_duration_human: say <1s instead of 0s

2020-06-12 Thread Dominik Csapak
if we get a duration of <=0s it should actually be somewhere
betweeen 0 and 1s so return <1s

Signed-off-by: Dominik Csapak 
---
 src/Utils.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/Utils.js b/src/Utils.js
index 2163794..a914795 100644
--- a/src/Utils.js
+++ b/src/Utils.js
@@ -158,7 +158,7 @@ utilities: {
let seconds = 0, minutes = 0, hours = 0, days = 0;
 
if (ut <= 0) {
-   return '0s';
+   return '<1s';
}
 
let remaining = ut;
-- 
2.20.1


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


[pve-devel] [PATCH widget-toolkit 3/4] TaskViewer: show endtime and duration in status

2020-06-12 Thread Dominik Csapak
but only when the caller gives us the endtime, since the status
api call does not give us the endtime

Signed-off-by: Dominik Csapak 
---
 src/node/Tasks.js|  1 +
 src/window/TaskViewer.js | 23 +++
 2 files changed, 24 insertions(+)

diff --git a/src/node/Tasks.js b/src/node/Tasks.js
index 5aff06d..c41f0b5 100644
--- a/src/node/Tasks.js
+++ b/src/node/Tasks.js
@@ -60,6 +60,7 @@ Ext.define('Proxmox.node.Tasks', {
 
let win = Ext.create('Proxmox.window.TaskViewer', {
upid: rec.data.upid,
+   endtime: rec.data.endtime,
});
win.show();
};
diff --git a/src/window/TaskViewer.js b/src/window/TaskViewer.js
index 2f31023..fedf693 100644
--- a/src/window/TaskViewer.js
+++ b/src/window/TaskViewer.js
@@ -152,6 +152,29 @@ Ext.define('Proxmox.window.TaskViewer', {
},
};
 
+   if (me.endtime) {
+   if (typeof me.endtime === 'object') {
+   // convert to epoch
+   me.endtime = parseInt(me.endtime.getTime()/1000, 10);
+   }
+   rows.endtime = {
+   header: gettext('End Time'),
+   required: true,
+   renderer: function() {
+   return Proxmox.Utils.render_timestamp(me.endtime);
+   },
+   };
+   rows.duration = {
+   header: gettext('Duration'),
+   required: true,
+   renderer: function() {
+   let starttime = statgrid.getObjectValue('starttime');
+   let duration = me.endtime - starttime;
+   return Proxmox.Utils.format_duration_human(duration);
+   },
+   };
+   }
+
let statstore = Ext.create('Proxmox.data.ObjectStore', {
 url: "/api2/json/nodes/" + task.node + "/tasks/" + me.upid + 
"/status",
interval: 1000,
-- 
2.20.1


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


[pve-devel] [PATCH widget-toolkit 1/4] ProxmoxProxy: add duration fields for proxmox-tasks

2020-06-12 Thread Dominik Csapak
Signed-off-by: Dominik Csapak 
---
 src/data/ProxmoxProxy.js | 12 
 1 file changed, 12 insertions(+)

diff --git a/src/data/ProxmoxProxy.js b/src/data/ProxmoxProxy.js
index 53e92f3..40fdc08 100644
--- a/src/data/ProxmoxProxy.js
+++ b/src/data/ProxmoxProxy.js
@@ -43,6 +43,18 @@ Ext.define('Proxmox.RestProxy', {
{ name: 'starttime', type: 'date', dateFormat: 'timestamp' },
{ name: 'endtime', type: 'date', dateFormat: 'timestamp' },
{ name: 'pid', type: 'int' },
+   {
+   name: 'duration',
+   sortType: 'asInt',
+   calculate: function(data) {
+   let endtime = data.endtime;
+   let starttime = data.starttime;
+   if (endtime !== undefined) {
+   return ((endtime - starttime)/1000).toFixed(0);
+   }
+   return 0;
+   },
+   },
'node', 'upid', 'user', 'status', 'type', 'id',
],
idProperty: 'upid',
-- 
2.20.1


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


[pve-devel] [PATCH widget-toolkit] button: make xtype of parent configurable

2020-06-04 Thread Dominik Csapak
to get the selection model of the parent, we use by default the xtype
'grid', but sometimes we want to use something else (e.g. 'treepanel')

to be flexible we make this configurable

Signed-off-by: Dominik Csapak 
---
we could of course fall back to 'treepanel' directly in the code if thats
preferred

 button/Button.js | 9 ++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/button/Button.js b/button/Button.js
index 68c6e98..9b8d66e 100644
--- a/button/Button.js
+++ b/button/Button.js
@@ -20,6 +20,9 @@ Ext.define('Proxmox.button.Button', {
 // take special care in confirm box (select no as default).
 dangerous: false,
 
+// is used to get the parent container for its selection model
+parentXType: 'grid',
+
 initComponent: function() {
 var me = this;
 
@@ -65,9 +68,9 @@ Ext.define('Proxmox.button.Button', {
 
var grid;
if (!me.selModel && me.selModel !== null && me.selModel !== false) {
-   grid = me.up('grid');
-   if (grid && grid.selModel) {
-   me.selModel = grid.selModel;
+   parent = me.up(me.parentXType);
+   if (parent && parent.selModel) {
+   me.selModel = parent.selModel;
}
}
 
-- 
2.20.1


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


[pve-devel] [PATCH http-server 2/2] fix post if variable declaration

2020-05-29 Thread Dominik Csapak
Signed-off-by: Dominik Csapak 
---
 PVE/APIServer/AnyEvent.pm | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/PVE/APIServer/AnyEvent.pm b/PVE/APIServer/AnyEvent.pm
index e5f2cb4..efb8168 100644
--- a/PVE/APIServer/AnyEvent.pm
+++ b/PVE/APIServer/AnyEvent.pm
@@ -1322,7 +1322,8 @@ sub unshift_read_header {
}
 
my $ctype = $r->header('Content-Type');
-   my ($ct, $boundary) = parse_content_type($ctype) if $ctype;
+   my ($ct, $boundary);
+   ($ct, $boundary)= parse_content_type($ctype) if $ctype;
 
if ($auth->{isUpload} && !$self->{trusted_env}) {
die "upload 'Content-Type '$ctype' not implemented\n"
-- 
2.20.1


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


[pve-devel] [PATCH http-server 1/2] fix #2766: allow application/json as content-type for post/put requests

2020-05-29 Thread Dominik Csapak
this makes creating an api client much nicer

Signed-off-by: Dominik Csapak 
---
 PVE/APIServer/AnyEvent.pm | 13 +++--
 1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/PVE/APIServer/AnyEvent.pm b/PVE/APIServer/AnyEvent.pm
index 3d755d4..e5f2cb4 100644
--- a/PVE/APIServer/AnyEvent.pm
+++ b/PVE/APIServer/AnyEvent.pm
@@ -44,6 +44,7 @@ use HTTP::Headers;
 use HTTP::Request;
 use HTTP::Response;
 use Data::Dumper;
+use JSON;
 
 my $limit_max_headers = 30;
 my $limit_max_header_size = 8*1024;
@@ -693,7 +694,15 @@ sub extract_params {
 my $params = {};
 
 if ($method eq 'PUT' || $method eq 'POST') {
-   $params = decode_urlencoded($r->content);
+   my $ct;
+   if (my $ctype = $r->header('Content-Type')) {
+   $ct = parse_content_type($ctype);
+   }
+   if (defined($ct) && $ct eq 'application/json')  {
+   $params = decode_json($r->content);
+   } else {
+   $params = decode_urlencoded($r->content);
+   }
 }
 
 my $query_params = decode_urlencoded($r->url->query());
@@ -1356,7 +1365,7 @@ sub unshift_read_header {
return;
}
 
-   if (!$ct || $ct eq 'application/x-www-form-urlencoded') {
+   if (!$ct || $ct eq 'application/x-www-form-urlencoded' || 
$ct eq 'application/json') {
$reqstate->{hdl}->unshift_read(chunk => $len, sub {
my ($hdl, $data) = @_;
$r->content($data);
-- 
2.20.1


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


[pve-devel] [PATCH manager] ui: add checkbox for vmid filter for backupview

2020-05-29 Thread Dominik Csapak
instead of hardcoding the text 'type-id-' into the searchbar
to accomodate for the additional size, add an overflowHandler
to the toolbar (for very small display sizes)

Signed-off-by: Dominik Csapak 
---
 www/manager6/grid/BackupView.js | 49 ++---
 1 file changed, 39 insertions(+), 10 deletions(-)

diff --git a/www/manager6/grid/BackupView.js b/www/manager6/grid/BackupView.js
index a74c6ccb..5d80bdaf 100644
--- a/www/manager6/grid/BackupView.js
+++ b/www/manager6/grid/BackupView.js
@@ -41,13 +41,16 @@ Ext.define('PVE.grid.BackupView', {
 
var searchFilter = {
property: 'volid',
-   // on initial store display only our vmid backups
-   // surround with minus sign to prevent the 2016 VMID bug
-   value: vmtype + '-' + vmid + '-',
+   value: '',
anyMatch: true,
caseSensitive: false
};
 
+   var vmidFilter = {
+   property: 'vmid',
+   value: vmid,
+   };
+
me.store = Ext.create('Ext.data.Store', {
model: 'pve-storage-content',
sorters: { 
@@ -56,10 +59,19 @@ Ext.define('PVE.grid.BackupView', {
},
filters: [
vmtypeFilter,
-   searchFilter
+   searchFilter,
+   vmidFilter,
]
});
 
+   let updateFilter = function() {
+   me.store.filter([
+   vmtypeFilter,
+   searchFilter,
+   vmidFilter,
+   ]);
+   };
+
var reload = Ext.Function.createBuffered(function() {
if (me.store) {
me.store.load();
@@ -102,14 +114,23 @@ Ext.define('PVE.grid.BackupView', {
keyup: function(field) {
me.store.clearFilter(true);
searchFilter.value = field.getValue();
-   me.store.filter([
-   vmtypeFilter,
-   searchFilter
-   ]);
+   updateFilter();
}
}
});
 
+   var vmidfilterCB = Ext.create('Ext.form.field.Checkbox', {
+   fieldLabel: gettext('Filter ID'),
+   labelAlign: 'right',
+   value: '1',
+   listeners: {
+   change: function(cb, value) {
+   vmidFilter.value = !!value ? vmid : '';
+   updateFilter();
+   },
+   },
+   });
+
var sm = Ext.create('Ext.selection.RowModel', {});
 
var backup_btn = Ext.create('Ext.button.Button', {
@@ -196,7 +217,10 @@ Ext.define('PVE.grid.BackupView', {
 
Ext.apply(me, {
selModel: sm,
-   tbar: [ backup_btn, restore_btn, delete_btn,config_btn, '->', 
storagesel, storagefilter ],
+   tbar: {
+   overflowHandler: 'scroller',
+   items: [ backup_btn, restore_btn, delete_btn,config_btn, '->', 
storagesel, vmidfilterCB, storagefilter ],
+   },
columns: [
{
header: gettext('Name'),
@@ -220,7 +244,12 @@ Ext.define('PVE.grid.BackupView', {
width: 100,
renderer: Proxmox.Utils.format_size,
dataIndex: 'size'
-   }
+   },
+   {
+   header: gettext('VMID'),
+   dataIndex: 'vmid',
+   hidden: true,
+   },
]
});
 
-- 
2.20.1


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


[pve-devel] [PATCH manager 1/2] ui: fix missing change from 'pve-' to 'pmx-' models

2020-05-29 Thread Dominik Csapak
we forgot to change these

Signed-off-by: Dominik Csapak 
---
 www/manager6/dc/AuthView.js | 2 +-
 www/manager6/dc/RoleView.js | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/www/manager6/dc/AuthView.js b/www/manager6/dc/AuthView.js
index 3e5a8517..bb5ec851 100644
--- a/www/manager6/dc/AuthView.js
+++ b/www/manager6/dc/AuthView.js
@@ -41,7 +41,7 @@ Ext.define('PVE.dc.AuthView', {
 ],
 
 store: {
-   model: 'pve-domains',
+   model: 'pmx-domains',
sorters: {
property: 'realm',
order: 'DESC',
diff --git a/www/manager6/dc/RoleView.js b/www/manager6/dc/RoleView.js
index e21e2920..3a25da80 100644
--- a/www/manager6/dc/RoleView.js
+++ b/www/manager6/dc/RoleView.js
@@ -12,7 +12,7 @@ Ext.define('PVE.dc.RoleView', {
var me = this;
 
var store = new Ext.data.Store({
-   model: 'pve-roles',
+   model: 'pmx-roles',
sorters: {
property: 'roleid',
order: 'DESC'
-- 
2.20.1


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


[pve-devel] [PATCH manager 2/2] ui: fix HotplugFeatureSelector

2020-05-29 Thread Dominik Csapak
we recently changed the setValue behaviour of the inputpanel and editwindow
(we now set all fields with the same names), which leads to wrong
behaviour here

use a different name for the internal checkboxes to avoid this

Signed-off-by: Dominik Csapak 
---
 www/manager6/form/HotplugFeatureSelector.js | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/www/manager6/form/HotplugFeatureSelector.js 
b/www/manager6/form/HotplugFeatureSelector.js
index 3bf394bc..a79fb845 100644
--- a/www/manager6/form/HotplugFeatureSelector.js
+++ b/www/manager6/form/HotplugFeatureSelector.js
@@ -6,7 +6,7 @@ Ext.define('PVE.form.HotplugFeatureSelector', {
 vertical: true,
 
 defaults: {
-   name: 'hotplug',
+   name: 'hotplugCbGroup',
submitValue: false
 },
 items: [
@@ -43,7 +43,7 @@ Ext.define('PVE.form.HotplugFeatureSelector', {
} else if (value !== '0') {
newVal = value.split(',');
}
-   me.callParent([{ hotplug: newVal }]);
+   me.callParent([{ hotplugCbGroup: newVal }]);
 },
 
 // override framework function to
-- 
2.20.1


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


[pve-devel] [PATCH widget-toolkit/manager] some refactorings

2020-05-28 Thread Dominik Csapak
just moving things to widget-toolkit
manager patches need the toolkit ones,
but they are not breaking manager

proxmox-widget-toolkit:

Dominik Csapak (2):
  Utils: add duration format/render
  css: add icon colors

 Utils.js | 27 +++
 css/ext6-pmx.css | 25 +
 2 files changed, 52 insertions(+)

pve-manager:

Dominik Csapak (2):
  ui: Replication: use render_duration from widget-toolkit
  css: remove icon colors

 www/css/ext6-pve.css | 25 -
 www/manager6/Utils.js| 27 ---
 www/manager6/grid/Replication.js |  2 +-
 3 files changed, 1 insertion(+), 53 deletions(-)

-- 
2.20.1


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


[pve-devel] [PATCH manager 1/2] ui: Replication: use render_duration from widget-toolkit

2020-05-28 Thread Dominik Csapak
Signed-off-by: Dominik Csapak 
---
 www/manager6/Utils.js| 27 ---
 www/manager6/grid/Replication.js |  2 +-
 2 files changed, 1 insertion(+), 28 deletions(-)

diff --git a/www/manager6/Utils.js b/www/manager6/Utils.js
index 676f56a8..5c81d7f8 100644
--- a/www/manager6/Utils.js
+++ b/www/manager6/Utils.js
@@ -536,26 +536,6 @@ Ext.define('PVE.Utils', { utilities: {
return msg;
 },
 
-format_duration_short: function(ut) {
-
-   if (ut < 60) {
-   return ut.toFixed(1) + 's';
-   }
-
-   if (ut < 3600) {
-   var mins = ut / 60;
-   return mins.toFixed(1) + 'm';
-   }
-
-   if (ut < 86400) {
-   var hours = ut / 3600;
-   return hours.toFixed(1) + 'h';
-   }
-
-   var days = ut / 86400;
-   return days.toFixed(1) + 'd';
-},
-
 contentTypes: {
'images': gettext('Disk image'),
'backup': gettext('VZDump backup file'),
@@ -836,13 +816,6 @@ Ext.define('PVE.Utils', { utilities: {
return Ext.Date.format(new Date(value * 1000), 'l d F Y H:i:s');
 },
 
-render_duration: function(value) {
-   if (value === undefined) {
-   return '-';
-   }
-   return PVE.Utils.format_duration_short(value);
-},
-
 calculate_mem_usage: function(data) {
if (!Ext.isNumeric(data.mem) ||
data.maxmem === 0 ||
diff --git a/www/manager6/grid/Replication.js b/www/manager6/grid/Replication.js
index 40f15982..eabf5524 100644
--- a/www/manager6/grid/Replication.js
+++ b/www/manager6/grid/Replication.js
@@ -382,7 +382,7 @@ Ext.define('PVE.grid.ReplicaView', {
text: gettext('Duration'),
dataIndex: 'duration',
width: 60,
-   renderer: PVE.Utils.render_duration
+   renderer: Proxmox.Utils.render_duration
},
{
text: gettext('Next Sync'),
-- 
2.20.1


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


[pve-devel] [PATCH widget-toolkit 1/2] Utils: add duration format/render

2020-05-28 Thread Dominik Csapak
from pve-manager

Signed-off-by: Dominik Csapak 
---
 Utils.js | 27 +++
 1 file changed, 27 insertions(+)

diff --git a/Utils.js b/Utils.js
index 56b1c9a..328164d 100644
--- a/Utils.js
+++ b/Utils.js
@@ -145,6 +145,26 @@ Ext.define('Proxmox.Utils', { utilities: {
return Ext.Date.format(date, "Y-m-d");
 },
 
+format_duration_short: function(ut) {
+
+   if (ut < 60) {
+   return ut.toFixed(1) + 's';
+   }
+
+   if (ut < 3600) {
+   var mins = ut / 60;
+   return mins.toFixed(1) + 'm';
+   }
+
+   if (ut < 86400) {
+   var hours = ut / 3600;
+   return hours.toFixed(1) + 'h';
+   }
+
+   var days = ut / 86400;
+   return days.toFixed(1) + 'd';
+},
+
 format_duration_long: function(ut) {
 
var days = Math.floor(ut / 86400);
@@ -643,6 +663,13 @@ Ext.define('Proxmox.Utils', { utilities: {
return task;
 },
 
+render_duration: function(value) {
+   if (value === undefined) {
+   return '-';
+   }
+   return Proxmox.Utils.format_duration_short(value);
+},
+
 render_timestamp: function(value, metaData, record, rowIndex, colIndex, 
store) {
var servertime = new Date(value * 1000);
return Ext.Date.format(servertime, 'Y-m-d H:i:s');
-- 
2.20.1


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


[pve-devel] [PATCH manager 2/2] css: remove icon colors

2020-05-28 Thread Dominik Csapak
they are now in the widget-toolkit

Signed-off-by: Dominik Csapak 
---
 www/css/ext6-pve.css | 25 -
 1 file changed, 25 deletions(-)

diff --git a/www/css/ext6-pve.css b/www/css/ext6-pve.css
index 4294f659..8f0407df 100644
--- a/www/css/ext6-pve.css
+++ b/www/css/ext6-pve.css
@@ -532,31 +532,6 @@ div.right-aligned {
 color: #000;
 }
 
-/* some icons have to be color manually */
-.black {
-color: #000;
-}
-
-.normal {
-color: #c2ddf2;
-}
-
-.faded {
-color: #cfcfcf;
-}
-
-.good {
-color: #21BF4B;
-}
-
-.warning {
-color: #fc0;
-}
-
-.critical {
-color: #FF6C59;
-}
-
 /* for the ceph monitor widgets */
 div.monitor {
text-align:left;
-- 
2.20.1


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


[pve-devel] [PATCH widget-toolkit 2/2] css: add icon colors

2020-05-28 Thread Dominik Csapak
from pve-manager

Signed-off-by: Dominik Csapak 
---
 css/ext6-pmx.css | 25 +
 1 file changed, 25 insertions(+)

diff --git a/css/ext6-pmx.css b/css/ext6-pmx.css
index 9b15392..37ee6aa 100644
--- a/css/ext6-pmx.css
+++ b/css/ext6-pmx.css
@@ -13,3 +13,28 @@
 .proxmox-invalid-row {
 background-color: #f3d6d7;
 }
+
+/* some icons have to be color manually */
+.black {
+color: #000;
+}
+
+.normal {
+color: #c2ddf2;
+}
+
+.faded {
+color: #cfcfcf;
+}
+
+.good {
+color: #21BF4B;
+}
+
+.warning {
+color: #fc0;
+}
+
+.critical {
+color: #FF6C59;
+}
-- 
2.20.1


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


Re: [pve-devel] [RFC manager 2/2] hardware view: Add disk import button

2020-05-27 Thread Dominik Csapak

sry for the delay of the review

a few comments inline

On 5/22/20 12:08 PM, Dominic Jäger wrote:

Is it a bad idea to move column2 as I did here? Seems strange to have column1
and 2 so different but I haven't found an easier way to make it available to
the subclass yet.

@Thomas Is this sort of what you had in mind for this feature?


i do not know what you're talked about, but seeing this
i would rather put the 'importing' code directly
into the hdedit panel, and make the 'mode' configurable

since most of the logic is in the window anyway.
that would avoid the whole issue of the accessing
columns of the superclass etc.



Signed-off-by: Dominic Jäger 
---
  www/manager6/Makefile|   1 +
  www/manager6/form/DiskStorageSelector.js |   5 +
  www/manager6/qemu/HDEdit.js  |  50 +
  www/manager6/qemu/HDImport.js| 128 +++
  www/manager6/qemu/HardwareView.js|  13 +++
  5 files changed, 176 insertions(+), 21 deletions(-)
  create mode 100644 www/manager6/qemu/HDImport.js

diff --git a/www/manager6/Makefile b/www/manager6/Makefile
index a29e280d..c1645748 100644
--- a/www/manager6/Makefile
+++ b/www/manager6/Makefile
@@ -143,6 +143,7 @@ JSSRC=  
\
qemu/Smbios1Edit.js \
qemu/CDEdit.js  \
qemu/HDEdit.js  \
+   qemu/HDImport.js\
qemu/HDResize.js\
qemu/HDMove.js  \
qemu/HDEfi.js   \
diff --git a/www/manager6/form/DiskStorageSelector.js 
b/www/manager6/form/DiskStorageSelector.js
index 445e3ac0..2c1555e1 100644
--- a/www/manager6/form/DiskStorageSelector.js
+++ b/www/manager6/form/DiskStorageSelector.js
@@ -32,6 +32,11 @@ Ext.define('PVE.form.DiskStorageSelector', {
  // string because else we get a type confusion
  defaultSize: '32',
  
+setDiskSize: function(newSize) {

+   let field = this.getComponent('disksize');
+   field.setValue(newSize);
+},
+
  changeStorage: function(f, value) {
var me = this;
var formatsel = me.getComponent('diskformat');
diff --git a/www/manager6/qemu/HDEdit.js b/www/manager6/qemu/HDEdit.js
index fd890600..5d6c12e9 100644
--- a/www/manager6/qemu/HDEdit.js
+++ b/www/manager6/qemu/HDEdit.js
@@ -13,6 +13,28 @@ Ext.define('PVE.qemu.HDInputPanel', {
  
  viewModel: {},
  
+diskStorageSelector: {

+   xtype: 'pveDiskStorageSelector',
+   storageContent: 'images',
+   name: 'disk',
+   reference: 'storageSelector',
+},
+
+column2: [
+   {
+   xtype: 'CacheTypeSelector',
+   name: 'cache',
+   value: '__default__',
+   fieldLabel: gettext('Cache')
+   },
+   {
+   xtype: 'proxmoxcheckbox',
+   fieldLabel: gettext('Discard'),
+   reference: 'discard',
+   name: 'discard'
+   },
+],
+
  controller: {
  
  	xclass: 'Ext.app.ViewController',

@@ -164,7 +186,6 @@ Ext.define('PVE.qemu.HDInputPanel', {
me.drive = {};
  
  	me.column1 = [];

-   me.column2 = [];
  
  	me.advancedColumn1 = [];

me.advancedColumn2 = [];
@@ -188,6 +209,8 @@ Ext.define('PVE.qemu.HDInputPanel', {
me.column1.push(me.scsiController);
}
  
+	me.diskStorageSelector.nodename = me.nodename;

+   me.diskStorageSelector.autoSelect = me.insideWizard;
if (me.unused) {
me.unusedDisks = Ext.create('Proxmox.form.KVComboBox', {
name: 'unusedId',
@@ -201,13 +224,7 @@ Ext.define('PVE.qemu.HDInputPanel', {
});
me.column1.push(me.unusedDisks);
} else if (me.isCreate) {
-   me.column1.push({
-   xtype: 'pveDiskStorageSelector',
-   storageContent: 'images',
-   name: 'disk',
-   nodename: me.nodename,
-   autoSelect: me.insideWizard
-   });
+   me.column1.push(me.diskStorageSelector);
} else {
me.column1.push({
xtype: 'textfield',
@@ -219,18 +236,6 @@ Ext.define('PVE.qemu.HDInputPanel', {
}
  
  	me.column2.push(

-   {
-   xtype: 'CacheTypeSelector',
-   name: 'cache',
-   value: '__default__',
-   fieldLabel: gettext('Cache')
-   },
-   {
-   xtype: 'proxmoxcheckbox',
-   fieldLabel: gettext('Discard'),
-   reference: 'discard',
-   name: 'discard'
-   }
);
  
  	me.advancedColumn1.push(

@@ -358,7 +363,9 @@ Ext.define('PVE.qemu.HDEdit', {
  
  backgroundDelay: 5,
  
-initComponent : function() {

+isImport: false,
+
+initComponent: 

[pve-devel] [PATCH widget-toolkit] improve error extraction for monStoreErrors

2020-05-26 Thread Dominik Csapak
by printing the whole error body when it cannot be parsed as JSON

Signed-off-by: Dominik Csapak 
---
 Utils.js | 15 ++-
 1 file changed, 10 insertions(+), 5 deletions(-)

diff --git a/Utils.js b/Utils.js
index 33c9b77..56b1c9a 100644
--- a/Utils.js
+++ b/Utils.js
@@ -244,17 +244,22 @@ Ext.define('Proxmox.Utils', { utilities: {
if (!err.statusText) {
return gettext('Connection error');
}
-   let msg = `${err.statusText} (${err.status})`;
+   let msg = [`${err.statusText} (${err.status})`];
if (err.response && err.response.responseText) {
let txt = err.response.responseText;
try {
let res = JSON.parse(txt)
-   for (let [key, value] of Object.entries(res.errors)) {
-   msg += `${key}: ${value}`;
+   if (res.errors && typeof res.errors === 'object') {
+   for (let [key, value] of Object.entries(res.errors)) {
+   msg.push(Ext.String.htmlEncode(`${key}: ${value}`));
+   }
}
-   } catch (e) { /* TODO? */ }
+   } catch (e) {
+   // fallback to string
+   msg.push(Ext.String.htmlEncode(txt));
+   }
}
-   return msg;
+   return msg.join('');
 },
 
 monStoreErrors: function(me, store, clearMaskBeforeLoad) {
-- 
2.20.1


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


[pve-devel] [PATCH widget-toolkit] return cookie again in authOK

2020-05-25 Thread Dominik Csapak
the calling code did require that authOK returns the cookie if
there is a valid one

make it now very explicit that the cookie gets returned instead
of using implicit short-circuit behaviour

Signed-off-by: Dominik Csapak 
---
 Utils.js | 6 +-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/Utils.js b/Utils.js
index cae25b2..402349a 100644
--- a/Utils.js
+++ b/Utils.js
@@ -208,7 +208,11 @@ Ext.define('Proxmox.Utils', { utilities: {
return undefined;
}
let cookie = Ext.util.Cookies.get(Proxmox.Setup.auth_cookie_name);
-   return (Proxmox.UserName !== '') && (cookie && 
!cookie.startsWith("PVE:tfa!"));
+   if (Proxmox.UserName !== '' && cookie && 
!cookie.startsWith("PVE:tfa!")) {
+   return cookie;
+   } else {
+   return false;
+   }
 },
 
 authClear: function() {
-- 
2.20.1


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


[pve-devel] [PATCH widget-toolkit] fix #2758: reject 'tfa' cookies

2020-05-25 Thread Dominik Csapak
return false on authOK when the ticket is a tfa ticket
(starts with PVE:tfa!)

when a user now loads the page with only a tfa ticket, it shows the
login window again

Signed-off-by: Dominik Csapak 
---
 Utils.js | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/Utils.js b/Utils.js
index 22eddd2..cae25b2 100644
--- a/Utils.js
+++ b/Utils.js
@@ -207,7 +207,8 @@ Ext.define('Proxmox.Utils', { utilities: {
if (Proxmox.LoggedOut) {
return undefined;
}
-   return (Proxmox.UserName !== '') && 
Ext.util.Cookies.get(Proxmox.Setup.auth_cookie_name);
+   let cookie = Ext.util.Cookies.get(Proxmox.Setup.auth_cookie_name);
+   return (Proxmox.UserName !== '') && (cookie && 
!cookie.startsWith("PVE:tfa!"));
 },
 
 authClear: function() {
-- 
2.20.1


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


[pve-devel] [PATCH widget-toolkit 1/1] add pmxRoleSelector

2020-05-19 Thread Dominik Csapak
copied+refactored from pve-manager
for use with other projects

also show privs now in the combobox

Signed-off-by: Dominik Csapak 
---
 Makefile |  1 +
 form/RoleSelector.js | 41 +
 2 files changed, 42 insertions(+)
 create mode 100644 form/RoleSelector.js

diff --git a/Makefile b/Makefile
index a23ad04..13f88d6 100644
--- a/Makefile
+++ b/Makefile
@@ -30,6 +30,7 @@ JSSRC=\
form/BondModeSelector.js\
form/NetworkSelector.js \
form/RealmComboBox.js   \
+   form/RoleSelector.js\
button/Button.js\
button/HelpButton.js\
grid/ObjectGrid.js  \
diff --git a/form/RoleSelector.js b/form/RoleSelector.js
new file mode 100644
index 000..142cdfd
--- /dev/null
+++ b/form/RoleSelector.js
@@ -0,0 +1,41 @@
+Ext.define('pmx-roles', {
+extend: 'Ext.data.Model',
+fields: ['roleid', 'privs'],
+proxy: {
+   type: 'proxmox',
+   url: "/api2/json/access/roles",
+},
+idProperty: 'roleid',
+});
+
+Ext.define('Proxmox.form.RoleSelector', {
+extend: 'Proxmox.form.ComboGrid',
+alias: 'widget.pmxRoleSelector',
+
+allowBlank: false,
+autoSelect: false,
+valueField: 'roleid',
+displayField: 'roleid',
+
+listConfig: {
+   columns: [
+   {
+   header: gettext('Role'),
+   sortable: true,
+   dataIndex: 'roleid',
+   flex: 1,
+   },
+   {
+   header: gettext('Privileges'),
+   dataIndex: 'privs',
+   flex: 1,
+   },
+   ],
+},
+
+store: {
+   autoLoad: true,
+   model: 'pmx-roles',
+   sorters: 'roleid',
+},
+});
-- 
2.20.1


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


[pve-devel] [PATCH manager 2/2] use RealmCombobox from widget-toolkit

2020-05-19 Thread Dominik Csapak
Signed-off-by: Dominik Csapak 
---
 www/manager6/dc/UserEdit.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/www/manager6/dc/UserEdit.js b/www/manager6/dc/UserEdit.js
index 692eb277..584fe19f 100644
--- a/www/manager6/dc/UserEdit.js
+++ b/www/manager6/dc/UserEdit.js
@@ -119,7 +119,7 @@ Ext.define('PVE.dc.UserEdit', {
 
 if (me.isCreate) {
 column1.splice(1,0,{
-xtype: 'pveRealmComboBox',
+xtype: 'pmxRealmComboBox',
 name: 'realm',
 fieldLabel: gettext('Realm'),
 allowBlank: false,
-- 
2.20.1


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


[pve-devel] [PATCH manager 1/2] ui: use RoleSelector from widget-toolkit

2020-05-19 Thread Dominik Csapak
Signed-off-by: Dominik Csapak 
---
 www/manager6/Makefile |  1 -
 www/manager6/dc/ACLView.js|  2 +-
 www/manager6/form/RoleSelector.js | 50 ---
 3 files changed, 1 insertion(+), 52 deletions(-)
 delete mode 100644 www/manager6/form/RoleSelector.js

diff --git a/www/manager6/Makefile b/www/manager6/Makefile
index a29e280d..5656ba27 100644
--- a/www/manager6/Makefile
+++ b/www/manager6/Makefile
@@ -26,7 +26,6 @@ JSSRC=
\
form/PrivilegesSelector.js  \
form/GroupSelector.js   \
form/UserSelector.js\
-   form/RoleSelector.js\
form/GuestIDSelector.js \
form/MemoryField.js \
form/NetworkCardSelector.js \
diff --git a/www/manager6/dc/ACLView.js b/www/manager6/dc/ACLView.js
index 24fd67d9..e9928b0f 100644
--- a/www/manager6/dc/ACLView.js
+++ b/www/manager6/dc/ACLView.js
@@ -46,7 +46,7 @@ Ext.define('PVE.dc.ACLAdd', {
}
 
items.push({
-   xtype: 'pveRoleSelector',
+   xtype: 'pmxRoleSelector',
name: 'roles',
value: 'NoAccess',
fieldLabel: gettext('Role')
diff --git a/www/manager6/form/RoleSelector.js 
b/www/manager6/form/RoleSelector.js
deleted file mode 100644
index 04b5b538..
--- a/www/manager6/form/RoleSelector.js
+++ /dev/null
@@ -1,50 +0,0 @@
-Ext.define('PVE.form.RoleSelector', {
-extend: 'Proxmox.form.ComboGrid',
-alias: ['widget.pveRoleSelector'],
-
-allowBlank: false,
-autoSelect: false,
-valueField: 'roleid',
-displayField: 'roleid',
-initComponent: function() {
-   var me = this;
-
-   var store = new Ext.data.Store({
-   model: 'pve-roles',
-   sorters: [{
-   property: 'roleid'
-   }]
-   });
-
-   Ext.apply(me, {
-   store: store,
-listConfig: {
-   columns: [
-   {
-   header: gettext('Role'),
-   sortable: true,
-   dataIndex: 'roleid',
-   flex: 1
-   }
-   ]
-   }
-   });
-
-me.callParent();
-
-   store.load();
-}
-
-}, function() {
-
-Ext.define('pve-roles', {
-   extend: 'Ext.data.Model',
-   fields: [ 'roleid', 'privs' ],
-   proxy: {
-type: 'proxmox',
-   url: "/api2/json/access/roles"
-   },
-   idProperty: 'roleid'
-});
-
-});
-- 
2.20.1


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


[pve-devel] [PATCH widget-toolkit/manager] move RoleSelector to widget-toolkit

2020-05-19 Thread Dominik Csapak
for use in other projects
also fixes a missing rename of the RealmCombobox in dc/UserEdit
(manager 2/2)

proxmox-widget-toolkit:

Dominik Csapak (1):
  add pmxRoleSelector

 Makefile |  1 +
 form/RoleSelector.js | 41 +
 2 files changed, 42 insertions(+)
 create mode 100644 form/RoleSelector.js

pve-manager:

Dominik Csapak (2):
  ui: use RoleSelector from widget-toolkit
  use RealmCombobox from widget-toolkit

 www/manager6/Makefile |  1 -
 www/manager6/dc/ACLView.js|  2 +-
 www/manager6/dc/UserEdit.js   |  2 +-
 www/manager6/form/RoleSelector.js | 50 ---
 4 files changed, 2 insertions(+), 53 deletions(-)
 delete mode 100644 www/manager6/form/RoleSelector.js

-- 
2.20.1


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


[pve-devel] [PATCH manager 2/2] ui: remove Realm model and RealmComboBox

2020-05-15 Thread Dominik Csapak
and use it from widget-toolkit

Signed-off-by: Dominik Csapak 
---
 www/manager6/Makefile  |  2 -
 www/manager6/data/model/Realm.js   | 30 --
 www/manager6/form/RealmComboBox.js | 65 --
 www/manager6/window/LoginWindow.js |  2 +-
 4 files changed, 1 insertion(+), 98 deletions(-)
 delete mode 100644 www/manager6/data/model/Realm.js
 delete mode 100644 www/manager6/form/RealmComboBox.js

diff --git a/www/manager6/Makefile b/www/manager6/Makefile
index 08861cca..a29e280d 100644
--- a/www/manager6/Makefile
+++ b/www/manager6/Makefile
@@ -17,7 +17,6 @@ JSSRC=
\
VNCConsole.js   \
data/PermPathStore.js   \
data/ResourceStore.js   \
-   data/model/Realm.js \
data/model/RRDModels.js \
form/VLanField.js   \
form/Boolean.js \
@@ -36,7 +35,6 @@ JSSRC=
\
form/BusTypeSelector.js \
form/ControllerSelector.js  \
form/EmailNotificationSelector.js   \
-   form/RealmComboBox.js   \
form/ViewSelector.js\
form/NodeSelector.js\
form/FileSelector.js\
diff --git a/www/manager6/data/model/Realm.js b/www/manager6/data/model/Realm.js
deleted file mode 100644
index 01f36351..
--- a/www/manager6/data/model/Realm.js
+++ /dev/null
@@ -1,30 +0,0 @@
-Ext.define('pve-domains', {
-extend: "Ext.data.Model",
-fields: [
-   'realm', 'type', 'comment', 'default', 'tfa',
-   {
-   name: 'descr',
-   // Note: We use this in the RealmComboBox.js (see Bug #125)
-   convert: function(value, record) {
-   if (value) {
-   return value;
-   }
-
-   var info = record.data;
-   // return realm if there is no comment
-   var text = info.comment || info.realm;
-
-   if (info.tfa) {
-   text += " (+ " + info.tfa + ")";
-   }
-
-   return Ext.String.htmlEncode(text);
-   }
-   }
-],
-idProperty: 'realm',
-proxy: {
-   type: 'proxmox',
-   url: "/api2/json/access/domains"
-}
-});
diff --git a/www/manager6/form/RealmComboBox.js 
b/www/manager6/form/RealmComboBox.js
deleted file mode 100644
index c85fe7d2..
--- a/www/manager6/form/RealmComboBox.js
+++ /dev/null
@@ -1,65 +0,0 @@
-/*global Proxmox*/
-Ext.define('PVE.form.RealmComboBox', {
-extend: 'Ext.form.field.ComboBox',
-alias: ['widget.pveRealmComboBox'],
-
-controller: {
-   xclass: 'Ext.app.ViewController',
-
-   init: function(view) {
-   view.store.on('load', this.onLoad, view);
-   },
-
-   onLoad: function(store, records, success) {
-   if (!success) {
-   return;
-   }
-   var me = this;
-   var val = me.getValue();
-   if (!val || !me.store.findRecord('realm', val)) {
-   var def = 'pam';
-   Ext.each(records, function(rec) {
-   if (rec.data && rec.data['default']) {
-   def = rec.data.realm;
-   }
-   });
-   me.setValue(def);
-   }
-   }
-},
-
-fieldLabel: gettext('Realm'),
-name: 'realm',
-queryMode: 'local',
-allowBlank: false,
-editable: false,
-forceSelection: true,
-autoSelect: false,
-triggerAction: 'all',
-valueField: 'realm',
-displayField: 'descr',
-getState: function() {
-   return { value: this.getValue() };
-},
-applyState : function(state) {
-   if (state && state.value) {
-   this.setValue(state.value);
-   }
-},
-stateEvents: [ 'select' ],
-stateful: true, // last chosen auth realm is saved between page reloads
-id: 'pveloginrealm', // We need stable ids when using stateful, not 
autogenerated
-stateID: 'pveloginrealm',
-
-needOTP: function(realm) {
-   var me = this;
-   // use exact match
-   var rec = me.store.findRecord('realm', realm, 0, false, false, true);
-   return rec && rec.data && rec.data.tfa ? rec.data.tfa : undefined;
-},
-
-store: {
-   model: 'pve-domains',
-   autoLoad: true
-}
-});
diff --git a/www/manager6/window/LoginWindow.js 
b/www/manager6/window/LoginWindow.js
index e29b7352..6123c655 100644
--- a/www/manager6/window/LoginWindow.js
+++ b/www/manager6/window/LoginWindow.js
@@ -227,7 +227,7 @@ Ext.defi

[pve-devel] [PATCH widget-toolkit 2/3] add PMX.image.Logo

2020-05-15 Thread Dominik Csapak
copied from pmg-gui, adapted to be able to set a custom url prefix
when we want to use something other than '/pve2'

Signed-off-by: Dominik Csapak 
---
 Logo.js  | 21 +
 Makefile |  1 +
 2 files changed, 22 insertions(+)
 create mode 100644 Logo.js

diff --git a/Logo.js b/Logo.js
new file mode 100644
index 000..78d9aad
--- /dev/null
+++ b/Logo.js
@@ -0,0 +1,21 @@
+Ext.define('PMX.image.Logo', {
+extend: 'Ext.Img',
+xtype: 'proxmoxlogo',
+
+height: 30,
+width: 172,
+src: '/images/proxmox_logo.png',
+alt: 'Proxmox',
+autoEl: {
+   tag: 'a',
+   href: 'https://www.proxmox.com',
+   target: '_blank',
+},
+
+initComponent: function() {
+   let me = this;
+   let prefix = me.prefix !== undefined ? me.prefix : '/pve2';
+   me.src = prefix + me.src;
+   me.callParent();
+},
+});
diff --git a/Makefile b/Makefile
index 2907419..85fad6b 100644
--- a/Makefile
+++ b/Makefile
@@ -7,6 +7,7 @@ SUBDIRS= css images
 JSSRC= \
Utils.js\
Toolkit.js  \
+   Logo.js \
mixin/CBind.js  \
data/reader/JsonObject.js   \
data/ProxmoxProxy.js\
-- 
2.20.1


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


[pve-devel] [PATCH manager 1/2] ui: use PMX.image.Logo from widget-toolkit

2020-05-15 Thread Dominik Csapak
Signed-off-by: Dominik Csapak 
---
 www/manager6/Workspace.js | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/www/manager6/Workspace.js b/www/manager6/Workspace.js
index 57cb1bb9..8d224f5b 100644
--- a/www/manager6/Workspace.js
+++ b/www/manager6/Workspace.js
@@ -307,8 +307,7 @@ Ext.define('PVE.StdWorkspace', {
margin: '2 0 2 5',
items: [
{
-   html: 'https://www.proxmox.com;>' +
-   ''
+   xtype: 'proxmoxlogo',
},
{
minWidth: 150,
-- 
2.20.1


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


[pve-devel] [PATCH widget-toolkit 1/3] window/Edit: read digest also from top level response

2020-05-15 Thread Dominik Csapak
we want to have the digest in the top level object, like:
{
data: { /* the real data */ },
digest: "fa123asf123123123", // the digest
}

instead of in the data itself, so read it preferably from there
(with fallback to stay compatible)

Signed-off-by: Dominik Csapak 
---
 window/Edit.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/window/Edit.js b/window/Edit.js
index d21c165..6e6c0d4 100644
--- a/window/Edit.js
+++ b/window/Edit.js
@@ -192,7 +192,7 @@ Ext.define('Proxmox.window.Edit', {
method: 'GET',
success: function(response, opts) {
form.clearInvalid();
-   me.digest = response.result.data.digest;
+   me.digest = response.result.digest || 
response.result.data.digest;
if (successFn) {
successFn(response, opts);
} else {
-- 
2.20.1


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


[pve-devel] [PATCH pmg-gui 1/1] remove Logo.js

2020-05-15 Thread Dominik Csapak
it is now in the widget-toolkit

Signed-off-by: Dominik Csapak 
---
 js/Logo.js  | 14 --
 js/Makefile |  1 -
 2 files changed, 15 deletions(-)
 delete mode 100644 js/Logo.js

diff --git a/js/Logo.js b/js/Logo.js
deleted file mode 100644
index 96ec14b..000
--- a/js/Logo.js
+++ /dev/null
@@ -1,14 +0,0 @@
-Ext.define('PMG.image.Logo', {
-extend: 'Ext.Img',
-xtype: 'proxmoxlogo',
-
-height: 30,
-width: 172,
-src: '/pve2/images/proxmox_logo.png',
-alt: 'Proxmox',
-autoEl: {
-   tag: 'a',
-   href: 'https://www.proxmox.com',
-   target: '_blank'
-}
-});
diff --git a/js/Makefile b/js/Makefile
index 672eedf..d35f3bc 100644
--- a/js/Makefile
+++ b/js/Makefile
@@ -18,7 +18,6 @@ JSSRC=
\
ActionList.js   \
RuleInfo.js \
RuleEditor.js   \
-   Logo.js \
MainView.js \
QuarantineList.js   \
SpamInfoGrid.js \
-- 
2.20.1


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


[pve-devel] [PATCH widget-toolkit 3/3] add Realm model and RealmComboBox

2020-05-15 Thread Dominik Csapak
copied from pve-manager, with adaptions for modern js
(let, parameter destructuring,...)

and dropped the not needed 'needOTP' method

Signed-off-by: Dominik Csapak 
---
 Makefile  |  2 ++
 data/model/Realm.js   | 29 ++
 form/RealmComboBox.js | 57 +++
 3 files changed, 88 insertions(+)
 create mode 100644 data/model/Realm.js
 create mode 100644 form/RealmComboBox.js

diff --git a/Makefile b/Makefile
index 85fad6b..a23ad04 100644
--- a/Makefile
+++ b/Makefile
@@ -16,6 +16,7 @@ JSSRC=\
data/ObjectStore.js \
data/RRDStore.js\
data/TimezoneStore.js   \
+   data/model/Realm.js \
form/DisplayEdit.js \
form/ExpireDate.js  \
form/IntegerField.js\
@@ -28,6 +29,7 @@ JSSRC=\
form/RRDTypeSelector.js \
form/BondModeSelector.js\
form/NetworkSelector.js \
+   form/RealmComboBox.js   \
button/Button.js\
button/HelpButton.js\
grid/ObjectGrid.js  \
diff --git a/data/model/Realm.js b/data/model/Realm.js
new file mode 100644
index 000..dce270d
--- /dev/null
+++ b/data/model/Realm.js
@@ -0,0 +1,29 @@
+Ext.define('pmx-domains', {
+extend: "Ext.data.Model",
+fields: [
+   'realm', 'type', 'comment', 'default',
+   {
+   name: 'tfa',
+   allowNull: true,
+   },
+   {
+   name: 'descr',
+   convert: function(value, { data={} }) {
+   if (value) return Ext.String.htmlEncode(value);
+
+   let text = data.comment || data.realm;
+
+   if (data.tfa) {
+   text += ` (+ ${data.tfa})`;
+   }
+
+   return Ext.String.htmlEncode(text);
+   },
+   },
+],
+idProperty: 'realm',
+proxy: {
+   type: 'proxmox',
+   url: "/api2/json/access/domains",
+},
+});
diff --git a/form/RealmComboBox.js b/form/RealmComboBox.js
new file mode 100644
index 000..e391fbf
--- /dev/null
+++ b/form/RealmComboBox.js
@@ -0,0 +1,57 @@
+Ext.define('Proxmox.form.RealmComboBox', {
+extend: 'Ext.form.field.ComboBox',
+alias: 'widget.pmxRealmComboBox',
+
+controller: {
+   xclass: 'Ext.app.ViewController',
+
+   init: function(view) {
+   view.store.on('load', this.onLoad, view);
+   },
+
+   onLoad: function(store, records, success) {
+   if (!success) {
+   return;
+   }
+   var me = this;
+   var val = me.getValue();
+   if (!val || !me.store.findRecord('realm', val)) {
+   var def = 'pam';
+   Ext.each(records, function(rec) {
+   if (rec.data && rec.data.default) {
+   def = rec.data.realm;
+   }
+   });
+   me.setValue(def);
+   }
+   },
+},
+
+fieldLabel: gettext('Realm'),
+name: 'realm',
+queryMode: 'local',
+allowBlank: false,
+editable: false,
+forceSelection: true,
+autoSelect: false,
+triggerAction: 'all',
+valueField: 'realm',
+displayField: 'descr',
+getState: function() {
+   return { value: this.getValue() };
+},
+applyState: function(state) {
+   if (state && state.value) {
+   this.setValue(state.value);
+   }
+},
+stateEvents: ['select'],
+stateful: true, // last chosen auth realm is saved between page reloads
+id: 'pveloginrealm', // We need stable ids when using stateful, not 
autogenerated
+stateID: 'pveloginrealm',
+
+store: {
+   model: 'pmx-domains',
+   autoLoad: true,
+},
+});
-- 
2.20.1


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


[pve-devel] [RFC PATCH manager] ui: ACMEAccountCreate: improve layout of account dialog

2020-05-14 Thread Dominik Csapak
by increasing the space for the link, and using a boxLabel instead
of fieldLabel, which has better spacing for longer text

also move the e-mail before the directory to have all textboxes together

Signed-off-by: Dominik Csapak 
---
not really sure if it looks good now, but the current layout
is rather ugly, so sending it as rfc
 www/manager6/node/ACME.js | 19 +--
 1 file changed, 9 insertions(+), 10 deletions(-)

diff --git a/www/manager6/node/ACME.js b/www/manager6/node/ACME.js
index fd3b..6a2730cb 100644
--- a/www/manager6/node/ACME.js
+++ b/www/manager6/node/ACME.js
@@ -2,7 +2,7 @@ Ext.define('PVE.node.ACMEAccountCreate', {
 extend: 'Proxmox.window.Edit',
 mixins: ['Proxmox.Mixin.CBind'],
 
-width: 400,
+width: 450,
 title: gettext('Register Account'),
 isCreate: true,
 method: 'POST',
@@ -21,6 +21,13 @@ Ext.define('PVE.node.ACMEAccountCreate', {
allowBlank: (get) => !get('defaultExists'),
},
},
+   {
+   xtype: 'textfield',
+   name: 'contact',
+   vtype: 'email',
+   allowBlank: false,
+   fieldLabel: gettext('E-Mail')
+   },
{
xtype: 'proxmoxComboGrid',
name: 'directory',
@@ -90,7 +97,6 @@ Ext.define('PVE.node.ACMEAccountCreate', {
{
xtype: 'displayfield',
itemId: 'tos_url_display',
-   fieldLabel: gettext('Terms of Service'),
renderer: PVE.Utils.render_optional_url,
name: 'tos_url_display'
},
@@ -102,7 +108,7 @@ Ext.define('PVE.node.ACMEAccountCreate', {
{
xtype: 'proxmoxcheckbox',
itemId: 'tos_checkbox',
-   fieldLabel: gettext('Accept TOS'),
+   boxLabel: gettext('Accept TOS'),
submitValue: false,
validateValue: function(value) {
if (value && this.checked) {
@@ -111,13 +117,6 @@ Ext.define('PVE.node.ACMEAccountCreate', {
return false;
}
},
-   {
-   xtype: 'textfield',
-   name: 'contact',
-   vtype: 'email',
-   allowBlank: false,
-   fieldLabel: gettext('E-Mail')
-   }
 ]
 
 });
-- 
2.20.1


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


[pve-devel] [PATCH stable-5 manager 3/3] pve5to6: add check for ovmf vms with potentially broken efi disk

2020-05-12 Thread Dominik Csapak
we wrongly mapped some efidisks into the vm, and fixed it in pve6
this potentially needs manual intervention, so warn the user about
which vms might be affected

Signed-off-by: Dominik Csapak 
---
 PVE/CLI/pve5to6.pm | 35 +++
 1 file changed, 35 insertions(+)

diff --git a/PVE/CLI/pve5to6.pm b/PVE/CLI/pve5to6.pm
index 01a3a819..8ccca076 100644
--- a/PVE/CLI/pve5to6.pm
+++ b/PVE/CLI/pve5to6.pm
@@ -18,6 +18,7 @@ use PVE::RPCEnvironment;
 use PVE::Storage;
 use PVE::Tools qw(run_command $IPV4RE $IPV6RE);
 use PVE::QemuServer;
+use PVE::QemuConfig;
 
 use AptPkg::Cache;
 use Socket qw(AF_INET AF_INET6 inet_ntop);
@@ -335,6 +336,38 @@ sub check_kvm_nested {
 }
 }
 
+sub check_vms_with_uefi {
+log_info("Checking VMs with OVMF enabled, which may need manual 
intervention...");
+
+my $vmlist = PVE::QemuServer::vzlist();
+
+my $vms = [];
+
+foreach my $vmid ( sort { $a <=> $b } keys %$vmlist ) {
+   my $conf = PVE::QemuConfig->load_config($vmid);
+   if ($conf->{bios} && $conf->{bios} eq 'ovmf' && $conf->{efidisk0}) {
+   my $disk = PVE::QemuServer::parse_drive('efidisk0', 
$conf->{efidisk0});
+   if (!defined($disk->{size}) || $disk->{size} > 128*1024) {
+   # all efidisks bigger than the default 128k and those
+   # without size in the config
+   push @$vms, $vmid;
+   } elsif ($disk->{file} !~ /\.(raw|qcow2|vmdk)$/) {
+   # all efidisks not on file storage
+   push @$vms, $vmid;
+   }
+   }
+}
+
+if (scalar(@$vms) > 0) {
+   my $warnmsg = "VMs with OVMF configured and potentially broken EFI 
disks: \n";
+   $warnmsg .= " " . join(',', @$vms);
+   $warnmsg .= "\nThere may be manual intervention required. See Known 
upgrade issues for details\n";
+   log_warn($warnmsg);
+} else {
+   log_pass("No VMs with OVMF and potentially broken EFI disk found.");
+}
+}
+
 sub check_storage_health {
 print_header("CHECKING CONFIGURED STORAGES");
 my $cfg = PVE::Storage::config();
@@ -741,6 +774,8 @@ sub check_misc {
 }
 
 check_kvm_nested();
+
+check_vms_with_uefi();
 }
 
 __PACKAGE__->register_method ({
-- 
2.20.1


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


[pve-devel] [PATCH stable-5 manager 2/3] pve5to6: add check for stock debian kernel package

2020-05-12 Thread Dominik Csapak
on current debian buster, stock kernel images recommend
firmware-linux-free which conflict with our pve-firmware package
which leads to apt wanting to remove promxox-ve

check for the meta package in the update check script

Signed-off-by: Dominik Csapak 
---
 PVE/CLI/pve5to6.pm | 14 ++
 1 file changed, 14 insertions(+)

diff --git a/PVE/CLI/pve5to6.pm b/PVE/CLI/pve5to6.pm
index 42c41bbd..01a3a819 100644
--- a/PVE/CLI/pve5to6.pm
+++ b/PVE/CLI/pve5to6.pm
@@ -19,6 +19,7 @@ use PVE::Storage;
 use PVE::Tools qw(run_command $IPV4RE $IPV6RE);
 use PVE::QemuServer;
 
+use AptPkg::Cache;
 use Socket qw(AF_INET AF_INET6 inet_ntop);
 use Term::ANSIColor;
 
@@ -249,6 +250,19 @@ sub check_pve_packages {
} else {
log_warn("unexpected running and installed kernel '$kernel_ver'.");
}
+
+}
+print "\nChecking for installed Debian Kernel..\n";
+if(my $apt_cache = AptPkg::Cache->new()) {
+   my $p = $apt_cache->{'linux-image-amd64'};
+   if ($p && $p->{SelectedState} eq 'Install') {
+   log_fail("Stock Debian kernel package installed. Please remove 
package 'linux-image-amd64'.");
+   } else {
+   log_pass("Stock Debian kernel package not installed.");
+   }
+
+} else {
+   log_fail("unable to initialize AptPkg::Cache\n");
 }
 }
 
-- 
2.20.1


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


[pve-devel] [PATCH stable-5 manager 1/3] ui: fix missing htmlEncodes

2020-05-12 Thread Dominik Csapak
username can include some special characters, so we have
to escape them

backport from pve6

Signed-off-by: Dominik Csapak 
---
 www/manager6/Workspace.js | 2 +-
 www/manager6/dc/ACLView.js| 2 +-
 www/manager6/dc/Log.js| 2 ++
 www/manager6/dc/TFAEdit.js| 1 +
 www/manager6/dc/Tasks.js  | 1 +
 www/manager6/dc/UserEdit.js   | 1 +
 www/manager6/dc/UserView.js   | 4 ++--
 www/manager6/form/UserSelector.js | 1 +
 www/manager6/window/Settings.js   | 2 +-
 9 files changed, 11 insertions(+), 5 deletions(-)

diff --git a/www/manager6/Workspace.js b/www/manager6/Workspace.js
index ca67b7d9..ae41915e 100644
--- a/www/manager6/Workspace.js
+++ b/www/manager6/Workspace.js
@@ -170,7 +170,7 @@ Ext.define('PVE.StdWorkspace', {
var ui = me.query('#userinfo')[0];
 
if (Proxmox.UserName) {
-   var msg =  Ext.String.format(gettext("You are logged in as {0}"), 
"'" + Proxmox.UserName + "'");
+   var msg =  Ext.String.format(gettext("You are logged in as {0}"), 
"'" + Ext.String.htmlEncode(Proxmox.UserName) + "'");
ui.update('' + msg + '');
} else {
ui.update('');
diff --git a/www/manager6/dc/ACLView.js b/www/manager6/dc/ACLView.js
index 1322f952..07d8f136 100644
--- a/www/manager6/dc/ACLView.js
+++ b/www/manager6/dc/ACLView.js
@@ -111,7 +111,7 @@ Ext.define('PVE.dc.ACLView', {
return '@' + ugid;
}
 
-   return ugid;
+   return Ext.String.htmlEncode(ugid);
};
 
var columns = [
diff --git a/www/manager6/dc/Log.js b/www/manager6/dc/Log.js
index 0106af99..2b6e06ad 100644
--- a/www/manager6/dc/Log.js
+++ b/www/manager6/dc/Log.js
@@ -68,6 +68,7 @@ Ext.define('PVE.dc.Log', {
{ 
header: gettext("User name"), 
dataIndex: 'user',
+   renderer: Ext.String.htmlEncode,
width: 150
},
{ 
@@ -79,6 +80,7 @@ Ext.define('PVE.dc.Log', {
{ 
header: gettext("Message"), 
dataIndex: 'msg',
+   renderer: Ext.String.htmlEncode,
flex: 1   
}
],
diff --git a/www/manager6/dc/TFAEdit.js b/www/manager6/dc/TFAEdit.js
index ed2ff30d..b39bed13 100644
--- a/www/manager6/dc/TFAEdit.js
+++ b/www/manager6/dc/TFAEdit.js
@@ -368,6 +368,7 @@ Ext.define('PVE.window.TFAEdit', {
{
xtype: 'displayfield',
fieldLabel: gettext('User name'),
+   renderer: Ext.String.htmlEncode,
cbind: {
value: '{userid}'
}
diff --git a/www/manager6/dc/Tasks.js b/www/manager6/dc/Tasks.js
index 62e5ac71..5220bcb2 100644
--- a/www/manager6/dc/Tasks.js
+++ b/www/manager6/dc/Tasks.js
@@ -101,6 +101,7 @@ Ext.define('PVE.dc.Tasks', {
{
header: gettext("User name"),
dataIndex: 'user',
+   renderer: Ext.String.htmlEncode,
width: 150
},
{
diff --git a/www/manager6/dc/UserEdit.js b/www/manager6/dc/UserEdit.js
index 1665f4b0..26382d60 100644
--- a/www/manager6/dc/UserEdit.js
+++ b/www/manager6/dc/UserEdit.js
@@ -72,6 +72,7 @@ Ext.define('PVE.dc.UserEdit', {
 name: 'userid',
 fieldLabel: gettext('User name'),
 value: me.userid,
+   renderer: Ext.String.htmlEncode,
 allowBlank: false,
 submitValue: me.isCreate ? true : false
 },
diff --git a/www/manager6/dc/UserView.js b/www/manager6/dc/UserView.js
index 8918fb2b..57dda809 100644
--- a/www/manager6/dc/UserView.js
+++ b/www/manager6/dc/UserView.js
@@ -110,11 +110,11 @@ Ext.define('PVE.dc.UserView', {
 ];
 
var render_username = function(userid) {
-   return userid.match(/^(.+)(@[^@]+)$/)[1];
+   return Ext.String.htmlEncode(userid.match(/^(.+)(@[^@]+)$/)[1]);
};
 
var render_realm = function(userid) {
-   return userid.match(/@([^@]+)$/)[1];
+   return Ext.String.htmlEncode(userid.match(/@([^@]+)$/)[1]);
};
 
Ext.apply(me, {
diff --git a/www/manager6/form/UserSelector.js 
b/www/manager6/form/UserSelector.js
index cd01bc3e..8f6f9fa4 100644
--- a/www/manager6/form/UserSelector.js
+++ b/www/manager6/form/UserSelector.js
@@ -29,6 +29,7 @@ Ext.define('PVE.form.UserSelector', {
header: gettext('User'),
sortable: true,
dataIndex: 'userid',
+   renderer: Ext.String.htmlEncode,
flex: 1
  

[pve-devel] [PATCH manager] ui: dc/ACME: fix not refreshing api column

2020-05-11 Thread Dominik Csapak
When using a diffstore, we have to specify all fields that are
displayed, otherwise the store does not know which fields to check for
change

for the acme plugin view, 'api' was missing

Signed-off-by: Dominik Csapak 
---
 www/manager6/dc/ACMEClusterView.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/www/manager6/dc/ACMEClusterView.js 
b/www/manager6/dc/ACMEClusterView.js
index 9c6ca377..cb45a2ba 100644
--- a/www/manager6/dc/ACMEClusterView.js
+++ b/www/manager6/dc/ACMEClusterView.js
@@ -10,7 +10,7 @@ Ext.define('pve-acme-accounts', {
 
 Ext.define('pve-acme-plugins', {
 extend: 'Ext.data.Model',
-fields: ['type', 'plugin'],
+fields: ['type', 'plugin', 'api'],
 proxy: {
type: 'proxmox',
url: "/api2/json/cluster/acme/plugins",
-- 
2.20.1


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


[pve-devel] [PATCH docs] pveum.adoc: use correct cli command for realm sync

2020-05-08 Thread Dominik Csapak
Signed-off-by: Dominik Csapak 
---
 pveum.adoc | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/pveum.adoc b/pveum.adoc
index 8f229a6..0057564 100644
--- a/pveum.adoc
+++ b/pveum.adoc
@@ -178,7 +178,7 @@ It is possible to sync users and groups for LDAP based 
realms. You can use the
 CLI command
 
 
-  pveum sync 
+  pveum realm sync 
 
 or in the `Authentication` panel of the GUI. Users and groups are synced to the
 cluster-wide user configuration file `/etc/pve/user.cfg`.
-- 
2.20.1


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


[pve-devel] [PATCH access-control] LDAP: skip anonymous bind when clientcert/key is given

2020-05-08 Thread Dominik Csapak
It seems that servers associate the client-cert/key with an account, so
doing an explicit anonymous bind then 'logs out' the already verified
user, limiting the search results in some cases

before refactoring to PVE::LDAP, we did not do '$ldap->bind' at all when
there was no bind_dn, but it is not really clear if Net::LDAP does this
automatically when searching (other libraries do this), so leave the
anonymous bind (for compatibility with PMG) but skip it when a client
certificate and key is given.

Signed-off-by: Dominik Csapak 
---
 PVE/Auth/LDAP.pm | 14 +++---
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/PVE/Auth/LDAP.pm b/PVE/Auth/LDAP.pm
index 9fa9095..09b2202 100755
--- a/PVE/Auth/LDAP.pm
+++ b/PVE/Auth/LDAP.pm
@@ -203,17 +203,17 @@ sub connect_and_bind {
 
 my $ldap = PVE::LDAP::ldap_connect($servers, $scheme, $port, \%ldap_args);
 
-my $bind_dn;
-my $bind_pass;
-
 if ($config->{bind_dn}) {
-   $bind_dn = $config->{bind_dn};
-   $bind_pass = ldap_get_credentials($realm);
+   my $bind_dn = $config->{bind_dn};
+   my $bind_pass = ldap_get_credentials($realm);
die "missing password for realm $realm\n" if !defined($bind_pass);
+   PVE::LDAP::ldap_bind($ldap, $bind_dn, $bind_pass);
+} elsif ($config->{cert} && $config->{certkey}) {
+   warn "skipping anonymous bind with clientcert\n";
+} else {
+   PVE::LDAP::ldap_bind($ldap);
 }
 
-PVE::LDAP::ldap_bind($ldap, $bind_dn, $bind_pass);
-
 if (!$config->{base_dn}) {
my $root = $ldap->root_dse(attrs => [ 'defaultNamingContext' ]);
$config->{base_dn} = $root->get_value('defaultNamingContext');
-- 
2.20.1


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


[pve-devel] [PATCH manager] dc/Realms: fix adding of new ldap realm

2020-05-08 Thread Dominik Csapak
we cannot pass 'delete' on create api call, and we have to make
sure that 'default_opts' and 'sync_attributes' are alwyas available,
since they are used in onGetValues
(they were only created during setValues, which is not called
when adding a new realm)

Signed-off-by: Dominik Csapak 
---
 www/manager6/dc/AuthEditLDAP.js | 8 ++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/www/manager6/dc/AuthEditLDAP.js b/www/manager6/dc/AuthEditLDAP.js
index 0ca6f6ac..c5976769 100644
--- a/www/manager6/dc/AuthEditLDAP.js
+++ b/www/manager6/dc/AuthEditLDAP.js
@@ -66,6 +66,8 @@ Ext.define('PVE.panel.LDAPSyncInputPanel', {
 
 editableAttributes: ['email'],
 editableDefaults: ['scope', 'full', 'enable-new', 'purge'],
+default_opts: {},
+sync_attributes: {},
 
 // (de)construct the sync-attributes from the list above,
 // not touching all others
@@ -93,12 +95,15 @@ Ext.define('PVE.panel.LDAPSyncInputPanel', {
PVE.Utils.delete_if_default(values, 'sync-defaults-options');
PVE.Utils.delete_if_default(values, 'sync_attributes');
 
+   if (me.isCreate) {
+   delete values.delete; // on create we cannot delete values
+   }
+
return values;
 },
 
 setValues: function(values) {
let me = this;
-   me.sync_attributes = {};
if (values.sync_attributes) {
me.sync_attributes = 
PVE.Parser.parsePropertyString(values.sync_attributes);
delete values.sync_attributes;
@@ -108,7 +113,6 @@ Ext.define('PVE.panel.LDAPSyncInputPanel', {
}
});
}
-   me.default_opts = {};
if (values['sync-defaults-options']) {
me.default_opts = 
PVE.Parser.parsePropertyString(values['sync-defaults-options']);
delete values.default_opts;
-- 
2.20.1


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


[pve-devel] [PATCH manager 1/3] ui: ACMEAccountCreate: make name only optional if no default exists

2020-05-07 Thread Dominik Csapak
if the 'default' account exists, make the name field required and
remove the emptytext

get the information by querying the grid store. this may be not
up-to-date, but it is less intrusive that an extra api call that
blocks the window

Signed-off-by: Dominik Csapak 
---
 www/manager6/dc/ACMEClusterView.js | 3 +++
 www/manager6/node/ACME.js  | 8 ++--
 2 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/www/manager6/dc/ACMEClusterView.js 
b/www/manager6/dc/ACMEClusterView.js
index 00db8e9f..aaf2fc19 100644
--- a/www/manager6/dc/ACMEClusterView.js
+++ b/www/manager6/dc/ACMEClusterView.js
@@ -29,7 +29,10 @@ Ext.define('PVE.dc.ACMEAccountView', {
 
addAccount: function() {
let me = this;
+   let view = me.getView();
+   let defaultExists = view.getStore().findExact('name', 'default') 
!== -1;
Ext.create('PVE.node.ACMEAccountCreate', {
+   defaultExists,
taskDone: function() {
me.reload();
},
diff --git a/www/manager6/node/ACME.js b/www/manager6/node/ACME.js
index 0418f406..fd3b 100644
--- a/www/manager6/node/ACME.js
+++ b/www/manager6/node/ACME.js
@@ -1,5 +1,6 @@
 Ext.define('PVE.node.ACMEAccountCreate', {
 extend: 'Proxmox.window.Edit',
+mixins: ['Proxmox.Mixin.CBind'],
 
 width: 400,
 title: gettext('Register Account'),
@@ -8,14 +9,17 @@ Ext.define('PVE.node.ACMEAccountCreate', {
 submitText: gettext('Register'),
 url: '/cluster/acme/account',
 showTaskViewer: true,
+defaultExists: false,
 
 items: [
{
xtype: 'proxmoxtextfield',
fieldLabel: gettext('Name'),
name: 'name',
-   emptyText: 'default',
-   allowBlank: true,
+   cbind: {
+   emptyText: (get) => get('defaultExists') ? '' : 'default',
+   allowBlank: (get) => !get('defaultExists'),
+   },
},
{
xtype: 'proxmoxComboGrid',
-- 
2.20.1


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


[pve-devel] [PATCH manager 2/3] ui: dc/ACMEClusterView: load the correct store on reload

2020-05-07 Thread Dominik Csapak
if we use a diff/update store combo, we have to load the updatestore
not the diff store, else we get spurious empty grids

Signed-off-by: Dominik Csapak 
---
 www/manager6/dc/ACMEClusterView.js | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/www/manager6/dc/ACMEClusterView.js 
b/www/manager6/dc/ACMEClusterView.js
index aaf2fc19..e73de7b7 100644
--- a/www/manager6/dc/ACMEClusterView.js
+++ b/www/manager6/dc/ACMEClusterView.js
@@ -52,7 +52,7 @@ Ext.define('PVE.dc.ACMEAccountView', {
reload: function() {
let me = this;
let view = me.getView();
-   view.getStore().load();
+   view.getStore().rstore.load();
},
 },
 
@@ -142,7 +142,7 @@ Ext.define('PVE.dc.ACMEPluginView', {
reload: function() {
let me = this;
let view = me.getView();
-   view.getStore().load();
+   view.getStore().rstore.load();
},
 },
 
-- 
2.20.1


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


[pve-devel] [PATCH manager 3/3] ui: dc/ACMEClusterView: show TaskProgress on account removal

2020-05-07 Thread Dominik Csapak
this is not a synchronous api call, so open a taskprogress window
and reload after the task is done

Signed-off-by: Dominik Csapak 
---
 www/manager6/dc/ACMEClusterView.js | 15 ++-
 1 file changed, 14 insertions(+), 1 deletion(-)

diff --git a/www/manager6/dc/ACMEClusterView.js 
b/www/manager6/dc/ACMEClusterView.js
index e73de7b7..74868cb7 100644
--- a/www/manager6/dc/ACMEClusterView.js
+++ b/www/manager6/dc/ACMEClusterView.js
@@ -54,6 +54,19 @@ Ext.define('PVE.dc.ACMEAccountView', {
let view = me.getView();
view.getStore().rstore.load();
},
+
+   showTaskAndReload: function(options, success, response) {
+   let me = this;
+   if (!success) return;
+
+   let upid = response.result.data;
+   Ext.create('Proxmox.window.TaskProgress', {
+   upid,
+   taskDone: function() {
+   me.reload();
+   },
+   }).show();
+   },
 },
 
 minHeight: 150,
@@ -84,7 +97,7 @@ Ext.define('PVE.dc.ACMEAccountView', {
{
xtype: 'proxmoxStdRemoveButton',
baseurl: '/cluster/acme/account',
-   callback: 'reload',
+   callback: 'showTaskAndReload',
},
 ],
 
-- 
2.20.1


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


Re: [pve-devel] [PATCH manager 3/7] ui: dc/ACMEClusterView: use a diff/update store combo for the grids

2020-05-07 Thread Dominik Csapak




On 5/7/20 1:08 PM, Thomas Lamprecht wrote:

On 5/7/20 10:27 AM, Dominik Csapak wrote:

so that they are get automatically reloaded with the default interval (3seconds)

Signed-off-by: Dominik Csapak 
---
this patch needs the widget-toolkit patches applied
we can of course leave those out, and to it manually in initComponent,
but this is a pattern we often use and maybe we can remove more manually
crated rstore/diffstore combos in other places


hmm, I now get a short glitch off "No accounts configured" shown when adding
a second or removing a second account.


yes i see that, but its only tangentially related to this patch.
we load the wrong store on 'reload' (the diff instead of the 
updatestore; which does not work)

can send a v2 of this or a follow-up, up to you

also noticed that on account removal we need to show a 
taskprogress/viewer since it is not synchronous




Semi-related, if an account with "default" already exists it would be great
if the emptyText gets dropped and the field gets required, as a second account
with "default" cannot be added anyway, but rather minor nit..


ok sounds reasonable





  www/manager6/dc/ACMEClusterView.js | 24 +++-
  1 file changed, 19 insertions(+), 5 deletions(-)

diff --git a/www/manager6/dc/ACMEClusterView.js 
b/www/manager6/dc/ACMEClusterView.js
index 228d1cf9..00db8e9f 100644
--- a/www/manager6/dc/ACMEClusterView.js
+++ b/www/manager6/dc/ACMEClusterView.js
@@ -90,8 +90,15 @@ Ext.define('PVE.dc.ACMEAccountView', {
  },
  
  store: {

-   model: 'pve-acme-accounts',
-   autoLoad: true,
+   type: 'diff',
+   autoDestroy: true,
+   autoDestroyRstore: true,
+   rstore: {
+   type: 'update',
+   storeid: 'pve-acme-accounts',
+   model: 'pve-acme-accounts',
+   autoStart: true,
+   },
sorters: 'name',
  },
  });
@@ -179,9 +186,16 @@ Ext.define('PVE.dc.ACMEPluginView', {
  },
  
  store: {

-   model: 'pve-acme-plugins',
-   autoLoad: true,
-   filters: item => !!item.data.api,
+   type: 'diff',
+   autoDestroy: true,
+   autoDestroyRstore: true,
+   rstore: {
+   type: 'update',
+   storeid: 'pve-acme-plugins',
+   model: 'pve-acme-plugins',
+   autoStart: true,
+   filters: item => !!item.data.api,
+   },
sorters: 'plugin',
  },
  });





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


[pve-devel] [PATCH manager 2/7] ui: ACME: add emptyText and add minHeight

2020-05-07 Thread Dominik Csapak
without the minHeight, the panel does resize weirdly on the first load

Signed-off-by: Dominik Csapak 
---
 www/manager6/dc/ACMEClusterView.js | 6 ++
 www/manager6/node/ACME.js  | 2 ++
 2 files changed, 8 insertions(+)

diff --git a/www/manager6/dc/ACMEClusterView.js 
b/www/manager6/dc/ACMEClusterView.js
index f3cae866..228d1cf9 100644
--- a/www/manager6/dc/ACMEClusterView.js
+++ b/www/manager6/dc/ACMEClusterView.js
@@ -53,6 +53,9 @@ Ext.define('PVE.dc.ACMEAccountView', {
},
 },
 
+minHeight: 150,
+emptyText: gettext('No Accounts configured'),
+
 columns: [
{
dataIndex: 'name',
@@ -133,6 +136,9 @@ Ext.define('PVE.dc.ACMEPluginView', {
},
 },
 
+minHeight: 150,
+emptyText: gettext('No Plugins configured'),
+
 columns: [
{
dataIndex: 'plugin',
diff --git a/www/manager6/node/ACME.js b/www/manager6/node/ACME.js
index 0b38f9c7..a2ac35f5 100644
--- a/www/manager6/node/ACME.js
+++ b/www/manager6/node/ACME.js
@@ -346,6 +346,8 @@ Ext.define('PVE.node.ACME', {
 margin: '10 0 0 0',
 title: 'ACME',
 
+emptyText: gettext('No Domains configured'),
+
 viewModel: {
data: {
account: undefined,
-- 
2.20.1


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


[pve-devel] [PATCH manager 1/7] NodeConfig/get_acme_conf: make domains always a hash

2020-05-07 Thread Dominik Csapak
on all call sites, we assume $cfg->{domains} is a hash, but if we do not
have any domains configured, that fails with
'Can't use an undefined value as a HASH reference at ...'

so always make domains a hash to avoid this

Signed-off-by: Dominik Csapak 
---
 PVE/NodeConfig.pm | 1 +
 1 file changed, 1 insertion(+)

diff --git a/PVE/NodeConfig.pm b/PVE/NodeConfig.pm
index 2de9015e..af726b15 100644
--- a/PVE/NodeConfig.pm
+++ b/PVE/NodeConfig.pm
@@ -251,6 +251,7 @@ sub get_acme_conf {
die $err;
}
my $standalone_domains = delete($res->{domains}) // '';
+   $res->{domains} = {};
for my $domain (split(";", $standalone_domains)) {
$res->{domains}->{$domain}->{plugin} = 'standalone';
$res->{domains}->{$domain}->{_configkey} = 'acme';
-- 
2.20.1


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


[pve-devel] [PATCH manager 4/7] ui: node/ACME: fix some eslint errors/warnings

2020-05-07 Thread Dominik Csapak
* unneeded brackets for arrow function
* unused variables
* me not defined
* trailing commas

Signed-off-by: Dominik Csapak 
---
 www/manager6/node/ACME.js | 19 ---
 1 file changed, 8 insertions(+), 11 deletions(-)

diff --git a/www/manager6/node/ACME.js b/www/manager6/node/ACME.js
index a2ac35f5..ba1906b4 100644
--- a/www/manager6/node/ACME.js
+++ b/www/manager6/node/ACME.js
@@ -356,9 +356,7 @@ Ext.define('PVE.node.ACME', {
},
 
formulas: {
-   editBtnIcon: (get) => {
-   return 'fa black fa-' + (get('accountEditable') ? 'check' : 
'pencil');
-   },
+   editBtnIcon: (get) => 'fa black fa-' + (get('accountEditable') ? 
'check' : 'pencil'),
accountTextHidden: (get) => get('accountEditable') || 
!get('accountsAvailable'),
accountValueHidden: (get) => !get('accountEditable') || 
!get('accountsAvailable'),
},
@@ -368,18 +366,18 @@ Ext.define('PVE.node.ACME', {
xclass: 'Ext.app.ViewController',
 
init: function(view) {
-   let vm = this.getViewModel();
let accountSelector = this.lookup('accountselector');
accountSelector.store.on('load', this.onAccountsLoad, this);
},
 
onAccountsLoad: function(store, records, success) {
-   let vm = this.getViewModel();
+   let me = this;
+   let vm = me.getViewModel();
vm.set('accountsAvailable', records.length > 0);
-   if (this.autoChangeAccount && records.length > 0) {
-   this.changeAccount(records[0].data.name, () => {
+   if (me.autoChangeAccount && records.length > 0) {
+   me.changeAccount(records[0].data.name, () => {
vm.set('accountEditable', false);
-   this.reload();
+   me.reload();
});
me.autoChangeAccount = false;
}
@@ -616,7 +614,7 @@ Ext.define('PVE.node.ACME', {
hidden: '{accountsAvailable}',
},
handler: 'addAccount',
-   }
+   },
 ],
 
 updateStore: function(store, records, success) {
@@ -627,7 +625,7 @@ Ext.define('PVE.node.ACME', {
rec = records[0];
} else {
rec = {
-   data: {}
+   data: {},
};
}
 
@@ -652,7 +650,6 @@ Ext.define('PVE.node.ACME', {
}
}
 
-   let accounttext = me.lookup('accounttext');
let vm = me.getViewModel();
let oldaccount = vm.get('account');
 
-- 
2.20.1


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


[pve-devel] [PATCH widget-toolkit 1/2] data/DiffStore: add autoDestroyRstore flag

2020-05-07 Thread Dominik Csapak
when this flag is set, the diffstore will automatically try to destroy
the rstore when it is destroyed itself

for this we have to move the rstore into the object (instead of using a closure)

Signed-off-by: Dominik Csapak 
---
 data/DiffStore.js | 26 +-
 1 file changed, 21 insertions(+), 5 deletions(-)

diff --git a/data/DiffStore.js b/data/DiffStore.js
index d43f111..6f335f0 100644
--- a/data/DiffStore.js
+++ b/data/DiffStore.js
@@ -24,6 +24,20 @@ Ext.define('Proxmox.data.DiffStore', {
 
 sortAfterUpdate: false,
 
+// if set to true, destroy rstore on destruction
+autoDestroyRstore: false,
+
+onDestroy: function() {
+   let me = this;
+   if (me.autoDestroyRstore) {
+   if (Ext.isFunction(me.rstore.destroy)) {
+   me.rstore.destroy();
+   }
+   delete me.rstore;
+   }
+   me.callParent();
+},
+
 constructor: function(config) {
var me = this;
 
@@ -46,6 +60,8 @@ Ext.define('Proxmox.data.DiffStore', {
 
me.callParent([config]);
 
+   me.rstore = rstore;
+
var first_load = true;
 
var cond_add_item = function(data, id) {
@@ -80,13 +96,13 @@ Ext.define('Proxmox.data.DiffStore', {
 
// remove vanished items
allItems.each(function(olditem) {
-   var item = rstore.getById(olditem.getId());
+   var item = me.rstore.getById(olditem.getId());
if (!item) {
me.remove(olditem);
}
});
 
-   rstore.each(function(item) {
+   me.rstore.each(function(item) {
cond_add_item(item.data, item.getId());
});
 
@@ -103,12 +119,12 @@ Ext.define('Proxmox.data.DiffStore', {
me.fireEvent('datachanged', me);
};
 
-   if (rstore.isLoaded()) {
+   if (me.rstore.isLoaded()) {
// if store is already loaded,
// insert items instantly
-   loadFn(rstore, [], true);
+   loadFn(me.rstore, [], true);
}
 
-   me.mon(rstore, 'load', loadFn);
+   me.mon(me.rstore, 'load', loadFn);
 }
 });
-- 
2.20.1


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


[pve-devel] [PATCH manager 6/7] ui: node/ACME: only enable order button when it should work

2020-05-07 Thread Dominik Csapak
to order a ceritificate, we need at least one configured domain, and
the configured account (or default) must exist

so track the domaincount in the viewmodel and introduce a
'canOrder' formula which is only true when domaincount > 0 and
account is set (if the configured account does not exist, or no account
exists at all we set 'account' to 'null')

Signed-off-by: Dominik Csapak 
---
 www/manager6/node/ACME.js | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/www/manager6/node/ACME.js b/www/manager6/node/ACME.js
index 1e91be4e..d21d18e4 100644
--- a/www/manager6/node/ACME.js
+++ b/www/manager6/node/ACME.js
@@ -350,6 +350,7 @@ Ext.define('PVE.node.ACME', {
 
 viewModel: {
data: {
+   domaincount: 0,
account: undefined, // the account we display
configaccount: undefined, // the account set in the config
accountEditable: false,
@@ -357,6 +358,7 @@ Ext.define('PVE.node.ACME', {
},
 
formulas: {
+   canOrder: (get) => !!get('account') && get('domaincount') > 0,
editBtnIcon: (get) => 'fa black fa-' + (get('accountEditable') ? 
'check' : 'pencil'),
accountTextHidden: (get) => get('accountEditable') || 
!get('accountsAvailable'),
accountValueHidden: (get) => !get('accountEditable') || 
!get('accountsAvailable'),
@@ -566,7 +568,7 @@ Ext.define('PVE.node.ACME', {
reference: 'order',
text: gettext('Order Certificates Now'),
bind: {
-   disabled: '{!accountsAvailable}',
+   disabled: '{!canOrder}',
},
handler: 'order',
},
@@ -678,6 +680,7 @@ Ext.define('PVE.node.ACME', {
data.push(record);
}
 
+   vm.set('domaincount', data.length);
me.store.loadData(data, false);
 },
 
-- 
2.20.1


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


[pve-devel] [PATCH widget-toolkit 2/2] data/DiffStore: auto-create the rstore if its just a config

2020-05-07 Thread Dominik Csapak
when rstore is not instanciated but only a config,
auto-create it with its type

this allows us to configure an diff/rstore combination completely
declaratively like this:

store: {
type: 'diff',
autoDestroy: true,
autoDestroyRstore: true,
rstore: {
type: 'update',
model: 'some-model',
autoStart: true,
interval: 5000,
},
},

the only thing we have to be careful about is to either
do a manual 'stopUpdate' somewhere, or use the 'autoDestroyRstore' flag

Signed-off-by: Dominik Csapak 
---
we might want to set the 'autoDestroyRstore' automatically when
we define 'autoDestroy' and autocreated it? in that case
the chance that someone manually extracts an instance of the rstore
and uses it somewhere else is probably very low

 data/DiffStore.js | 9 -
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/data/DiffStore.js b/data/DiffStore.js
index 6f335f0..2fc08be 100644
--- a/data/DiffStore.js
+++ b/data/DiffStore.js
@@ -51,7 +51,14 @@ Ext.define('Proxmox.data.DiffStore', {
throw "no rstore model specified";
}
 
-   var rstore = config.rstore;
+   let rstore;
+   if (config.rstore.isInstance) {
+   rstore = config.rstore;
+   } else if (config.rstore.type) {
+   rstore = Ext.create(`store.${config.rstore.type}`, config.rstore);
+   } else {
+   throw 'rstore is not an instance, and cannot autocreate without 
"type"';
+   }
 
Ext.apply(config, {
model: rstore.model,
-- 
2.20.1


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


[pve-devel] [PATCH widget-toolkit/manager] fixups for ACME UI

2020-05-07 Thread Dominik Csapak
this series fixes some problems and improves the ACME UI, namely:
* auto update dc->Acme grids
* add emptyText
* adds missing stopUpdates
* improve order button enable logic
* reuse existing store for account verification
* add auto-create/destroy feature to the diffstore

path 3/7 from manager needs the widget-toolkit patches applied,
but all others do not need them

proxmox-widget-toolkit:

Dominik Csapak (2):
  data/DiffStore: add autoDestroyRstore flag
  data/DiffStore: auto-create the rstore if its just a config

 data/DiffStore.js | 35 +--
 1 file changed, 29 insertions(+), 6 deletions(-)

pve-manager:

Dominik Csapak (7):
  NodeConfig/get_acme_conf: make domains always a hash
  ui: ACME: add emptyText and add minHeight
  ui: dc/ACMEClusterView: use a diff/update store combo for the grids
  ui: node/ACME: fix some eslint errors/warnings
  ui: node/ACME: use accountselector for verification
  ui: node/ACME: only enable order button when it should work
  ui: node/{ACME,Certificates}: add stopUpdate on destruction

 PVE/NodeConfig.pm  |  1 +
 www/manager6/dc/ACMEClusterView.js | 30 +++---
 www/manager6/node/ACME.js  | 50 --
 www/manager6/node/Certificates.js  |  1 +
 4 files changed, 54 insertions(+), 28 deletions(-)

-- 
2.20.1


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


[pve-devel] [PATCH manager 5/7] ui: node/ACME: use accountselector for verification

2020-05-07 Thread Dominik Csapak
instead of using API2Request manually, just reload the store of
the accountselector and check if the configured account is in it

this should fix the spurious loading mask of the panel when
loading the accounts

Signed-off-by: Dominik Csapak 
---
 www/manager6/node/ACME.js | 23 ---
 1 file changed, 12 insertions(+), 11 deletions(-)

diff --git a/www/manager6/node/ACME.js b/www/manager6/node/ACME.js
index ba1906b4..1e91be4e 100644
--- a/www/manager6/node/ACME.js
+++ b/www/manager6/node/ACME.js
@@ -350,7 +350,8 @@ Ext.define('PVE.node.ACME', {
 
 viewModel: {
data: {
-   account: undefined,
+   account: undefined, // the account we display
+   configaccount: undefined, // the account set in the config
accountEditable: false,
accountsAvailable: false,
},
@@ -373,6 +374,7 @@ Ext.define('PVE.node.ACME', {
onAccountsLoad: function(store, records, success) {
let me = this;
let vm = me.getViewModel();
+   let configaccount = vm.get('configaccount');
vm.set('accountsAvailable', records.length > 0);
if (me.autoChangeAccount && records.length > 0) {
me.changeAccount(records[0].data.name, () => {
@@ -380,6 +382,12 @@ Ext.define('PVE.node.ACME', {
me.reload();
});
me.autoChangeAccount = false;
+   } else if (configaccount) {
+   if (store.findExact('name', configaccount) !== -1) {
+   vm.set('account', configaccount);
+   } else {
+   vm.set('account', null);
+   }
}
},
 
@@ -573,6 +581,7 @@ Ext.define('PVE.node.ACME', {
{
xtype: 'displayfield',
reference: 'accounttext',
+   renderer: (val) => val || Proxmox.Utils.NoneText,
bind: {
value: '{account}',
hidden: '{accountTextHidden}',
@@ -655,16 +664,8 @@ Ext.define('PVE.node.ACME', {
 
// account changed, and we do not edit currently, load again to verify
if (oldaccount !== account && !vm.get('accountEditable')) {
-   Proxmox.Utils.API2Request({
-   url: `/cluster/acme/account/${account}`,
-   waitMsgTarget: me,
-   success: function(response, opt) {
-   vm.set('account', account);
-   },
-   failure: function(response, opt) {
-   vm.set('account', Proxmox.Utils.NoneText);
-   },
-   });
+   vm.set('configaccount', account);
+   me.lookup('accountselector').store.load();
}
 
for (let i = 0; i < PVE.Utils.acmedomain_count; i++) {
-- 
2.20.1


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


[pve-devel] [PATCH manager 7/7] ui: node/{ACME, Certificates}: add stopUpdate on destruction

2020-05-07 Thread Dominik Csapak
else the stores never stop updating

Signed-off-by: Dominik Csapak 
---
 www/manager6/node/ACME.js | 1 +
 www/manager6/node/Certificates.js | 1 +
 2 files changed, 2 insertions(+)

diff --git a/www/manager6/node/ACME.js b/www/manager6/node/ACME.js
index d21d18e4..0418f406 100644
--- a/www/manager6/node/ACME.js
+++ b/www/manager6/node/ACME.js
@@ -731,5 +731,6 @@ Ext.define('PVE.node.ACME', {
me.callParent();
me.mon(me.rstore, 'load', 'updateStore', me);
Proxmox.Utils.monStoreErrors(me, me.rstore);
+   me.on('destroy', me.rstore.stopUpdate, me.rstore);
 },
 });
diff --git a/www/manager6/node/Certificates.js 
b/www/manager6/node/Certificates.js
index df2fd7de..0c5dfc68 100644
--- a/www/manager6/node/Certificates.js
+++ b/www/manager6/node/Certificates.js
@@ -399,5 +399,6 @@ Ext.define('PVE.node.Certificates', {
 
me.mon(me.rstore, 'load', me.set_button_status, me);
me.rstore.startUpdate();
+   me.on('destroy', me.rstore.stopUpdate, me.rstore);
 }
 });
-- 
2.20.1


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


[pve-devel] [PATCH manager 3/7] ui: dc/ACMEClusterView: use a diff/update store combo for the grids

2020-05-07 Thread Dominik Csapak
so that they are get automatically reloaded with the default interval (3seconds)

Signed-off-by: Dominik Csapak 
---
this patch needs the widget-toolkit patches applied
we can of course leave those out, and to it manually in initComponent,
but this is a pattern we often use and maybe we can remove more manually
crated rstore/diffstore combos in other places

 www/manager6/dc/ACMEClusterView.js | 24 +++-
 1 file changed, 19 insertions(+), 5 deletions(-)

diff --git a/www/manager6/dc/ACMEClusterView.js 
b/www/manager6/dc/ACMEClusterView.js
index 228d1cf9..00db8e9f 100644
--- a/www/manager6/dc/ACMEClusterView.js
+++ b/www/manager6/dc/ACMEClusterView.js
@@ -90,8 +90,15 @@ Ext.define('PVE.dc.ACMEAccountView', {
 },
 
 store: {
-   model: 'pve-acme-accounts',
-   autoLoad: true,
+   type: 'diff',
+   autoDestroy: true,
+   autoDestroyRstore: true,
+   rstore: {
+   type: 'update',
+   storeid: 'pve-acme-accounts',
+   model: 'pve-acme-accounts',
+   autoStart: true,
+   },
sorters: 'name',
 },
 });
@@ -179,9 +186,16 @@ Ext.define('PVE.dc.ACMEPluginView', {
 },
 
 store: {
-   model: 'pve-acme-plugins',
-   autoLoad: true,
-   filters: item => !!item.data.api,
+   type: 'diff',
+   autoDestroy: true,
+   autoDestroyRstore: true,
+   rstore: {
+   type: 'update',
+   storeid: 'pve-acme-plugins',
+   model: 'pve-acme-plugins',
+   autoStart: true,
+   filters: item => !!item.data.api,
+   },
sorters: 'plugin',
 },
 });
-- 
2.20.1


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


Re: [pve-devel] [PATCH manager v2 0/5] ACME node adaptions for plugins

2020-05-06 Thread Dominik Csapak




On 5/6/20 8:11 PM, Thomas Lamprecht wrote:

On 5/6/20 4:31 PM, Dominik Csapak wrote:

this series adapts the node->certificates->acme panel to include
an 'accountselector' and to be able to add/edit/remove single domains,
including ones with a plugin

changes from v1:
* drop fieldLabel in ACMEAccountSelector
* reword 'Account' in 'Used Account'
* use different approach to change the account
   (use viewModel and a displayfield/combobox/editbutton to better
   see when the account actually changes)

Dominik Csapak (5):
   ui: add ACME selector formfields for account and plugins
   ui: Parser: add printACME
   ui: Utils: add helper functions for acme domains
   ui: node/ACME: add ACMEDomainEdit
   ui: node/ACME: rework ACME grid for plugin based domains

  www/manager6/Makefile|   2 +
  www/manager6/Parser.js   |   7 +
  www/manager6/Utils.js|  23 +
  www/manager6/form/ACMEAccountSelector.js |  21 +
  www/manager6/form/ACMEPluginSelector.js  |  19 +
  www/manager6/node/ACME.js| 617 ---
  6 files changed, 517 insertions(+), 172 deletions(-)
  create mode 100644 www/manager6/form/ACMEAccountSelector.js
  create mode 100644 www/manager6/form/ACMEPluginSelector.js



applied series, but this wasn't much tested, or the wrong thing was sent..


hi, sorry yes should have tested more (was a bit in a hurry yesterday)


I had to fix the acme undefined access exceptions I mentioned to you for v1
off-list,


i actually tested this, but did not trigger it, but looking at the code
now, yes i can see where it has tripped up


the "show button to go to account page" didn't worked at all (no code
doing it included),


yes, sorry, after my initial tests with this, i did actually never
remove my acme accounts again


I fixed that but threw it out for something different
all together.. 


looks good AFAICS


renamed: form/ACMEAPiSelector.js -> form/ACMEAPISelector.js > (Which I also 
mentioned for v1..) and threw in a few smaller followups.


but this was in my other series (which you applied the day before),

anyway, i would've been happy to send a v3 (you can ofc fix up my 
patches, but no need to generate more work for yourself :) )




The store glitches still on load for the Certificates ACME view, I increased
the interval to 10 seconds as I really did not wanted to investigate that too.


i think what you mean with 'glitch' is the loading mask on account 
verification... after looking at the thing again, i am not so sure 
anymore that we actually need that (we already have a list off accounts

in the accountselector). i'll see if i can improve that bit



The DC -> ACME ones could profit from update/diffstore to get changes more
live, even if seldom made - they are really cheap to query.



yes makes sense, i found also some other issues (backend as well)
i'll send some patches later today

thanks for fixing my bugs :)


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


[pve-devel] [PATCH manager v2 2/5] ui: Parser: add printACME

2020-05-06 Thread Dominik Csapak
since we decode the domain list in parseACME into an array, we
have to join them again to a string when printing

otherwise printPropertyString attaches them just with ',' which
does not work here

Signed-off-by: Dominik Csapak 
---
 www/manager6/Parser.js | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/www/manager6/Parser.js b/www/manager6/Parser.js
index 4cecb3e1..20d81d4a 100644
--- a/www/manager6/Parser.js
+++ b/www/manager6/Parser.js
@@ -5,6 +5,13 @@ Ext.define('PVE.Parser', { statics: {
 
 // this class only contains static functions
 
+printACME: function(value) {
+   if (Ext.isArray(value.domains)) {
+   value.domains = value.domains.join(';');
+   }
+   return PVE.Parser.printPropertyString(value);
+},
+
 parseACME: function(value) {
if (!value) {
return;
-- 
2.20.1


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


[pve-devel] [PATCH manager v2 4/5] ui: node/ACME: add ACMEDomainEdit

2020-05-06 Thread Dominik Csapak
which expects a nodeconfig (for digest and domaincount)
and for the edit case, the parsed 'domain' object

this editwindow has three fields:
* type selector (standalone/dns)
* domain
* plugin (only for dns)

if the user chooses dns but there are already the maximum count of
acmedomainX entries, the type field gets invalid (with a error tooltip)

the onGetValues method is non-trivial, because of the mixing of
acmedomainX and acme.domain values, so we have to be careful
that we delete/edit the correct entry

Signed-off-by: Dominik Csapak 
---
 www/manager6/node/ACME.js | 136 ++
 1 file changed, 136 insertions(+)

diff --git a/www/manager6/node/ACME.js b/www/manager6/node/ACME.js
index 40ecc00e..a8bb39d6 100644
--- a/www/manager6/node/ACME.js
+++ b/www/manager6/node/ACME.js
@@ -230,6 +230,142 @@ Ext.define('PVE.node.ACMEAccountView', {
 }
 });
 
+Ext.define('PVE.node.ACMEDomainEdit', {
+extend: 'Proxmox.window.Edit',
+alias: 'widget.pveACMEDomainEdit',
+
+subject: gettext('Domain'),
+isCreate: false,
+
+items: [
+   {
+   xtype: 'inputpanel',
+   onGetValues: function(values) {
+   let me = this;
+   let win = me.up('pveACMEDomainEdit');
+   let nodeconfig = win.nodeconfig;
+   let olddomain = win.domain || {};
+
+   let params = {
+   digest: nodeconfig.digest,
+   };
+
+   let configkey = olddomain.configkey;
+   let acmeObj = PVE.Parser.parseACME(nodeconfig.acme) || {};
+
+   if (values.type === 'dns') {
+   if (!olddomain.configkey || olddomain.configkey === 'acme') 
{
+   // look for first free slot
+   for (let i = 0; i < PVE.Utils.acmedomain_count; i++) {
+   if (nodeconfig[`acmedomain${i}`] === undefined) {
+   configkey = `acmedomain${i}`;
+   break;
+   }
+   }
+   if (olddomain.domain) {
+   // we have to remove the domain from the acme 
domainlist
+   PVE.Utils.remove_domain_from_acme(acmeObj, 
olddomain.domain);
+   params.acme = PVE.Parser.printACME(acmeObj);
+   }
+   }
+
+   delete values.type;
+   params[configkey] = PVE.Parser.printPropertyString(values, 
'domain');
+   } else {
+   if (olddomain.configkey && olddomain.configkey !== 'acme') {
+   // delete the old dns entry
+   params.delete = [olddomain.configkey];
+   }
+
+   // add new, remove old and make entries unique
+   PVE.Utils.add_domain_to_acme(acmeObj, values.domain);
+   PVE.Utils.remove_domain_from_acme(acmeObj, 
olddomain.domain);
+   params.acme = PVE.Parser.printACME(acmeObj);
+   }
+
+   return params;
+   },
+   items: [
+   {
+   xtype: 'proxmoxKVComboBox',
+   name: 'type',
+   fieldLabel: gettext('Type'),
+   allowBlank: false,
+   comboItems: [
+   ['standalone', 'standalone'],
+   ['dns', 'DNS'],
+   ],
+   validator: function(value) {
+   let me = this;
+   let win = me.up('pveACMEDomainEdit');
+   let oldconfigkey = win.domain ? win.domain.configkey : 
undefined;
+   let val = me.getValue();
+   if (val === 'dns' && (!oldconfigkey || oldconfigkey === 
'acme')) {
+   // we have to check if there is a 'acmedomain' slot 
left
+   let found = false;
+   for (let i = 0; i < PVE.Utils.acmedomain_count; 
i++) {
+   if (!win.nodeconfig[`acmedomain${i}`]) {
+   found = true;
+   }
+   }
+   if (!found) {
+   return gettext('Only 5 Domains with type DNS 
can be configured');
+   }
+   }
+
+   return true;
+   },
+   listeners: {
+   change: function(cb, value) {
+   let me = this;
+   let view = me.up('pveACMEDomainEdit');
+   view.down('field[name=plugin]').setDisabled(value 
!== 'dns');
+   },
+   },
+   },
+   {
+   

[pve-devel] [PATCH manager v2 5/5] ui: node/ACME: rework ACME grid for plugin based domains

2020-05-06 Thread Dominik Csapak
This is basically a complete rework of the ACME grid.
Instead of having an ObjectGrid, we now have a normal
GridPanel which allows us to show a row for each Domain.

But to achieve this, we need to manually fill the store with data
from the 'acme' and 'acmedomainX' entries of the node config.

We also add an AccountSelector to the tbar and a link to the
datacenter->acme panel (when there is no account)

this also removes the 'register account' and 'view account' buttons,
since those are now available in datacenter->acme

Signed-off-by: Dominik Csapak 
---
changes from v1:
* different approach for editing accounts
  uses now a displayfield/combobox and button to switch between
  display and edit, and only do it when the 'check' is clicked

* use viewmodel binding for account name, makes the code a little more
  compact

 www/manager6/node/ACME.js | 481 --
 1 file changed, 309 insertions(+), 172 deletions(-)

diff --git a/www/manager6/node/ACME.js b/www/manager6/node/ACME.js
index a8bb39d6..33159b2e 100644
--- a/www/manager6/node/ACME.js
+++ b/www/manager6/node/ACME.js
@@ -1,49 +1,3 @@
-Ext.define('PVE.node.ACMEEditor', {
-extend: 'Proxmox.window.Edit',
-xtype: 'pveACMEEditor',
-
-subject: gettext('Domains'),
-items: [
-   {
-   xtype: 'inputpanel',
-   items: [
-   {
-   xtype: 'textarea',
-   fieldLabel: gettext('Domains'),
-   emptyText: "domain1.example.com\ndomain2.example.com",
-   name: 'domains'
-   }
-   ],
-   onGetValues: function(values) {
-   if (!values.domains) {
-   return {
-   'delete': 'acme'
-   };
-   }
-   var domains = values.domains.split(/\n/).join(';');
-   return {
-   'acme': 'domains=' + domains
-   };
-   }
-   }
-],
-
-initComponent: function() {
-   var me = this;
-   me.callParent();
-
-   me.load({
-   success: function(response, opts) {
-   var res = PVE.Parser.parseACME(response.result.data.acme);
-   if (res) {
-   res.domains = res.domains.join(' ');
-   me.setValues(res);
-   }
-   }
-   });
-}
-});
-
 Ext.define('PVE.node.ACMEAccountCreate', {
 extend: 'Proxmox.window.Edit',
 
@@ -366,138 +320,330 @@ Ext.define('PVE.node.ACMEDomainEdit', {
 },
 });
 
+Ext.define('pve-acme-domains', {
+extend: 'Ext.data.Model',
+fields: ['domain', 'type', 'alias', 'plugin', 'configkey'],
+idProperty: 'domain',
+});
+
 Ext.define('PVE.node.ACME', {
-extend: 'Proxmox.grid.ObjectGrid',
-xtype: 'pveACMEView',
+extend: 'Ext.grid.Panel',
+alias: 'widget.pveACMEView',
 
 margin: '10 0 0 0',
 title: 'ACME',
 
+viewModel: {
+   data: {
+   account: null,
+   accountEditable: false,
+   },
+
+   formulas: {
+   editBtnIcon: (get) => {
+   return 'fa black fa-' + (get('accountEditable') ? 'check' : 
'pencil');
+   },
+   },
+},
+
+controller: {
+   xclass: 'Ext.app.ViewController',
+
+   addDomain: function() {
+   let me = this;
+   let view = me.getView();
+
+   Ext.create('PVE.node.ACMEDomainEdit', {
+   nodename: view.nodename,
+   nodeconfig: view.nodeconfig,
+   apiCallDone: function() {
+   me.reload();
+   },
+   }).show();
+   },
+
+   editDomain: function() {
+   let me = this;
+   let view = me.getView();
+
+   let selection = view.getSelection();
+   if (selection.length < 1) return;
+
+   Ext.create('PVE.node.ACMEDomainEdit', {
+   nodename: view.nodename,
+   nodeconfig: view.nodeconfig,
+   domain: selection[0].data,
+   apiCallDone: function() {
+   me.reload();
+   },
+   }).show();
+   },
+
+   removeDomain: function() {
+   let me = this;
+   let view = me.getView();
+   let selection = view.getSelection();
+   if (selection.length < 1) return;
+
+   let rec = selection[0].data;
+   let params = {};
+   if (rec.configkey !== 'acme') {
+   params.delete = rec.configkey;
+   } else {
+   let acme = PVE.Parser.parseACME(view.nodeconfig.acme);
+   PVE.Utils.remove_domain_from_acme(acme, rec.domain);
+   params.acme = PVE.Parser.printACME(acme);
+   }
+
+   Proxmox.Utils.API2Request({
+   method: 'PUT',
+   url: `/nodes/${view.nodename}/config`,
+   params,
+   success: function(response, opt) {
+   

[pve-devel] [PATCH manager v2 3/5] ui: Utils: add helper functions for acme domains

2020-05-06 Thread Dominik Csapak
to convieniently add and remove domains from a parsed ACME object
they also make domains unique in the array

also add the count of configureable acmedomainX entries

Signed-off-by: Dominik Csapak 
---
 www/manager6/Utils.js | 23 +++
 1 file changed, 23 insertions(+)

diff --git a/www/manager6/Utils.js b/www/manager6/Utils.js
index 872b7c29..31e262c0 100644
--- a/www/manager6/Utils.js
+++ b/www/manager6/Utils.js
@@ -1354,6 +1354,29 @@ Ext.define('PVE.Utils', { utilities: {
}
 },
 
+acmedomain_count: 5,
+
+add_domain_to_acme: function(acme, domain) {
+   if (acme.domains === undefined) {
+   acme.domains = [domain];
+   } else {
+   acme.domains.push(domain);
+   acme.domains = acme.domains.filter((value, index, self) => {
+   return self.indexOf(value) === index;
+   });
+   }
+   return acme;
+},
+
+remove_domain_from_acme: function(acme, domain) {
+   if (acme.domains !== undefined) {
+   acme.domains = acme.domains.filter((value, index, self) => {
+   return self.indexOf(value) === index && value !== domain;
+   });
+   }
+   return acme;
+},
+
 handleStoreErrorOrMask: function(me, store, regex, callback) {
 
me.mon(store, 'load', function (proxy, response, success, operation) {
-- 
2.20.1


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


[pve-devel] [PATCH manager v2 1/5] ui: add ACME selector formfields for account and plugins

2020-05-06 Thread Dominik Csapak
filter the plugins by type === 'dns'
and add a convenience method for ACMEAccountSelector to check if there
are any accounts

Signed-off-by: Dominik Csapak 
---
changes from v1:
* drop fieldLabel in ACMEAccountSelector
 www/manager6/Makefile|  2 ++
 www/manager6/form/ACMEAccountSelector.js | 21 +
 www/manager6/form/ACMEPluginSelector.js  | 19 +++
 3 files changed, 42 insertions(+)
 create mode 100644 www/manager6/form/ACMEAccountSelector.js
 create mode 100644 www/manager6/form/ACMEPluginSelector.js

diff --git a/www/manager6/Makefile b/www/manager6/Makefile
index e2214588..563e7dc5 100644
--- a/www/manager6/Makefile
+++ b/www/manager6/Makefile
@@ -73,6 +73,8 @@ JSSRC=
\
form/SDNControllerSelector.js   \
form/TFASelector.js \
form/ACMEAPiSelector.js \
+   form/ACMEAccountSelector.js \
+   form/ACMEPluginSelector.js  \
dc/Tasks.js \
dc/Log.js   \
panel/StatusPanel.js\
diff --git a/www/manager6/form/ACMEAccountSelector.js 
b/www/manager6/form/ACMEAccountSelector.js
new file mode 100644
index ..12d5848c
--- /dev/null
+++ b/www/manager6/form/ACMEAccountSelector.js
@@ -0,0 +1,21 @@
+Ext.define('PVE.form.ACMEAccountSelector', {
+extend: 'Ext.form.field.ComboBox',
+alias: 'widget.pveACMEAccountSelector',
+
+displayField: 'name',
+valueField: 'name',
+
+store: {
+   model: 'pve-acme-accounts',
+   autoLoad: true,
+},
+
+triggerAction: 'all',
+queryMode: 'local',
+allowBlank: false,
+editable: false,
+
+isEmpty: function() {
+   return this.getStore().getData().length === 0;
+}
+});
diff --git a/www/manager6/form/ACMEPluginSelector.js 
b/www/manager6/form/ACMEPluginSelector.js
new file mode 100644
index ..ccce97b8
--- /dev/null
+++ b/www/manager6/form/ACMEPluginSelector.js
@@ -0,0 +1,19 @@
+Ext.define('PVE.form.ACMEPluginSelector', {
+extend: 'Ext.form.field.ComboBox',
+alias: 'widget.pveACMEPluginSelector',
+
+fieldLabel: gettext('Plugin'),
+displayField: 'plugin',
+valueField: 'plugin',
+
+store: {
+   model: 'pve-acme-plugins',
+   autoLoad: true,
+   filters: item => item.data.type === 'dns',
+},
+
+triggerAction: 'all',
+queryMode: 'local',
+allowBlank: false,
+editable: false,
+});
-- 
2.20.1


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


[pve-devel] [PATCH manager v2 0/5] ACME node adaptions for plugins

2020-05-06 Thread Dominik Csapak
this series adapts the node->certificates->acme panel to include
an 'accountselector' and to be able to add/edit/remove single domains,
including ones with a plugin

changes from v1:
* drop fieldLabel in ACMEAccountSelector
* reword 'Account' in 'Used Account'
* use different approach to change the account
  (use viewModel and a displayfield/combobox/editbutton to better
  see when the account actually changes)

Dominik Csapak (5):
  ui: add ACME selector formfields for account and plugins
  ui: Parser: add printACME
  ui: Utils: add helper functions for acme domains
  ui: node/ACME: add ACMEDomainEdit
  ui: node/ACME: rework ACME grid for plugin based domains

 www/manager6/Makefile|   2 +
 www/manager6/Parser.js   |   7 +
 www/manager6/Utils.js|  23 +
 www/manager6/form/ACMEAccountSelector.js |  21 +
 www/manager6/form/ACMEPluginSelector.js  |  19 +
 www/manager6/node/ACME.js| 617 ---
 6 files changed, 517 insertions(+), 172 deletions(-)
 create mode 100644 www/manager6/form/ACMEAccountSelector.js
 create mode 100644 www/manager6/form/ACMEPluginSelector.js

-- 
2.20.1


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


[pve-devel] [PATCH manager 1/5] ui: add ACME selector formfields for account and plugins

2020-05-06 Thread Dominik Csapak
filter the plugins by type === 'dns'
and add a convenience method for ACMEAccountSelector to check if there
are any accounts

Signed-off-by: Dominik Csapak 
---
 www/manager6/Makefile|  2 ++
 www/manager6/form/ACMEAccountSelector.js | 22 ++
 www/manager6/form/ACMEPluginSelector.js  | 19 +++
 3 files changed, 43 insertions(+)
 create mode 100644 www/manager6/form/ACMEAccountSelector.js
 create mode 100644 www/manager6/form/ACMEPluginSelector.js

diff --git a/www/manager6/Makefile b/www/manager6/Makefile
index e2214588..563e7dc5 100644
--- a/www/manager6/Makefile
+++ b/www/manager6/Makefile
@@ -73,6 +73,8 @@ JSSRC=
\
form/SDNControllerSelector.js   \
form/TFASelector.js \
form/ACMEAPiSelector.js \
+   form/ACMEAccountSelector.js \
+   form/ACMEPluginSelector.js  \
dc/Tasks.js \
dc/Log.js   \
panel/StatusPanel.js\
diff --git a/www/manager6/form/ACMEAccountSelector.js 
b/www/manager6/form/ACMEAccountSelector.js
new file mode 100644
index ..5b533c1b
--- /dev/null
+++ b/www/manager6/form/ACMEAccountSelector.js
@@ -0,0 +1,22 @@
+Ext.define('PVE.form.ACMEAccountSelector', {
+extend: 'Ext.form.field.ComboBox',
+alias: 'widget.pveACMEAccountSelector',
+
+fieldLabel: gettext('Account'),
+displayField: 'name',
+valueField: 'name',
+
+store: {
+   model: 'pve-acme-accounts',
+   autoLoad: true,
+},
+
+triggerAction: 'all',
+queryMode: 'local',
+allowBlank: false,
+editable: false,
+
+isEmpty: function() {
+   return this.getStore().getData().length === 0;
+}
+});
diff --git a/www/manager6/form/ACMEPluginSelector.js 
b/www/manager6/form/ACMEPluginSelector.js
new file mode 100644
index ..ccce97b8
--- /dev/null
+++ b/www/manager6/form/ACMEPluginSelector.js
@@ -0,0 +1,19 @@
+Ext.define('PVE.form.ACMEPluginSelector', {
+extend: 'Ext.form.field.ComboBox',
+alias: 'widget.pveACMEPluginSelector',
+
+fieldLabel: gettext('Plugin'),
+displayField: 'plugin',
+valueField: 'plugin',
+
+store: {
+   model: 'pve-acme-plugins',
+   autoLoad: true,
+   filters: item => item.data.type === 'dns',
+},
+
+triggerAction: 'all',
+queryMode: 'local',
+allowBlank: false,
+editable: false,
+});
-- 
2.20.1


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


[pve-devel] [PATCH manager 0/5] ACME node adaptions for plugins

2020-05-06 Thread Dominik Csapak
this series adapts the node->certificates->acme panel to include
an 'accountselector' and to be able to add/edit/remove single domains,
including ones with a plugin

Dominik Csapak (5):
  ui: add ACME selector formfields for account and plugins
  ui: Parser: add printACME
  ui: Utils: add helper functions for acme domains
  ui: node/ACME: add ACMEDomainEdit
  ui: node/ACME: rework ACME grid for plugin based domains

 www/manager6/Makefile|   2 +
 www/manager6/Parser.js   |   7 +
 www/manager6/Utils.js|  23 +
 www/manager6/form/ACMEAccountSelector.js |  22 +
 www/manager6/form/ACMEPluginSelector.js  |  19 +
 www/manager6/node/ACME.js| 556 ---
 6 files changed, 463 insertions(+), 166 deletions(-)
 create mode 100644 www/manager6/form/ACMEAccountSelector.js
 create mode 100644 www/manager6/form/ACMEPluginSelector.js

-- 
2.20.1


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


[pve-devel] [PATCH manager 3/5] ui: Utils: add helper functions for acme domains

2020-05-06 Thread Dominik Csapak
to convieniently add and remove domains from a parsed ACME object
they also make domains unique in the array

also add the count of configureable acmedomainX entries

Signed-off-by: Dominik Csapak 
---
 www/manager6/Utils.js | 23 +++
 1 file changed, 23 insertions(+)

diff --git a/www/manager6/Utils.js b/www/manager6/Utils.js
index 872b7c29..31e262c0 100644
--- a/www/manager6/Utils.js
+++ b/www/manager6/Utils.js
@@ -1354,6 +1354,29 @@ Ext.define('PVE.Utils', { utilities: {
}
 },
 
+acmedomain_count: 5,
+
+add_domain_to_acme: function(acme, domain) {
+   if (acme.domains === undefined) {
+   acme.domains = [domain];
+   } else {
+   acme.domains.push(domain);
+   acme.domains = acme.domains.filter((value, index, self) => {
+   return self.indexOf(value) === index;
+   });
+   }
+   return acme;
+},
+
+remove_domain_from_acme: function(acme, domain) {
+   if (acme.domains !== undefined) {
+   acme.domains = acme.domains.filter((value, index, self) => {
+   return self.indexOf(value) === index && value !== domain;
+   });
+   }
+   return acme;
+},
+
 handleStoreErrorOrMask: function(me, store, regex, callback) {
 
me.mon(store, 'load', function (proxy, response, success, operation) {
-- 
2.20.1


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


[pve-devel] [PATCH manager 2/5] ui: Parser: add printACME

2020-05-06 Thread Dominik Csapak
since we decode the domain list in parseACME into an array, we
have to join them again to a string when printing

otherwise printPropertyString attaches them just with ',' which
does not work here

Signed-off-by: Dominik Csapak 
---
 www/manager6/Parser.js | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/www/manager6/Parser.js b/www/manager6/Parser.js
index 4cecb3e1..20d81d4a 100644
--- a/www/manager6/Parser.js
+++ b/www/manager6/Parser.js
@@ -5,6 +5,13 @@ Ext.define('PVE.Parser', { statics: {
 
 // this class only contains static functions
 
+printACME: function(value) {
+   if (Ext.isArray(value.domains)) {
+   value.domains = value.domains.join(';');
+   }
+   return PVE.Parser.printPropertyString(value);
+},
+
 parseACME: function(value) {
if (!value) {
return;
-- 
2.20.1


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


[pve-devel] [PATCH manager 4/5] ui: node/ACME: add ACMEDomainEdit

2020-05-06 Thread Dominik Csapak
which expects a nodeconfig (for digest and domaincount)
and for the edit case, the parsed 'domain' object

this editwindow has three fields:
* type selector (standalone/dns)
* domain
* plugin (only for dns)

if the user chooses dns but there are already the maximum count of
acmedomainX entries, the type field gets invalid (with a error tooltip)

the onGetValues method is non-trivial, because of the mixing of
acmedomainX and acme.domain values, so we have to be careful
that we delete/edit the correct entry

Signed-off-by: Dominik Csapak 
---
 www/manager6/node/ACME.js | 136 ++
 1 file changed, 136 insertions(+)

diff --git a/www/manager6/node/ACME.js b/www/manager6/node/ACME.js
index 40ecc00e..a8bb39d6 100644
--- a/www/manager6/node/ACME.js
+++ b/www/manager6/node/ACME.js
@@ -230,6 +230,142 @@ Ext.define('PVE.node.ACMEAccountView', {
 }
 });
 
+Ext.define('PVE.node.ACMEDomainEdit', {
+extend: 'Proxmox.window.Edit',
+alias: 'widget.pveACMEDomainEdit',
+
+subject: gettext('Domain'),
+isCreate: false,
+
+items: [
+   {
+   xtype: 'inputpanel',
+   onGetValues: function(values) {
+   let me = this;
+   let win = me.up('pveACMEDomainEdit');
+   let nodeconfig = win.nodeconfig;
+   let olddomain = win.domain || {};
+
+   let params = {
+   digest: nodeconfig.digest,
+   };
+
+   let configkey = olddomain.configkey;
+   let acmeObj = PVE.Parser.parseACME(nodeconfig.acme) || {};
+
+   if (values.type === 'dns') {
+   if (!olddomain.configkey || olddomain.configkey === 'acme') 
{
+   // look for first free slot
+   for (let i = 0; i < PVE.Utils.acmedomain_count; i++) {
+   if (nodeconfig[`acmedomain${i}`] === undefined) {
+   configkey = `acmedomain${i}`;
+   break;
+   }
+   }
+   if (olddomain.domain) {
+   // we have to remove the domain from the acme 
domainlist
+   PVE.Utils.remove_domain_from_acme(acmeObj, 
olddomain.domain);
+   params.acme = PVE.Parser.printACME(acmeObj);
+   }
+   }
+
+   delete values.type;
+   params[configkey] = PVE.Parser.printPropertyString(values, 
'domain');
+   } else {
+   if (olddomain.configkey && olddomain.configkey !== 'acme') {
+   // delete the old dns entry
+   params.delete = [olddomain.configkey];
+   }
+
+   // add new, remove old and make entries unique
+   PVE.Utils.add_domain_to_acme(acmeObj, values.domain);
+   PVE.Utils.remove_domain_from_acme(acmeObj, 
olddomain.domain);
+   params.acme = PVE.Parser.printACME(acmeObj);
+   }
+
+   return params;
+   },
+   items: [
+   {
+   xtype: 'proxmoxKVComboBox',
+   name: 'type',
+   fieldLabel: gettext('Type'),
+   allowBlank: false,
+   comboItems: [
+   ['standalone', 'standalone'],
+   ['dns', 'DNS'],
+   ],
+   validator: function(value) {
+   let me = this;
+   let win = me.up('pveACMEDomainEdit');
+   let oldconfigkey = win.domain ? win.domain.configkey : 
undefined;
+   let val = me.getValue();
+   if (val === 'dns' && (!oldconfigkey || oldconfigkey === 
'acme')) {
+   // we have to check if there is a 'acmedomain' slot 
left
+   let found = false;
+   for (let i = 0; i < PVE.Utils.acmedomain_count; 
i++) {
+   if (!win.nodeconfig[`acmedomain${i}`]) {
+   found = true;
+   }
+   }
+   if (!found) {
+   return gettext('Only 5 Domains with type DNS 
can be configured');
+   }
+   }
+
+   return true;
+   },
+   listeners: {
+   change: function(cb, value) {
+   let me = this;
+   let view = me.up('pveACMEDomainEdit');
+   view.down('field[name=plugin]').setDisabled(value 
!== 'dns');
+   },
+   },
+   },
+   {
+   

[pve-devel] [PATCH manager 5/5] ui: node/ACME: rework ACME grid for plugin based domains

2020-05-06 Thread Dominik Csapak
This is basically a complete rework of the ACME grid.
Instead of having an ObjectGrid, we now have a normal
GridPanel which allows us to show a row for each Domain.

But to achieve this, we need to manually fill the store with data
from the 'acme' and 'acmedomainX' entries of the node config.

We also add an AccountSelector to the tbar and a link to the
datacenter->acme panel (when there is no account)

this also removes the 'register account' and 'view account' buttons,
since those are now available in datacenter->acme

removes the old 'acmeeditor' since that is no longer needed

Signed-off-by: Dominik Csapak 
---
 www/manager6/node/ACME.js | 420 +++---
 1 file changed, 254 insertions(+), 166 deletions(-)

diff --git a/www/manager6/node/ACME.js b/www/manager6/node/ACME.js
index a8bb39d6..f6499d6e 100644
--- a/www/manager6/node/ACME.js
+++ b/www/manager6/node/ACME.js
@@ -1,49 +1,3 @@
-Ext.define('PVE.node.ACMEEditor', {
-extend: 'Proxmox.window.Edit',
-xtype: 'pveACMEEditor',
-
-subject: gettext('Domains'),
-items: [
-   {
-   xtype: 'inputpanel',
-   items: [
-   {
-   xtype: 'textarea',
-   fieldLabel: gettext('Domains'),
-   emptyText: "domain1.example.com\ndomain2.example.com",
-   name: 'domains'
-   }
-   ],
-   onGetValues: function(values) {
-   if (!values.domains) {
-   return {
-   'delete': 'acme'
-   };
-   }
-   var domains = values.domains.split(/\n/).join(';');
-   return {
-   'acme': 'domains=' + domains
-   };
-   }
-   }
-],
-
-initComponent: function() {
-   var me = this;
-   me.callParent();
-
-   me.load({
-   success: function(response, opts) {
-   var res = PVE.Parser.parseACME(response.result.data.acme);
-   if (res) {
-   res.domains = res.domains.join(' ');
-   me.setValues(res);
-   }
-   }
-   });
-}
-});
-
 Ext.define('PVE.node.ACMEAccountCreate', {
 extend: 'Proxmox.window.Edit',
 
@@ -366,138 +320,279 @@ Ext.define('PVE.node.ACMEDomainEdit', {
 },
 });
 
+Ext.define('pve-acme-domains', {
+extend: 'Ext.data.Model',
+fields: ['domain', 'type', 'alias', 'plugin', 'configkey'],
+idProperty: 'domain',
+});
+
 Ext.define('PVE.node.ACME', {
-extend: 'Proxmox.grid.ObjectGrid',
-xtype: 'pveACMEView',
+extend: 'Ext.grid.Panel',
+alias: 'widget.pveACMEView',
 
 margin: '10 0 0 0',
 title: 'ACME',
 
+controller: {
+   xclass: 'Ext.app.ViewController',
+
+   addDomain: function() {
+   let me = this;
+   let view = me.getView();
+
+   Ext.create('PVE.node.ACMEDomainEdit', {
+   nodename: view.nodename,
+   nodeconfig: view.nodeconfig,
+   apiCallDone: function() {
+   me.reload();
+   },
+   }).show();
+   },
+
+   editDomain: function() {
+   let me = this;
+   let view = me.getView();
+
+   let selection = view.getSelection();
+   if (selection.length < 1) return;
+
+   Ext.create('PVE.node.ACMEDomainEdit', {
+   nodename: view.nodename,
+   nodeconfig: view.nodeconfig,
+   domain: selection[0].data,
+   apiCallDone: function() {
+   me.reload();
+   },
+   }).show();
+   },
+
+   removeDomain: function() {
+   let me = this;
+   let view = me.getView();
+   let selection = view.getSelection();
+   if (selection.length < 1) return;
+
+   let rec = selection[0].data;
+   let params = {};
+   if (rec.configkey !== 'acme') {
+   params.delete = rec.configkey;
+   } else {
+   let acme = PVE.Parser.parseACME(view.nodeconfig.acme);
+   PVE.Utils.remove_domain_from_acme(acme, rec.domain);
+   params.acme = PVE.Parser.printACME(acme);
+   }
+
+   Proxmox.Utils.API2Request({
+   method: 'PUT',
+   url: `/nodes/${view.nodename}/config`,
+   params,
+   success: function(response, opt) {
+   me.reload();
+   },
+   failure: function(response, opt) {
+   Ext.Msg.alert(gettext('Error'), response.htmlStatus);
+   },
+   });
+   },
+
+   changeAccount: function(cb, value, oldvalue) {
+   if (value === oldvalue) return;
+   let me = this;
+   let view = me.getView();
+   let params = {};
+
+   let acme = PVE.Parser.parseACME(view.nodeconfig.acme);
+ 

[pve-devel] [PATCH manager 1/6] ACMEPlugin: check digest on update

2020-05-05 Thread Dominik Csapak
and extract the param, otherwise the check dies because of an unknown
field 'digest'

Signed-off-by: Dominik Csapak 
---
 PVE/API2/ACMEPlugin.pm | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/PVE/API2/ACMEPlugin.pm b/PVE/API2/ACMEPlugin.pm
index 92e0dfb6..71f53a35 100644
--- a/PVE/API2/ACMEPlugin.pm
+++ b/PVE/API2/ACMEPlugin.pm
@@ -173,9 +173,11 @@ __PACKAGE__->register_method({
 
my $id = extract_param($param, 'id');
my $delete = extract_param($param, 'delete');
+   my $digest = extract_param($param, 'digest');
 
cfs_lock_file($plugin_config_file, undef, sub {
my $cfg = load_config();
+   PVE::Tools::assert_if_modified($cfg->{digest}, $digest);
my $plugin_cfg = $cfg->{ids}->{$id};
die "ACME plugin ID '$id' does not exist\n" if !$plugin_cfg;
 
-- 
2.20.1


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


[pve-devel] [PATCH 1/2] DNSChallenge: make plugins a hash with an optional schema

2020-05-05 Thread Dominik Csapak
so that we can use that schema to generate form fields in the gui

Signed-off-by: Dominik Csapak 
---
 src/PVE/ACME/DNSChallenge.pm | 235 ---
 1 file changed, 132 insertions(+), 103 deletions(-)

diff --git a/src/PVE/ACME/DNSChallenge.pm b/src/PVE/ACME/DNSChallenge.pm
index 2b4f051..8a393f4 100644
--- a/src/PVE/ACME/DNSChallenge.pm
+++ b/src/PVE/ACME/DNSChallenge.pm
@@ -18,109 +18,138 @@ sub type {
 return 'dns';
 }
 
-my $plugin_names = [
-'acmedns',
-'acmeproxy',
-'active24',
-'ad',
-'ali',
-'autodns',
-'aws',
-'azure',
-'cf',
-'clouddns',
-'cloudns',
-'cn',
-'conoha',
-'constellix',
-'cx',
-'cyon',
-'da',
-'ddnss',
-'desec',
-'dgon',
-'dnsimple',
-'do',
-'doapi',
-'domeneshop',
-'dp',
-'dpi',
-'dreamhost',
-'duckdns',
-'durabledns',
-'dyn',
-'dynu',
-'dynv6',
-'easydns',
-'euserv',
-'exoscale',
-'freedns',
-'gandi_livedns',
-'gcloud',
-'gd',
-'gdnsdk',
-'he',
-'hexonet',
-'hostingde',
-'infoblox',
-'internetbs',
-'inwx',
-'ispconfig',
-'jd',
-'kas',
-'kinghost',
-'knot',
-'leaseweb',
-'lexicon',
-'linode',
-'linode_v4',
-'loopia',
-'lua',
-'maradns',
-'me',
-'miab',
-'misaka',
-'myapi',
-'mydevil',
-'mydnsjp',
-'namecheap',
-'namecom',
-'namesilo',
-'nederhost',
-'neodigit',
-'netcup',
-'nic',
-'nsd',
-'nsone',
-'nsupdate',
-'nw',
-'one',
-'online',
-'openprovider',
-'opnsense',
-'ovh',
-'pdns',
-'pleskxml',
-'pointhq',
-'rackspace',
-'rcode0',
-'regru',
-'schlundtech',
-'selectel',
-'servercow',
-'tele3',
-'ultra',
-'unoeuro',
-'variomedia',
-'vscale',
-'vultr',
-'yandex',
-'zilore',
-'zone',
-'zonomi',
-];
+# describe the data schema of the supported plugins
+my $plugins = {
+'acmedns' => {},
+'acmeproxy' => {},
+'active24' => {},
+'ad' => {},
+'ali' => {},
+'autodns' => {},
+'aws' => {},
+'azure' => {},
+'cf' => {},
+'clouddns' => {},
+'cloudns' => {},
+'cn' => {},
+'conoha' => {},
+'constellix' => {},
+'cx' => {},
+'cyon' => {},
+'da' => {},
+'ddnss' => {},
+'desec' => {},
+'dgon' => {},
+'dnsimple' => {},
+'do' => {},
+'doapi' => {},
+'domeneshop' => {},
+'dp' => {},
+'dpi' => {},
+'dreamhost' => {},
+'duckdns' => {},
+'durabledns' => {},
+'dyn' => {},
+'dynu' => {},
+'dynv6' => {},
+'easydns' => {},
+'euserv' => {},
+'exoscale' => {},
+'freedns' => {},
+'gandi_livedns' => {},
+'gcloud' => {},
+'gd' => {},
+'gdnsdk' => {},
+'he' => {},
+'hexonet' => {},
+'hostingde' => {},
+'infoblox' => {},
+'internetbs' => {},
+'inwx' => {},
+'ispconfig' => {},
+'jd' => {},
+'kas' => {},
+'kinghost' => {},
+'knot' => {},
+'leaseweb' => {},
+'lexicon' => {},
+'linode' => {},
+'linode_v4' => {},
+'loopia' => {},
+'lua' => {},
+'maradns' => {},
+'me' => {},
+'miab' => {},
+'misaka' => {},
+'myapi' => {},
+'mydevil' => {},
+'mydnsjp' => {},
+'namecheap' => {},
+'namecom' => {},
+'namesilo' => {},
+'nederhost' => {},
+'neodigit' => {},
+'netcup' => {},
+'nic' => {},
+'nsd' => {},
+'nsone' => {},
+'nsupdate' => {},
+'nw' => {},
+'one' => {},
+'online' => {},
+'openprovider' => {},
+'opnsense' => {},
+'ovh' => {
+   'OVH_END_POINT' => {
+   description => "The OVH endpoint",
+   type => 'string',
+   },
+   'OVH_AK' => {
+   description => "The application key.",
+   type => 'string',
+   },
+   'OVH_AS' => {
+   description => "The application secret.",
+   type => 'string',
+   },
+},
+'pdns' => {
+   'PDNS_Url' => {
+   description => "The PowerDNS API endpoint.",
+   type => 'string',
+   },
+   'PDNS_ServerId'=> {
+   type => 'string',
+   },
+   'PDNS_Token'=> {
+   type => 'string',
+   },
+   'PDNS_Ttl'=> {
+   type => 'integer',
+   },
+},
+'pleskxml' => {},
+'pointhq' => {},
+'rackspace' => {},
+'rcode0' => {},
+'regru' => {},
+'schlundtech' => {},
+'selectel' => {},
+'servercow' => {},
+'tele3' => {},
+'ultra' =>

[pve-devel] [PATCH 2/2] add note that the data has to be base64 encoded

2020-05-05 Thread Dominik Csapak
but only via api, on the cli it is a file which contains
the data in plaintext

Signed-off-by: Dominik Csapak 
---
 src/PVE/ACME/DNSChallenge.pm | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/PVE/ACME/DNSChallenge.pm b/src/PVE/ACME/DNSChallenge.pm
index 8a393f4..534922d 100644
--- a/src/PVE/ACME/DNSChallenge.pm
+++ b/src/PVE/ACME/DNSChallenge.pm
@@ -161,7 +161,7 @@ sub properties {
},
data => {
type => 'string',
-   description => 'DNS plugin data.',
+   description => 'DNS plugin data. (base64 encoded)',
},
'validation-delay' => {
type => 'integer',
-- 
2.20.1


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


[pve-devel] [PATCH proxmox-acme/pve-manager] add crud for acme accounts/plugin

2020-05-05 Thread Dominik Csapak
this series adds the gui (and necessary api calls) for
adding/editing/deleting acme accounts and plugins

gui parts still missing are:
* changing the account on the node
* selecting a plugin for a domain

proxmox-acme:

Dominik Csapak (2):
  DNSChallenge: make plugins a hash with an optional schema
  add note that the data has to be base64 encoded

 src/PVE/ACME/DNSChallenge.pm | 237 ---
 1 file changed, 133 insertions(+), 104 deletions(-)

pve-manager:

Dominik Csapak (6):
  ACMEPlugin: check digest on update
  ACME: add challengeschema api call
  ui: ACMEAccountCreate: add optional name field
  ui: add ACMEAPiSelector field
  ui: add ACMEPluginEdit window
  ui: add ACMEClusterView

 PVE/API2/ACMEAccount.pm  |  55 +++
 PVE/API2/ACMEPlugin.pm   |   2 +
 www/manager6/Makefile|   3 +
 www/manager6/Parser.js   |  17 ++-
 www/manager6/dc/ACMEClusterView.js   | 206 +++
 www/manager6/dc/ACMEPluginEdit.js| 190 
 www/manager6/dc/Config.js|  10 ++
 www/manager6/form/ACMEAPiSelector.js |  40 ++
 www/manager6/node/ACME.js|   7 +
 9 files changed, 529 insertions(+), 1 deletion(-)
 create mode 100644 www/manager6/dc/ACMEClusterView.js
 create mode 100644 www/manager6/dc/ACMEPluginEdit.js
 create mode 100644 www/manager6/form/ACMEAPiSelector.js

-- 
2.20.1


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


[pve-devel] [PATCH manager 6/6] ui: add ACMEClusterView

2020-05-05 Thread Dominik Csapak
to show the list of accounts and defined plugins
for now we ignore 'standalone' plugins here and only show 'dns' ones

Signed-off-by: Dominik Csapak 
---
 www/manager6/Makefile  |   1 +
 www/manager6/dc/ACMEClusterView.js | 206 +
 www/manager6/dc/Config.js  |  10 ++
 3 files changed, 217 insertions(+)
 create mode 100644 www/manager6/dc/ACMEClusterView.js

diff --git a/www/manager6/Makefile b/www/manager6/Makefile
index fb4c51bb..4deb7990 100644
--- a/www/manager6/Makefile
+++ b/www/manager6/Makefile
@@ -217,6 +217,7 @@ JSSRC=  
\
ha/GroupEdit.js \
ha/Groups.js\
ha/Fencing.js   \
+   dc/ACMEClusterView.js   \
dc/ACMEPluginEdit.js\
dc/Summary.js   \
grid/Replication.js \
diff --git a/www/manager6/dc/ACMEClusterView.js 
b/www/manager6/dc/ACMEClusterView.js
new file mode 100644
index ..a0bbd8a5
--- /dev/null
+++ b/www/manager6/dc/ACMEClusterView.js
@@ -0,0 +1,206 @@
+Ext.define('pve-acme-accounts', {
+extend: 'Ext.data.Model',
+fields: ['name'],
+proxy: {
+   type: 'proxmox',
+   url: "/api2/json/cluster/acme/account",
+},
+idProperty: 'name',
+});
+
+Ext.define('pve-acme-plugins', {
+extend: 'Ext.data.Model',
+fields: ['type', 'plugin'],
+proxy: {
+   type: 'proxmox',
+   url: "/api2/json/cluster/acme/plugins",
+},
+idProperty: 'plugin',
+});
+
+Ext.define('PVE.dc.ACMEAccountView', {
+extend: 'Ext.grid.Panel',
+alias: 'widget.pveACMEAccountView',
+
+title: gettext('Accounts'),
+
+controller: {
+   xclass: 'Ext.app.ViewController',
+
+   addAccount: function() {
+   let me = this;
+   Ext.create('PVE.node.ACMEAccountCreate', {
+   taskDone: function() {
+   me.reload();
+   },
+   }).show();
+   },
+
+   viewAccount: function() {
+   let me = this;
+   let view = me.getView();
+   let selection = view.getSelection();
+   if (selection.length < 1) return;
+   Ext.create('PVE.node.ACMEAccountView', {
+   accountname: selection[0].data.name,
+   }).show();
+   },
+
+   reload: function() {
+   let me = this;
+   let view = me.getView();
+   view.getStore().load();
+   },
+},
+
+columns: [
+   {
+   dataIndex: 'name',
+   text: gettext('Name'),
+   renderer: Ext.String.htmlEncode,
+   flex: 1,
+   },
+],
+
+tbar: [
+   {
+   xtype: 'proxmoxButton',
+   text: gettext('Add'),
+   selModel: false,
+   handler: 'addAccount',
+   },
+   {
+   xtype: 'proxmoxButton',
+   text: gettext('View'),
+   handler: 'viewAccount',
+   disabled: true,
+   },
+   {
+   xtype: 'proxmoxStdRemoveButton',
+   baseurl: '/cluster/acme/account',
+   callback: 'reload',
+   },
+],
+
+listeners: {
+   itemdblclick: 'viewAccount',
+},
+
+store: {
+   model: 'pve-acme-accounts',
+   autoLoad: true,
+   sorters: 'name',
+},
+});
+
+Ext.define('PVE.dc.ACMEPluginView', {
+extend: 'Ext.grid.Panel',
+alias: 'widget.pveACMEPluginView',
+
+title: gettext('Plugins'),
+
+controller: {
+   xclass: 'Ext.app.ViewController',
+
+   addPlugin: function() {
+   let me = this;
+   Ext.create('PVE.dc.ACMEPluginEditor', {
+   isCreate: true,
+   apiCallDone: function() {
+   me.reload();
+   },
+   }).show();
+   },
+
+   editPlugin: function() {
+   let me = this;
+   let view = me.getView();
+   let selection = view.getSelection();
+   if (selection.length < 1) return;
+   let plugin = selection[0].data.plugin;
+   Ext.create('PVE.dc.ACMEPluginEditor', {
+   url: `/cluster/acme/plugins/${plugin}`,
+   apiCallDone: function() {
+   me.reload();
+   },
+   }).show();
+   },
+
+   reload: function() {
+   let me = this;
+   let view = me.getView();
+   view.getStore().load();
+   },
+},
+
+columns: [
+   {
+   dataIndex: 'plugin',
+   text: gettext('Plugin'),
+   renderer: Ext.String.htmlEncode,
+   flex: 1,
+   },
+   {
+   dataIndex: 'api',
+   text: gettext('API'),
+   renderer: Ext.String.htmlEncode,
+   flex: 1,
+   },
+],
+
+tbar: [
+   {
+  

[pve-devel] [PATCH manager 2/6] ACME: add challengeschema api call

2020-05-05 Thread Dominik Csapak
which returns a list of challenge api types with the schema of their
required data (if it exists)

Signed-off-by: Dominik Csapak 
---
 PVE/API2/ACMEAccount.pm | 55 +
 1 file changed, 55 insertions(+)

diff --git a/PVE/API2/ACMEAccount.pm b/PVE/API2/ACMEAccount.pm
index baff26bd..cbfa19a7 100644
--- a/PVE/API2/ACMEAccount.pm
+++ b/PVE/API2/ACMEAccount.pm
@@ -9,6 +9,7 @@ use PVE::Exception qw(raise_param_exc);
 use PVE::JSONSchema qw(get_standard_option);
 use PVE::RPCEnvironment;
 use PVE::Tools qw(extract_param);
+use PVE::ACME::Challenge;
 
 use PVE::API2::ACMEPlugin;
 
@@ -63,6 +64,7 @@ __PACKAGE__->register_method ({
{ name => 'tos' },
{ name => 'directories' },
{ name => 'plugins' },
+   { name => 'challengeschema' },
];
 }});
 
@@ -366,4 +368,57 @@ __PACKAGE__->register_method ({
return $acme_directories;
 }});
 
+__PACKAGE__->register_method ({
+name => 'challengeschema',
+path => 'challengeschema',
+method => 'GET',
+description => "Get schema of ACME challenge types.",
+permissions => { user => 'all' },
+parameters => {
+   additionalProperties => 0,
+   properties => {},
+},
+returns => {
+   type => 'array',
+   items => {
+   type => 'object',
+   additionalProperties => 0,
+   properties => {
+   name => {
+   type => 'string',
+   },
+   type => {
+   type => 'string',
+   },
+   schema => {
+   type => 'object',
+   },
+   },
+   },
+},
+code => sub {
+   my ($param) = @_;
+
+   my $plugin_type_enum = PVE::ACME::Challenge->lookup_types();
+
+   my $res = [];
+
+   for my $type (@$plugin_type_enum) {
+   my $plugin = PVE::ACME::Challenge->lookup($type);
+   if ($plugin->can('get_supported_plugins')) {
+   my $type = $plugin->type();
+   my $plugins = $plugin->get_supported_plugins();
+   for my $name (sort keys %$plugins) {
+   push @$res, {
+   name => $name,
+   type => $type,
+   schema => $plugins->{$name},
+   };
+   }
+   }
+   }
+
+   return $res;
+}});
+
 1;
-- 
2.20.1


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


[pve-devel] [PATCH manager 4/6] ui: add ACMEAPiSelector field

2020-05-05 Thread Dominik Csapak
which return all api types from /cluster/acme/challengeschema
and has a convenience method for getting the schema of the current value

Signed-off-by: Dominik Csapak 
---
 www/manager6/Makefile|  1 +
 www/manager6/form/ACMEAPiSelector.js | 40 
 2 files changed, 41 insertions(+)
 create mode 100644 www/manager6/form/ACMEAPiSelector.js

diff --git a/www/manager6/Makefile b/www/manager6/Makefile
index ff93b224..62253ede 100644
--- a/www/manager6/Makefile
+++ b/www/manager6/Makefile
@@ -72,6 +72,7 @@ JSSRC=
\
form/SDNZoneSelector.js \
form/SDNControllerSelector.js   \
form/TFASelector.js \
+   form/ACMEAPiSelector.js \
dc/Tasks.js \
dc/Log.js   \
panel/StatusPanel.js\
diff --git a/www/manager6/form/ACMEAPiSelector.js 
b/www/manager6/form/ACMEAPiSelector.js
new file mode 100644
index ..1ae40849
--- /dev/null
+++ b/www/manager6/form/ACMEAPiSelector.js
@@ -0,0 +1,40 @@
+Ext.define('pve-acme-challenges', {
+extend: 'Ext.data.Model',
+fields: ['name', 'schema'],
+proxy: {
+   type: 'proxmox',
+   url: "/api2/json/cluster/acme/challengeschema",
+},
+idProperty: 'name',
+});
+
+Ext.define('PVE.form.ACMEApiSelector', {
+extend: 'Ext.form.field.ComboBox',
+alias: 'widget.pveACMEApiSelector',
+
+fieldLabel: gettext('API'),
+displayField: 'name',
+valueField: 'name',
+
+store: {
+   model: 'pve-acme-challenges',
+   autoLoad: true,
+},
+
+triggerAction: 'all',
+queryMode: 'local',
+allowBlank: false,
+editable: false,
+
+getSchema: function() {
+   let me = this;
+   let val = me.getValue();
+   if (val) {
+   let record = me.getStore().findRecord('name', val);
+   if (record) {
+   return record.data.schema;
+   }
+   }
+   return {};
+},
+});
-- 
2.20.1


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


[pve-devel] [PATCH manager 5/6] ui: add ACMEPluginEdit window

2020-05-05 Thread Dominik Csapak
this is a rather complex edit window, because we dynamically create form
fields according to the schema we get from the api

to do this properly we have to handle a few things:
* we have to properly set the values on edit
* we have to properly track the original values
* we have to merge and split with/from the generic 'data' field
  (so that if a plugin has some extra fields that we did not include in
  the schema the user can still enter them)

Signed-off-by: Dominik Csapak 
---
 www/manager6/Makefile |   1 +
 www/manager6/Parser.js|  17 ++-
 www/manager6/dc/ACMEPluginEdit.js | 190 ++
 3 files changed, 207 insertions(+), 1 deletion(-)
 create mode 100644 www/manager6/dc/ACMEPluginEdit.js

diff --git a/www/manager6/Makefile b/www/manager6/Makefile
index 62253ede..fb4c51bb 100644
--- a/www/manager6/Makefile
+++ b/www/manager6/Makefile
@@ -217,6 +217,7 @@ JSSRC=  
\
ha/GroupEdit.js \
ha/Groups.js\
ha/Fencing.js   \
+   dc/ACMEPluginEdit.js\
dc/Summary.js   \
grid/Replication.js \
dc/Health.js\
diff --git a/www/manager6/Parser.js b/www/manager6/Parser.js
index 43cc4f5f..4cecb3e1 100644
--- a/www/manager6/Parser.js
+++ b/www/manager6/Parser.js
@@ -696,5 +696,20 @@ Ext.define('PVE.Parser', { statics: {
};
}
return null;
-}
+},
+
+parseACMEPluginData: function(data) {
+   let res = {};
+   let extradata = [];
+   data.split('\n').forEach((line) => {
+   // capture everything after the first = as value
+   let [key, value] = line.split(/=(.+)/);
+   if (value !== undefined) {
+   res[key] = value;
+   } else {
+   extradata.push(line);
+   }
+   });
+   return [res, extradata];
+},
 }});
diff --git a/www/manager6/dc/ACMEPluginEdit.js 
b/www/manager6/dc/ACMEPluginEdit.js
new file mode 100644
index ..fd07017c
--- /dev/null
+++ b/www/manager6/dc/ACMEPluginEdit.js
@@ -0,0 +1,190 @@
+Ext.define('PVE.dc.ACMEPluginEditor', {
+extend: 'Proxmox.window.Edit',
+xtype: 'pveACMEPluginEditor',
+mixins: ['Proxmox.Mixin.CBind'],
+
+isAdd: true,
+isCreate: false,
+
+width: 400,
+url: '/cluster/acme/plugins/',
+
+subject: gettext('Plugin'),
+items: [
+   {
+   xtype: 'inputpanel',
+   // we dynamically create fields from the given schema
+   // things we have to do here:
+   // * save which fields we created to remove them again
+   // * split the data from the generic 'data' field into the boxes
+   // * on deletion collect those values again
+   // * save the original values of the data field
+   createdFields: {},
+   createdInitially: false,
+   originalValues: {},
+   createSchemaFields: function(schema) {
+   let me = this;
+   // we know where to add because we define it right below
+   let container = me.down('container');
+   let datafield = me.down('field[name=data]');
+   if (!me.createdInitially) {
+   [me.originalValues] = 
PVE.Parser.parseACMEPluginData(datafield.getValue());
+   }
+
+   // collect values from custom fields and add it to 'data'',
+   // then remove the custom fields
+   let data = [];
+   for (const [name, field] of Object.entries(me.createdFields)) {
+   let value = field.getValue();
+   if (value !== undefined && value !== null && value !== '') {
+   data.push(`${name}=${value}`);
+   }
+   container.remove(field);
+   }
+   let datavalue = datafield.getValue();
+   if (datavalue !== undefined && datavalue !== null && datavalue 
!== '') {
+   data.push(datavalue);
+   }
+   datafield.setValue(data.join('\n'));
+
+   me.createdFields = {};
+
+   // create custom fields according to schema
+   for (const [name, definition] of Object.entries(schema)) {
+   let xtype;
+   switch (definition.type) {
+   case 'string':
+   xtype = 'proxmoxtextfield';
+   break;
+   case 'integer':
+   xtype = 'proxmoxintegerfield';
+   break;
+   case 'number':
+   xtype = 'numberfield';
+   bre

[pve-devel] [PATCH manager 3/6] ui: ACMEAccountCreate: add optional name field

2020-05-05 Thread Dominik Csapak
so that we can create multiple accounts, but leave it empty and set the
emptyText to the default name 'default'

Signed-off-by: Dominik Csapak 
---
 www/manager6/node/ACME.js | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/www/manager6/node/ACME.js b/www/manager6/node/ACME.js
index cfdcc5cf..40ecc00e 100644
--- a/www/manager6/node/ACME.js
+++ b/www/manager6/node/ACME.js
@@ -56,6 +56,13 @@ Ext.define('PVE.node.ACMEAccountCreate', {
 showTaskViewer: true,
 
 items: [
+   {
+   xtype: 'proxmoxtextfield',
+   fieldLabel: gettext('Name'),
+   name: 'name',
+   emptyText: 'default',
+   allowBlank: true,
+   },
{
xtype: 'proxmoxComboGrid',
name: 'directory',
-- 
2.20.1


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


[pve-devel] [PATCH docs v3] add documenation for ldap syncing

2020-05-04 Thread Dominik Csapak
explaining the main Requirements and limitations, as well as the
most important sync options

Signed-off-by: Dominik Csapak 
---
changes from v2:
* incorporated suggestions from aaron
@aaron, regarding linking to character limitations,
sadly no, this is a sub based format, so even if we would have a place
were we could link to for formats (we don't afaik) since it's sub
based there would be no auto-generated information

just for completeness, atm the limit is >2 and <60 characters, and no
'/', ':'

(maybe we can change it to a regex?)

 pveum.adoc | 48 
 1 file changed, 48 insertions(+)

diff --git a/pveum.adoc b/pveum.adoc
index c89d4b8..7f8bd67 100644
--- a/pveum.adoc
+++ b/pveum.adoc
@@ -170,6 +170,54 @@ A server and authentication domain need to be specified. 
Like with
 ldap an optional fallback server, optional port, and SSL
 encryption can be configured.
 
+[[pveum_ldap_sync]]
+Syncing LDAP-based realms
+~
+
+It is possible to sync users and groups for LDAP based realms using
+  pveum sync 
+or in the `Authentication` panel of the GUI. Users and groups are synced
+to `/etc/pve/user.cfg`.
+
+Requirements and limitations
+
+
+The `bind_dn` is used to query the users and groups. This account
+needs access to all desired entries.
+
+The fields which represent the names of the users and groups can be configured
+via the `user_attr` and `group_name_attr` respectively. Only entries which
+adhere to the usual character limitations of the user.cfg are synced.
+
+Groups are synced with `-$realm` attached to the name, to avoid naming
+conflicts. Please make sure that a sync does not overwrite manually created
+groups.
+
+Options
+^^^
+
+The main options for syncing are:
+
+* `dry-run`: No data is written to the config. This is useful if you want to
+  see which users and groups would get synced to the user.cfg. This is set
+  when you click `Preview` in the GUI.
+
+* `enable-new`: If set, the newly synced users are enabled and can login.
+  The default is `true`.
+
+* `full`: If set, the sync uses the LDAP Directory as a source of truth,
+  overwriting information set manually in the user.cfg and deletes users
+  and groups which are not present in the LDAP directory. If not set,
+  only new data is written to the config, and no stale users are deleted.
+
+* `purge`: If set, sync removes all corresponding ACLs when removing users
+  and groups. This is only useful with the option `full`.
+
+* `scope`: The scope of what to sync. It can be either `users`, `groups` or
+  `both`.
+
+These options are either set as parameters or as defaults, via the
+realm option `sync-defaults-options`.
 
 [[pveum_tfa_auth]]
 Two-factor authentication
-- 
2.20.1


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


[pve-devel] [PATCH manager] ui: fix missing htmlEncodes

2020-04-30 Thread Dominik Csapak
username can include some special characters, so we have
to escape them

Signed-off-by: Dominik Csapak 
---
 www/manager6/Workspace.js  | 2 +-
 www/manager6/dc/ACLView.js | 2 +-
 www/manager6/dc/GroupView.js   | 1 +
 www/manager6/dc/Log.js | 2 ++
 www/manager6/dc/PermissionView.js  | 3 ++-
 www/manager6/dc/TFAEdit.js | 1 +
 www/manager6/dc/Tasks.js   | 1 +
 www/manager6/dc/TokenEdit.js   | 1 +
 www/manager6/dc/TokenView.js   | 4 ++--
 www/manager6/dc/UserEdit.js| 1 +
 www/manager6/dc/UserView.js| 4 ++--
 www/manager6/form/GroupSelector.js | 1 +
 www/manager6/form/TokenSelector.js | 1 +
 www/manager6/form/UserSelector.js  | 1 +
 www/manager6/window/Settings.js| 2 +-
 15 files changed, 19 insertions(+), 8 deletions(-)

diff --git a/www/manager6/Workspace.js b/www/manager6/Workspace.js
index 01b462c7..a95b88d7 100644
--- a/www/manager6/Workspace.js
+++ b/www/manager6/Workspace.js
@@ -182,7 +182,7 @@ Ext.define('PVE.StdWorkspace', {
 updateUserInfo: function() {
var me = this;
var ui = me.query('#userinfo')[0];
-   ui.setText(Proxmox.UserName || '');
+   ui.setText(Ext.String.htmlEncode(Proxmox.UserName || ''));
ui.updateLayout();
 },
 
diff --git a/www/manager6/dc/ACLView.js b/www/manager6/dc/ACLView.js
index d0efe22e..24fd67d9 100644
--- a/www/manager6/dc/ACLView.js
+++ b/www/manager6/dc/ACLView.js
@@ -118,7 +118,7 @@ Ext.define('PVE.dc.ACLView', {
return '@' + ugid;
}
 
-   return ugid;
+   return Ext.String.htmlEncode(ugid);
};
 
var columns = [
diff --git a/www/manager6/dc/GroupView.js b/www/manager6/dc/GroupView.js
index c40c5ba1..960ad114 100644
--- a/www/manager6/dc/GroupView.js
+++ b/www/manager6/dc/GroupView.js
@@ -92,6 +92,7 @@ Ext.define('PVE.dc.GroupView', {
header: gettext('Users'),
sortable: false,
dataIndex: 'users',
+   renderer: Ext.String.htmlEncode,
flex: 1
}
],
diff --git a/www/manager6/dc/Log.js b/www/manager6/dc/Log.js
index 48ce272e..fa58c08a 100644
--- a/www/manager6/dc/Log.js
+++ b/www/manager6/dc/Log.js
@@ -68,6 +68,7 @@ Ext.define('PVE.dc.Log', {
{ 
header: gettext("User name"), 
dataIndex: 'user',
+   renderer: Ext.String.htmlEncode,
width: 150
},
{ 
@@ -79,6 +80,7 @@ Ext.define('PVE.dc.Log', {
{ 
header: gettext("Message"), 
dataIndex: 'msg',
+   renderer: Ext.String.htmlEncode,
flex: 1   
}
],
diff --git a/www/manager6/dc/PermissionView.js 
b/www/manager6/dc/PermissionView.js
index 483ab015..cc582261 100644
--- a/www/manager6/dc/PermissionView.js
+++ b/www/manager6/dc/PermissionView.js
@@ -140,7 +140,8 @@ Ext.define('PVE.dc.PermissionView', {
 height: 600,
 layout: 'fit',
 cbind: {
-   title: '{userid} - ' + gettext('Granted Permissions'),
+   title: (get) => Ext.String.htmlEncode(get('userid')) +
+   ` - ${gettext('Granted Permissions')}`,
 },
 items: [{
xtype: 'pveUserPermissionGrid',
diff --git a/www/manager6/dc/TFAEdit.js b/www/manager6/dc/TFAEdit.js
index bf51b8c9..3aada4cd 100644
--- a/www/manager6/dc/TFAEdit.js
+++ b/www/manager6/dc/TFAEdit.js
@@ -376,6 +376,7 @@ Ext.define('PVE.window.TFAEdit', {
{
xtype: 'displayfield',
fieldLabel: gettext('User name'),
+   renderer: Ext.String.htmlEncode,
cbind: {
value: '{userid}'
}
diff --git a/www/manager6/dc/Tasks.js b/www/manager6/dc/Tasks.js
index a011fe4f..b1441a72 100644
--- a/www/manager6/dc/Tasks.js
+++ b/www/manager6/dc/Tasks.js
@@ -101,6 +101,7 @@ Ext.define('PVE.dc.Tasks', {
{
header: gettext("User name"),
dataIndex: 'user',
+   renderer: Ext.String.htmlEncode,
width: 150
},
{
diff --git a/www/manager6/dc/TokenEdit.js b/www/manager6/dc/TokenEdit.js
index cdb5d911..13f1dff8 100644
--- a/www/manager6/dc/TokenEdit.js
+++ b/www/manager6/dc/TokenEdit.js
@@ -41,6 +41,7 @@ Ext.define('PVE.dc.TokenEdit', {
},
name: 'userid',
value: Proxmox.UserName,
+   renderer: Ext.String.htmlEncode,
fieldLabel: gettext('User'),
},
{
diff --git a/www/manager6/dc/TokenView.js b/www/manager6/dc/TokenView.js
index c81d5f2f..69c60569 100644
--- a/www/manager6/dc/T

[pve-devel] [PATCH widget-toolkit] add missing htmlEncodes

2020-04-30 Thread Dominik Csapak
username can include some special characters, so we have
to escape them

Signed-off-by: Dominik Csapak 
---
 window/TaskViewer.js | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/window/TaskViewer.js b/window/TaskViewer.js
index 347542e..bbbf716 100644
--- a/window/TaskViewer.js
+++ b/window/TaskViewer.js
@@ -127,6 +127,7 @@ Ext.define('Proxmox.window.TaskViewer', {
},
user: {
header: gettext('User name'),
+   renderer: Ext.String.htmlEncode,
required: true
},
node: {
@@ -146,7 +147,8 @@ Ext.define('Proxmox.window.TaskViewer', {
renderer: Proxmox.Utils.render_timestamp
},
upid: {
-   header: gettext('Unique task ID')
+   header: gettext('Unique task ID'),
+   renderer: Ext.String.htmlEncode,
}
};
 
-- 
2.20.1


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


[pve-devel] [PATCH docs v2] add documenation for ldap syncing

2020-04-30 Thread Dominik Csapak
explaining the main Requirements and limitations, as well as the
most important sync options

Signed-off-by: Dominik Csapak 
---
changes from v1:
* incorporated suggestions from Alwin, thanks :)
* re-worded the sentence about limitations to specify the character
  limitations of user.cfg
 pveum.adoc | 47 +++
 1 file changed, 47 insertions(+)

diff --git a/pveum.adoc b/pveum.adoc
index c89d4b8..80b3385 100644
--- a/pveum.adoc
+++ b/pveum.adoc
@@ -170,6 +170,53 @@ A server and authentication domain need to be specified. 
Like with
 ldap an optional fallback server, optional port, and SSL
 encryption can be configured.
 
+[[pveum_ldap_sync]]
+Syncing LDAP-based realms
+~
+
+It is possible to sync users and groups for LDAP based realms using
+  pveum sync 
+or in the `Authentication` panel of the GUI to the user.cfg.
+
+Requirements and limitations
+
+
+The `bind_dn` is used to query the users and groups, so this account
+should be able to see all desired entries.
+
+The fields which represent the names of the users and groups can be configured
+via the `user_attr` and `group_name_attr` respectively. Only entries which
+adhere to the usual character limitations of the user.cfg are synced.
+
+Groups are synced with `-$realm` attached to the name, to avoid naming
+conflicts. Please make sure that a sync does not overwrite manually created
+groups.
+
+Options
+^^^
+
+The main options for syncing are:
+
+* `dry-run`: No data is written to the config. This is useful if you want to
+  see which users and groups would get synced to the user.cfg. This is set
+  when you click `Preview` in the GUI.
+
+* `enable-new`: If set, the newly synced users are enabled and can login.
+  The default is `true`.
+
+* `full`: If set, the sync uses the LDAP Directory as a source of truth,
+  overwriting information set manually in the user.cfg and deleting users
+  and groups which are not returned. If not set, only new data is
+  written to the config, and no stale users are deleted.
+
+* `purge`: If set, sync removes all corresponding ACLs when removing users
+  and groups. This is only useful with the option `full`.
+
+* `scope`: The scope of what to sync. It can be either `users`, `groups` or
+  `both`.
+
+These options are either set as parameters or as defaults, via the
+realm option `sync-defaults-options`.
 
 [[pveum_tfa_auth]]
 Two-factor authentication
-- 
2.20.1


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


Re: [pve-devel] [PATCH manager 2/3] Allow setting targetstorage for offline migration

2020-04-30 Thread Dominik Csapak




On 4/30/20 1:15 PM, Fabian Ebner wrote:

Let's make this one an RFC ;)
The problem is that offline migration with target storage might not 
always work depending on supported export/import formats. Then users 
might start an offline migration, which then fails after a few disks 
have already been copied.
If we had a check for the export/import formats before starting 
migration, it would improve. But currently the erroring out happens on a 
per disk basis inside storage_migrate.


So I'm not sure anymore if this is an improvement. If not, and if patch 
#3 is fine, I'll send a v2 without this one.




if we cannot produce a warning/error beforehand, i would abstain
from allowing it in the gui (for now)

we had a similar issue with local disks, which is the
reason most of this panel exists in the first place

having the user wait for an error late into the migration
is really not nice and frustrating for the user

but for 3/3 i wanted to send a very similar patch myself,
so that one is ack'ed by me

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


Re: [pve-devel] [PATCH manager 1/3] Don't show empty parentheses when size is not known

2020-04-30 Thread Dominik Csapak

one comment inline

On 4/30/20 12:59 PM, Fabian Ebner wrote:

The size of VM state files and the size of unused disks not
referenced by any snapshot is not saved in the VM configuration,
so it's not available here either.

Signed-off-by: Fabian Ebner 
---
  www/manager6/window/Migrate.js | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/www/manager6/window/Migrate.js b/www/manager6/window/Migrate.js
index 61bc6a49..9fc66a9b 100644
--- a/www/manager6/window/Migrate.js
+++ b/www/manager6/window/Migrate.js
@@ -269,7 +269,7 @@ Ext.define('PVE.window.Migrate', {
migration['with-local-disks'] = 1;
migration.preconditions.push({
text:'Migration with local disk might take 
long: ' + disk.volid
-   +' (' + 
PVE.Utils.render_size(disk.size) + ')',
+   + (disk.size ? ' (' + 
PVE.Utils.render_size(disk.size) + ')' : ''),\


we are already deeply nested here and the line is already very long,
i would rather put the text above in a variable
(and maybe use template strings)



severity: 'warning'
});
}



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


[pve-devel] [PATCH manager] ui: dc/SyncWindow: add help button

2020-04-30 Thread Dominik Csapak
with link to the LDAP Syncing section of the documentation

Signed-off-by: Dominik Csapak 
---
 www/manager6/dc/SyncWindow.js | 8 
 1 file changed, 8 insertions(+)

diff --git a/www/manager6/dc/SyncWindow.js b/www/manager6/dc/SyncWindow.js
index e85e5b88..9355c551 100644
--- a/www/manager6/dc/SyncWindow.js
+++ b/www/manager6/dc/SyncWindow.js
@@ -21,6 +21,7 @@ Ext.define('PVE.dc.SyncWindow', {
},
'button': {
click: function(btn) {
+   if (btn.reference === 'help_btn') return;
this.sync_realm(btn.reference === 'preview_btn');
},
},
@@ -144,6 +145,13 @@ Ext.define('PVE.dc.SyncWindow', {
 ],
 
 buttons: [
+   {
+   xtype: 'proxmoxHelpButton',
+   reference: 'help_btn',
+   onlineHelp: 'pveum_ldap_sync',
+   hidden: false,
+   },
+   '->',
{
text: gettext('Preview'),
reference: 'preview_btn',
-- 
2.20.1


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


[pve-devel] [PATCH docs] add documenation for ldap syncing

2020-04-30 Thread Dominik Csapak
explaining the main Requirements and limitations, as well as the
most important sync options

Signed-off-by: Dominik Csapak 
---
 pveum.adoc | 47 +++
 1 file changed, 47 insertions(+)

diff --git a/pveum.adoc b/pveum.adoc
index c89d4b8..5881fa9 100644
--- a/pveum.adoc
+++ b/pveum.adoc
@@ -170,6 +170,53 @@ A server and authentication domain need to be specified. 
Like with
 ldap an optional fallback server, optional port, and SSL
 encryption can be configured.
 
+[[pveum_ldap_sync]]
+Syncing LDAP-based realms
+~
+
+It is possible to sync users and groups for ldap based realms using
+  pveum sync 
+or in the `Authentication` panel of the GUI to the user.cfg.
+
+Requirements and limitations
+
+
+The `bind_dn` will be used to query the users and groups, so this account
+should be able to see all desired entries.
+
+The names of the users and groups (configurable via `user_attr` and
+`group_name_attr` respectively) have to adhere to the limitations of usual
+users and groups in the config.
+
+Groups will be synced with `-$realm` attached to the name, to avoid naming
+conflicts. Please make sure that a sync does not overwrite manually created
+groups.
+
+Options
+^^^
+
+The main options for syncing are:
+
+* `dry-run`: No data will actually be synced. This is useful if you want to
+  see which users and groups would get synced to the user.cfg. This is set
+  when you click `Preview` in the GUI.
+
+* `enable-new`: If set, the newly synced users are enabled and can login.
+  The default is `true`.
+
+* `full`: If set, the sync usses the LDAP Directory as source of truth,
+  overwriting information set manually in the user.cfg and deleting users
+  and groups which were not returned. If not set, only new data
+  will be written to the config, and no stale users will be deleted.
+
+* `purge`: If set, sync removes all corresponding ACLs when removing users
+  and groups. This is only useful with the option `full`.
+
+* `scope`: The scope of what to sync. Can be either `users`, `groups` or
+  `both`.
+
+These options either to be set either as parameters, or as defaults, via the
+realm option `sync-defaults-options`.
 
 [[pveum_tfa_auth]]
 Two-factor authentication
-- 
2.20.1


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


  1   2   3   4   5   6   7   8   9   10   >