Signed-off-by: Filip Schauer <f.scha...@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