From mboxrd@z Thu Jan  1 00:00:00 1970
Return-Path: <pve-devel-bounces@lists.proxmox.com>
Received: from firstgate.proxmox.com (firstgate.proxmox.com [212.224.123.68])
	by lore.proxmox.com (Postfix) with ESMTPS id 4E8BD1FF173
	for <inbox@lore.proxmox.com>; Mon, 10 Feb 2025 16:38:13 +0100 (CET)
Received: from firstgate.proxmox.com (localhost [127.0.0.1])
	by firstgate.proxmox.com (Proxmox) with ESMTP id 9DDE7117CB;
	Mon, 10 Feb 2025 16:37:59 +0100 (CET)
From: Filip Schauer <f.schauer@proxmox.com>
To: pve-devel@lists.proxmox.com
Date: Mon, 10 Feb 2025 16:37:28 +0100
Message-Id: <20250210153734.103381-6-f.schauer@proxmox.com>
X-Mailer: git-send-email 2.39.5
In-Reply-To: <20250210153734.103381-1-f.schauer@proxmox.com>
References: <20250210153734.103381-1-f.schauer@proxmox.com>
MIME-Version: 1.0
X-SPAM-LEVEL: Spam detection results:  0
 AWL -0.022 Adjusted score from AWL reputation of From: address
 BAYES_00                 -1.9 Bayes spam probability is 0 to 1%
 DMARC_MISSING             0.1 Missing DMARC policy
 KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment
 SPF_HELO_NONE           0.001 SPF: HELO does not publish an SPF Record
 SPF_PASS               -0.001 SPF: sender matches SPF record
Subject: [pve-devel] [PATCH manager v3 05/11] ui: add hardware RNG resource
 mapping
X-BeenThere: pve-devel@lists.proxmox.com
X-Mailman-Version: 2.1.29
Precedence: list
List-Id: Proxmox VE development discussion <pve-devel.lists.proxmox.com>
List-Unsubscribe: <https://lists.proxmox.com/cgi-bin/mailman/options/pve-devel>, 
 <mailto:pve-devel-request@lists.proxmox.com?subject=unsubscribe>
List-Archive: <http://lists.proxmox.com/pipermail/pve-devel/>
List-Post: <mailto:pve-devel@lists.proxmox.com>
List-Help: <mailto:pve-devel-request@lists.proxmox.com?subject=help>
List-Subscribe: <https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel>, 
 <mailto:pve-devel-request@lists.proxmox.com?subject=subscribe>
Reply-To: Proxmox VE development discussion <pve-devel@lists.proxmox.com>
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Errors-To: pve-devel-bounces@lists.proxmox.com
Sender: "pve-devel" <pve-devel-bounces@lists.proxmox.com>

Signed-off-by: Filip Schauer <f.schauer@proxmox.com>
---
 www/manager6/Makefile               |   2 +
 www/manager6/data/PermPathStore.js  |   1 +
 www/manager6/dc/Config.js           |  10 ++
 www/manager6/dc/HWRNGMapView.js     |  76 ++++++++++++++
 www/manager6/window/HWRNGMapEdit.js | 149 ++++++++++++++++++++++++++++
 5 files changed, 238 insertions(+)
 create mode 100644 www/manager6/dc/HWRNGMapView.js
 create mode 100644 www/manager6/window/HWRNGMapEdit.js

diff --git a/www/manager6/Makefile b/www/manager6/Makefile
index c94a5cdf..01a95c7e 100644
--- a/www/manager6/Makefile
+++ b/www/manager6/Makefile
@@ -138,6 +138,7 @@ JSSRC= 							\
 	window/TreeSettingsEdit.js			\
 	window/PCIMapEdit.js				\
 	window/USBMapEdit.js				\
+	window/HWRNGMapEdit.js				\
 	window/GuestImport.js				\
 	ha/Fencing.js					\
 	ha/GroupEdit.js					\
@@ -188,6 +189,7 @@ JSSRC= 							\
 	dc/RealmSyncJob.js				\
 	dc/PCIMapView.js				\
 	dc/USBMapView.js				\
+	dc/HWRNGMapView.js				\
 	lxc/CmdMenu.js					\
 	lxc/Config.js					\
 	lxc/CreateWizard.js				\
