Signed-off-by: Filip Schauer <f.scha...@proxmox.com> --- www/manager6/Makefile | 1 + www/manager6/form/HWRNGMapSelector.js | 99 +++++++++++++++++++++++++++ www/manager6/qemu/HardwareView.js | 9 ++- www/manager6/qemu/RNGEdit.js | 79 ++++++++++++++------- 4 files changed, 159 insertions(+), 29 deletions(-) create mode 100644 www/manager6/form/HWRNGMapSelector.js
diff --git a/www/manager6/Makefile b/www/manager6/Makefile index 01a95c7e..d148a1c9 100644 --- a/www/manager6/Makefile +++ b/www/manager6/Makefile @@ -44,6 +44,7 @@ JSSRC= \ form/GuestIDSelector.js \ form/HashAlgorithmSelector.js \ form/HotplugFeatureSelector.js \ + form/HWRNGMapSelector.js \ form/IPProtocolSelector.js \ form/IPRefSelector.js \ form/MDevSelector.js \ diff --git a/www/manager6/form/HWRNGMapSelector.js b/www/manager6/form/HWRNGMapSelector.js new file mode 100644 index 00000000..1c795d2d --- /dev/null +++ b/www/manager6/form/HWRNGMapSelector.js @@ -0,0 +1,99 @@ +Ext.define('PVE.form.HWRNGMapSelector', { + extend: 'Proxmox.form.ComboGrid', + alias: 'widget.pveHWRNGMapSelector', + + store: { + fields: ['name', 'path'], + filterOnLoad: true, + sorters: [ + { + property: 'name', + direction: 'ASC', + }, + ], + }, + + allowBlank: false, + autoSelect: false, + displayField: 'id', + valueField: 'id', + + listConfig: { + width: 800, + columns: [ + { + header: gettext('Name'), + dataIndex: 'id', + flex: 1, + }, + { + header: gettext('Status'), + dataIndex: 'errors', + flex: 2, + renderer: function(value) { + let me = this; + + if (!Ext.isArray(value) || !value?.length) { + return `<i class="fa fa-check-circle good"></i> ${gettext('Mapping matches host data')}`; + } + + let errors = []; + + value.forEach((error) => { + let iconCls; + switch (error?.severity) { + case 'warning': + iconCls = 'fa-exclamation-circle warning'; + break; + case 'error': + iconCls = 'fa-times-circle critical'; + break; + } + + let message = error?.message; + let icon = `<i class="fa ${iconCls}"></i>`; + if (iconCls !== undefined) { + errors.push(`${icon} ${message}`); + } + }); + + return errors.join('<br>'); + }, + }, + { + header: gettext('Comment'), + dataIndex: 'description', + flex: 1, + renderer: Ext.String.htmlEncode, + }, + ], + }, + + setNodename: function(nodename) { + var me = this; + + if (!nodename || me.nodename === nodename) { + return; + } + + me.nodename = nodename; + + me.store.setProxy({ + type: 'proxmox', + url: `/api2/json/cluster/mapping/hwrng?check-node=${nodename}`, + }); + + me.store.load(); + }, + + initComponent: function() { + var me = this; + + var nodename = me.nodename; + me.nodename = undefined; + + me.callParent(); + + me.setNodename(nodename); + }, +}); diff --git a/www/manager6/qemu/HardwareView.js b/www/manager6/qemu/HardwareView.js index c6d193fc..8085e288 100644 --- a/www/manager6/qemu/HardwareView.js +++ b/www/manager6/qemu/HardwareView.js @@ -315,8 +315,8 @@ Ext.define('PVE.qemu.HardwareView', { rows.rng0 = { group: 45, tdCls: 'pve-itype-icon-die', - editor: caps.nodes['Sys.Console'] ? 'PVE.qemu.RNGEdit' : undefined, - never_delete: !caps.nodes['Sys.Console'], + editor: caps.vms['VM.Config.HWType'] || caps.mapping['Mapping.Use'] ? 'PVE.qemu.RNGEdit' : undefined, + never_delete: !caps.vms['VM.Config.HWType'] && !caps.mapping['Mapping.Use'], header: gettext("VirtIO RNG"), }; @@ -588,7 +588,6 @@ Ext.define('PVE.qemu.HardwareView', { }); // heuristic only for disabling some stuff, the backend has the final word. - const noSysConsolePerm = !caps.nodes['Sys.Console']; const noHWPerm = !caps.nodes['Sys.Console'] && !caps.mapping['Mapping.Use']; const noVMConfigHWTypePerm = !caps.vms['VM.Config.HWType']; const noVMConfigNetPerm = !caps.vms['VM.Config.Network']; @@ -601,7 +600,7 @@ Ext.define('PVE.qemu.HardwareView', { me.down('#addAudio').setDisabled(noVMConfigHWTypePerm || isAtLimit('audio')); me.down('#addSerial').setDisabled(noVMConfigHWTypePerm || isAtLimit('serial')); me.down('#addNet').setDisabled(noVMConfigNetPerm || isAtLimit('net')); - me.down('#addRng').setDisabled(noSysConsolePerm || isAtLimit('rng')); + me.down('#addRng').setDisabled(noVMConfigHWTypePerm || isAtLimit('rng')); efidisk_menuitem.setDisabled(noVMConfigDiskPerm || isAtLimit('efidisk')); me.down('#addTpmState').setDisabled(noVMConfigDiskPerm || isAtLimit('tpmstate')); me.down('#addCloudinitDrive').setDisabled(noVMConfigCDROMPerm || noVMConfigCloudinitPerm || hasCloudInit); @@ -745,7 +744,7 @@ Ext.define('PVE.qemu.HardwareView', { text: gettext("VirtIO RNG"), itemId: 'addRng', iconCls: 'pve-itype-icon-die', - disabled: !caps.nodes['Sys.Console'], + disabled: !caps.vms['VM.Config.HWType'] && !caps.mapping['Mapping.Use'], handler: editorFactory('RNGEdit'), }, ], diff --git a/www/manager6/qemu/RNGEdit.js b/www/manager6/qemu/RNGEdit.js index e34e2c08..fab8c1b0 100644 --- a/www/manager6/qemu/RNGEdit.js +++ b/www/manager6/qemu/RNGEdit.js @@ -1,9 +1,19 @@ Ext.define('PVE.qemu.RNGInputPanel', { extend: 'Proxmox.panel.InputPanel', xtype: 'pveRNGInputPanel', + mixins: ['Proxmox.Mixin.CBind'], onlineHelp: 'qm_virtio_rng', + cbindData: function(initialConfig) { + let me = this; + if (!me.pveSelNode) { + throw "no pveSelNode given"; + } + + return { nodename: me.pveSelNode.data.node }; + }, + onGetValues: function(values) { if (values.max_bytes === "") { values.max_bytes = "0"; @@ -23,6 +33,10 @@ Ext.define('PVE.qemu.RNGInputPanel', { values.max_bytes = null; } + if (values.mapping) { + values.source = 'mapped'; + } + this.callParent(arguments); }, @@ -35,27 +49,49 @@ Ext.define('PVE.qemu.RNGInputPanel', { limitWarning.setHidden(!!newVal); }, }, - '#source': { - change: function(el, newVal) { - let limitWarning = this.lookupReference('sourceWarning'); - limitWarning.setHidden(newVal !== '/dev/random'); - }, - }, }, }, items: [{ - itemId: 'source', - name: 'source', - xtype: 'proxmoxKVComboBox', - value: '/dev/urandom', - fieldLabel: gettext('Entropy source'), - labelWidth: 130, - comboItems: [ - ['/dev/urandom', '/dev/urandom'], - ['/dev/random', '/dev/random'], - ['/dev/hwrng', '/dev/hwrng'], - ], + xtype: 'fieldcontainer', + defaultType: 'radiofield', + layout: 'fit', + items: [{ + name: 'source', + inputValue: '/dev/urandom', + boxLabel: '/dev/urandom', + checked: true, + }, + { + name: 'source', + inputValue: '/dev/random', + boxLabel: '/dev/random', + }, + { + name: 'source', + inputValue: 'mapped', + boxLabel: gettext('Use mapped Hardware RNG device'), + reference: 'mapped', + submitValue: false, + listeners: { + change: function(f, value) { + let me = this; + if (!me.rendered) { + return; + } + me.up().down('field[name=mapping]').setDisabled(!value); + }, + }, + }, + { + xtype: 'pveHWRNGMapSelector', + name: 'mapping', + cbind: { nodename: '{nodename}' }, + allowBlank: false, + fieldLabel: gettext('Choose Device'), + labelAlign: 'right', + disabled: true, + }], }, { xtype: 'numberfield', @@ -77,13 +113,6 @@ Ext.define('PVE.qemu.RNGInputPanel', { labelWidth: 130, emptyText: '1000', }, - { - xtype: 'displayfield', - reference: 'sourceWarning', - value: gettext('Using /dev/random as entropy source is discouraged, as it can lead to host entropy starvation. /dev/urandom is preferred, and does not lead to a decrease in security in practice.'), - userCls: 'pmx-hint', - hidden: true, - }, { xtype: 'displayfield', reference: 'limitWarning', @@ -95,11 +124,13 @@ Ext.define('PVE.qemu.RNGInputPanel', { Ext.define('PVE.qemu.RNGEdit', { extend: 'Proxmox.window.Edit', + mixins: ['Proxmox.Mixin.CBind'], subject: gettext('VirtIO RNG'), items: [{ xtype: 'pveRNGInputPanel', + cbind: { pveSelNode: '{pveSelNode}' }, }], initComponent: function() { -- 2.39.5 _______________________________________________ pve-devel mailing list pve-devel@lists.proxmox.com https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel