[pve-devel] [PATCH manager 2/5] qemu: add virtio-rng option to GUI

Stefan Reiter s.reiter at proxmox.com
Thu Feb 20 18:10:42 CET 2020


Warn the user when selecting /dev/random or disabling speed limits.

'hardware_counts' is used since technically more than one RNG could be
attached to a QEMU machine. It is limited to 1 however, since the
usefulness of such a setup is more than questionable, considering the
linux kernel only ever uses one hwrng at a time anyway.

Signed-off-by: Stefan Reiter <s.reiter at proxmox.com>
---
 www/manager6/Makefile             |   1 +
 www/manager6/Utils.js             |   2 +-
 www/manager6/qemu/HardwareView.js |  23 ++++++
 www/manager6/qemu/RNGEdit.js      | 124 ++++++++++++++++++++++++++++++
 4 files changed, 149 insertions(+), 1 deletion(-)
 create mode 100644 www/manager6/qemu/RNGEdit.js

diff --git a/www/manager6/Makefile b/www/manager6/Makefile
index eb7ac004..41615430 100644
--- a/www/manager6/Makefile
+++ b/www/manager6/Makefile
@@ -160,6 +160,7 @@ JSSRC= 				                 	\
 	qemu/IPConfigEdit.js				\
 	qemu/SystemEdit.js				\
 	qemu/AudioEdit.js				\
+	qemu/RNGEdit.js					\
 	lxc/Network.js					\
 	lxc/Resources.js				\
 	lxc/FeaturesEdit.js				\
diff --git a/www/manager6/Utils.js b/www/manager6/Utils.js
index 68edc275..0d4bbad8 100644
--- a/www/manager6/Utils.js
+++ b/www/manager6/Utils.js
@@ -1215,7 +1215,7 @@ Ext.define('PVE.Utils', { utilities: {
 	}
     },
 
-    hardware_counts: { net: 32, usb: 5, hostpci: 16, audio: 1, efidisk: 1, serial: 4 },
+    hardware_counts: { net: 32, usb: 5, hostpci: 16, audio: 1, efidisk: 1, serial: 4, rng: 1 },
 
     cleanEmptyObjectKeys: function (obj) {
 	var propName;
diff --git a/www/manager6/qemu/HardwareView.js b/www/manager6/qemu/HardwareView.js
index a78e7dd4..595afd10 100644
--- a/www/manager6/qemu/HardwareView.js
+++ b/www/manager6/qemu/HardwareView.js
@@ -301,6 +301,13 @@ Ext.define('PVE.qemu.HardwareView', {
 		header: gettext('Unused Disk') + ' ' + i.toString()
 	    };
 	}
+	rows.rng0 = {
+	    group: 45,
+	    iconCls: 'cogs',
+	    editor: caps.nodes['Sys.Console'] ? 'PVE.qemu.RNGEdit' : undefined,
+	    never_delete: caps.nodes['Sys.Console'] ? false : true,
+	    header: gettext("VirtIO RNG")
+	};
 
 	var sorterFn = function(rec1, rec2) {
 	    var v1 = rec1.data.key;
@@ -563,6 +570,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'));
 	    efidisk_menuitem.setDisabled(isAtLimit('efidisk'));
 	    me.down('#addci').setDisabled(noSysConsolePerm || hasCloudInit);
 
@@ -723,6 +731,21 @@ Ext.define('PVE.qemu.HardwareView', {
 				    win.on('destroy', me.reload, me);
 				    win.show();
 				}
+			    },
+			    {
+				text: gettext("VirtIO RNG"),
+				itemId: 'addrng',
+				iconCls: 'fa fa-fw fa-cogs black',
+				disabled: !caps.nodes['Sys.Console'],
+				handler: function() {
+				    var win = Ext.create('PVE.qemu.RNGEdit', {
+					url: '/api2/extjs/' + baseurl,
+					isCreate: true,
+					isAdd: true
+				    });
+				    win.on('destroy', me.reload, me);
+				    win.show();
+				}
 			    }
 			]
 		    })
diff --git a/www/manager6/qemu/RNGEdit.js b/www/manager6/qemu/RNGEdit.js
new file mode 100644
index 00000000..f112eb1f
--- /dev/null
+++ b/www/manager6/qemu/RNGEdit.js
@@ -0,0 +1,124 @@
+Ext.define('PVE.qemu.RNGInputPanel', {
+    extend: 'Proxmox.panel.InputPanel',
+    xtype: 'pveRNGInputPanel',
+
+    // FIXME: enable once we bumped doc-gen so this ref is included
+    //onlineHelp: 'qm_virtio_rng',
+
+    onGetValues: function(values) {
+	if (values.max_bytes === "") {
+	    values.max_bytes = "0";
+	} else if (values.max_bytes === "1024" && values.period === "") {
+	    delete values.max_bytes;
+	}
+
+	var ret = PVE.Parser.printPropertyString(values);
+
+	return {
+	    rng0: ret
+	};
+    },
+
+    setValues: function(values) {
+	if (values.max_bytes == 0) {
+	    values.max_bytes = null;
+	}
+
+	this.callParent(arguments);
+    },
+
+    controller: {
+	xclass: 'Ext.app.ViewController',
+	control: {
+	    '#max_bytes': {
+		change: function(el, newVal) {
+		    let limitWarning = this.lookupReference('limitWarning');
+		    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: 'numberfield',
+	itemId: 'max_bytes',
+	name: 'max_bytes',
+	minValue: 0,
+	step: 1,
+	value: 1024,
+	fieldLabel: gettext('Limit (Bytes/Period)'),
+	labelWidth: 130,
+	emptyText: gettext('unlimited')
+    },
+    {
+	xtype: 'numberfield',
+	name: 'period',
+	minValue: 1,
+	step: 1,
+	fieldLabel: gettext('Period') + ' (ms)',
+	labelWidth: 130,
+	emptyText: gettext('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',
+	value: gettext('Disabling the limiter can potentially allow a guest to overload the host. Proceed with caution.'),
+	userCls: 'pmx-hint',
+	hidden: true
+    }]
+});
+
+Ext.define('PVE.qemu.RNGEdit', {
+    extend: 'Proxmox.window.Edit',
+
+    subject: gettext('VirtIO RNG'),
+
+    items: [{
+	xtype: 'pveRNGInputPanel'
+    }],
+
+    initComponent : function() {
+	var me = this;
+
+	me.callParent();
+
+	if (!me.isCreate) {
+	    me.load({
+		success: function(response) {
+		    me.vmconfig = response.result.data;
+
+		    var rng0 = me.vmconfig.rng0;
+		    if (rng0) {
+			me.setValues(PVE.Parser.parsePropertyString(rng0));
+		    }
+		}
+	    });
+	}
+    }
+});
-- 
2.20.1





More information about the pve-devel mailing list