diff --git a/www/manager6/data/PermPathStore.js b/www/manager6/data/PermPathStore.js
index 8785a1d7..8212b17d 100644
--- a/www/manager6/data/PermPathStore.js
+++ b/www/manager6/data/PermPathStore.js
@@ -10,6 +10,7 @@ Ext.define('PVE.data.PermPathStore', {
 	{ 'value': '/access/realm' },
 	{ 'value': '/mapping' },
 	{ 'value': '/mapping/notifications' },
+	{ 'value': '/mapping/hwrng' },
 	{ 'value': '/mapping/pci' },
 	{ 'value': '/mapping/usb' },
 	{ 'value': '/nodes' },
diff --git a/www/manager6/dc/Config.js b/www/manager6/dc/Config.js
index 74728c83..3650f290 100644
--- a/www/manager6/dc/Config.js
+++ b/www/manager6/dc/Config.js
@@ -329,6 +329,16 @@ Ext.define('PVE.dc.Config', {
 			    title: gettext('USB Devices'),
 			    flex: 1,
 			},
+			{
+			    xtype: 'splitter',
+			    collapsible: false,
+			    performCollapse: false,
+			},
+			{
+			    xtype: 'pveDcHWRNGMapView',
+			    title: gettext('Hardware RNG Devices'),
+			    flex: 1,
+			},
 		    ],
 		},
 	    );
