[pve-devel] [PATCH manager v2 6/9] ui: allow use of mapped hardware RNGs as entropy sources for VMs
Filip Schauer
f.schauer at proxmox.com
Wed Jan 29 16:53:36 CET 2025
Signed-off-by: Filip Schauer <f.schauer at 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
More information about the pve-devel
mailing list