diff --git a/www/manager6/dc/HWRNGMapView.js b/www/manager6/dc/HWRNGMapView.js
new file mode 100644
index 00000000..27c0d2fc
--- /dev/null
+++ b/www/manager6/dc/HWRNGMapView.js
@@ -0,0 +1,76 @@
+Ext.define('pve-resource-hwrng-tree', {
+    extend: 'Ext.data.Model',
+    idProperty: 'internalId',
+    fields: ['type', 'text', 'path', 'description', 'digest'],
+});
+
+Ext.define('PVE.dc.HWRNGMapView', {
+    extend: 'PVE.tree.ResourceMapTree',
+    alias: 'widget.pveDcHWRNGMapView',
+
+    editWindowClass: 'PVE.window.HWRNGMapEditWindow',
+    baseUrl: '/cluster/mapping/hwrng',
+    mapIconCls: 'pve-itype-icon-die',
+    getStatusCheckUrl: (node) => `/nodes/${node}/hardware/hwrng`,
+    entryIdProperty: 'path',
+
+    checkValidity: function(data, node) {
+	let me = this;
+	let paths = {};
+	data.forEach((entry) => {
+	    paths[entry.path] = entry;
+	});
+	me.getRootNode()?.cascade(function(rec) {
+	    if (rec.data.node !== node || rec.data.type !== 'map') {
+		return;
+	    }
+
+	    let device;
+	    if (rec.data.path) {
+		device = paths[rec.data.path];
+	    }
+
+	    if (!device) {
+		rec.set('valid', false);
+		rec.set(
+		    'errmsg',
+		    Ext.String.format(gettext("Cannot find Hardware RNG device {0}"), rec.data.id),
+		);
+		rec.commit();
+		return;
+	    }
+
+	    rec.set('valid', true);
+	    rec.commit();
+	});
+    },
+
+    store: {
+	sorters: 'text',
+	model: 'pve-resource-hwrng-tree',
+	data: {},
+    },
+
+    columns: [
+	{
+	    xtype: 'treecolumn',
+	    text: gettext('ID/Node/Path'),
+	    dataIndex: 'text',
+	    width: 200,
+	},
+	{
+	    header: gettext('Status'),
+	    dataIndex: 'valid',
+	    flex: 1,
+	    renderer: 'renderStatus',
+	},
+	{
+	    header: gettext('Comment'),
+	    dataIndex: 'description',
+	    renderer: function(value, _meta, record) {
+		return Ext.String.htmlEncode(value ?? record.data.comment);
+	    },
+	    flex: 1,
+	},
+    ],
+});
diff --git a/www/manager6/window/HWRNGMapEdit.js b/www/manager6/window/HWRNGMapEdit.js
new file mode 100644
index 00000000..aef4e2af
--- /dev/null
+++ b/www/manager6/window/HWRNGMapEdit.js
@@ -0,0 +1,149 @@
+Ext.define('PVE.window.HWRNGMapEditWindow', {
+    extend: 'Proxmox.window.Edit',
+    mixins: ['Proxmox.Mixin.CBind'],
+
+    width: 800,
+
+    subject: gettext('Hardware RNG mapping'),
+
+    onlineHelp: 'resource_mapping',
+
+    method: 'POST',
+
+    cbindData: function(initialConfig) {
+	let me = this;
+	me.isCreate = !me.name;
+	me.method = me.isCreate ? 'POST' : 'PUT';
+	me.hideMapping = !!me.entryOnly;
+	me.hideComment = me.name && !me.entryOnly;
+	me.hideNodeSelector = me.nodename || me.entryOnly;
+	me.hideNode = !me.nodename || !me.hideNodeSelector;
+	return {
+	    name: me.name,
+	    nodename: me.nodename,
+	};
+    },
+
+    submitUrl: function(_url, data) {
+	let me = this;
+	let name = me.isCreate ? '' : me.name;
+	return `/cluster/mapping/hwrng/${name}`;
+    },
+
+    controller: {
+	xclass: 'Ext.app.ViewController',
+
+	onGetValues: function(values) {
+	    let me = this;
+	    let view = me.getView();
+	    values.node ??= view.nodename;
+
+	    let name = values.name;
+	    let description = values.description;
+	    delete values.description;
+	    delete values.name;
+	    values.path = '/dev/hwrng';
+
+	    let map = [];
+	    if (me.originalMap) {
+		map = PVE.Parser.filterPropertyStringList(me.originalMap, (e) => e.node !== values.node);
+	    }
+	    if (view.isCreate) {
+		map.push(PVE.Parser.printPropertyString(values));
+	    }
+
+	    values = { map };
+	    if (description) {
+		values.description = description;
+	    }
+
+	    if (view.isCreate) {
+		values.id = name;
+	    }
+
+	    return values;
+	},
+
+	onSetValues: function(values) {
+	    let me = this;
+	    let view = me.getView();
+	    me.originalMap = [...values.map];
+	    let configuredNodes = [];
+	    PVE.Parser.filterPropertyStringList(values.map, (e) => {
+		configuredNodes.push(e.node);
+		if (e.node === view.nodename) {
+		    values = e;
+		}
+		return false;
+	    });
+
+	    me.lookup('nodeselector').disallowedNodes = configuredNodes;
+
+	    return values;
+	},
+    },
+
+    items: [
+	{
+	    xtype: 'inputpanel',
+	    onGetValues: function(values) {
+		return this.up('window').getController().onGetValues(values);
+	    },
+
+	    onSetValues: function(values) {
+		return this.up('window').getController().onSetValues(values);
+	    },
+
+	    column1: [
+		{
+		    xtype: 'pmxDisplayEditField',
+		    fieldLabel: gettext('Name'),
+		    cbind: {
+			editable: '{!name}',
+			value: '{name}',
+			submitValue: '{isCreate}',
+		    },
+		    name: 'name',
+		    allowBlank: false,
+		},
+		{
+		    xtype: 'displayfield',
+		    fieldLabel: gettext('Mapping on Node'),
+		    labelWidth: 120,
+		    name: 'node',
+		    cbind: {
+			value: '{nodename}',
+			disabled: '{hideNode}',
+			hidden: '{hideNode}',
+		    },
+		    allowBlank: false,
+		},
+		{
+		    xtype: 'pveNodeSelector',
+		    reference: 'nodeselector',
+		    fieldLabel: gettext('Mapping on Node'),
+		    labelWidth: 120,
+		    name: 'node',
+		    cbind: {
+			disabled: '{hideNodeSelector}',
+			hidden: '{hideNodeSelector}',
+		    },
+		    allowBlank: false,
+		},
+	    ],
+
+	    columnB: [
+		{
+		    xtype: 'proxmoxtextfield',
+		    fieldLabel: gettext('Comment'),
+		    submitValue: true,
+		    name: 'description',
+		    cbind: {
+			disabled: '{hideComment}',
+			hidden: '{hideComment}',
+		    },
+		},
+	    ],
+	},
+    ],
+});
-- 
2.39.5



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