ui: add support for adding TPM devices

Inspired by HDEfi for efidisks. Extends the DiskStorageSelector to allow
hiding the format, since tpmstate can only be stored in 'raw' format
(even on directory storages).

Signed-off-by: Stefan Reiter <s.reiter@proxmox.com>
This commit is contained in:
Stefan Reiter 2021-10-04 17:29:21 +02:00 committed by Thomas Lamprecht
parent ef05a786d5
commit be63fc17fc
6 changed files with 119 additions and 3 deletions

View File

@ -205,6 +205,7 @@ JSSRC= \
qemu/DisplayEdit.js \
qemu/HDEdit.js \
qemu/HDEfi.js \
qemu/HDTPM.js \
qemu/HDMove.js \
qemu/HDResize.js \
qemu/HardwareView.js \

View File

@ -1602,7 +1602,7 @@ Ext.define('PVE.Utils', {
}
},
hardware_counts: { net: 32, usb: 5, hostpci: 16, audio: 1, efidisk: 1, serial: 4, rng: 1 },
hardware_counts: { net: 32, usb: 5, hostpci: 16, audio: 1, efidisk: 1, serial: 4, rng: 1, tpmstate: 1 },
cleanEmptyObjectKeys: function(obj) {
for (const propName of Object.keys(obj)) {

View File

@ -28,6 +28,9 @@ Ext.define('PVE.form.DiskStorageSelector', {
// hides the size field (e.g, for the efi disk dialog)
hideSize: false,
// hides the format field (e.g. for TPM state), always assumes 'raw'
hideFormat: false,
// sets the initial size value
// string because else we get a type confusion
defaultSize: '32',
@ -155,7 +158,7 @@ Ext.define('PVE.form.DiskStorageSelector', {
fieldLabel: gettext('Format'),
nodename: me.nodename,
disabled: true,
hidden: me.storageContent === 'rootdir',
hidden: me.hideFormat || me.storageContent === 'rootdir',
value: 'qcow2',
allowBlank: false,
},

View File

@ -75,6 +75,7 @@ Ext.define('PVE.window.HDMove', {
nodename: me.nodename,
storageContent: qemu ? 'images' : 'rootdir',
hideSize: true,
hideFormat: me.disk === 'tpmstate0',
});
items.push({

View File

@ -0,0 +1,88 @@
Ext.define('PVE.qemu.TPMDiskInputPanel', {
extend: 'Proxmox.panel.InputPanel',
alias: 'widget.pveTPMDiskInputPanel',
unused: false,
vmconfig: {},
onGetValues: function(values) {
var me = this;
var confid = 'tpmstate0';
if (values.hdimage) {
me.drive.file = values.hdimage;
} else {
// size is constant, so just use 1
me.drive.file = values.hdstorage + ":1";
}
me.drive.version = values.version;
var params = {};
params[confid] = PVE.Parser.printQemuDrive(me.drive);
return params;
},
setNodename: function(nodename) {
var me = this;
me.down('#hdstorage').setNodename(nodename);
me.down('#hdimage').setStorage(undefined, nodename);
},
initComponent: function() {
var me = this;
me.drive = {};
me.items = [
{
xtype: 'pveDiskStorageSelector',
name: me.disktype + '0',
storageContent: 'images',
nodename: me.nodename,
hideSize: true,
hideFormat: true,
},
{
xtype: 'proxmoxKVComboBox',
name: 'version',
value: 'v2.0',
deleteEmpty: false,
fieldLabel: gettext('Version'),
comboItems: [
['v1.2', 'v1.2'],
['v2.0', 'v2.0'],
],
},
];
me.callParent();
},
});
Ext.define('PVE.qemu.TPMDiskEdit', {
extend: 'Proxmox.window.Edit',
isAdd: true,
subject: gettext('TPM State'),
width: 450,
initComponent: function() {
var me = this;
var nodename = me.pveSelNode.data.node;
if (!nodename) {
throw "no node name specified";
}
me.items = [{
xtype: 'pveTPMDiskInputPanel',
//onlineHelp: 'qm_tpm', FIXME: add once available
confid: me.confid,
nodename: nodename,
isCreate: true,
}];
me.callParent();
},
});

View File

@ -245,6 +245,13 @@ Ext.define('PVE.qemu.HardwareView', {
never_delete: !caps.vms['VM.Config.Disk'],
header: gettext('EFI Disk'),
};
rows.tpmstate0 = {
group: 22,
iconCls: 'hdd-o',
editor: null,
never_delete: !caps.vms['VM.Config.Disk'],
header: gettext('TPM State'),
};
for (let i = 0; i < PVE.Utils.hardware_counts.usb; i++) {
let confid = "usb" + i.toString();
rows[confid] = {
@ -564,6 +571,7 @@ Ext.define('PVE.qemu.HardwareView', {
me.down('#addnet').setDisabled(noVMConfigNetPerm || isAtLimit('net'));
me.down('#addrng').setDisabled(noSysConsolePerm || isAtLimit('rng'));
efidisk_menuitem.setDisabled(noVMConfigDiskPerm || isAtLimit('efidisk'));
me.down('#addtpmstate').setDisabled(noSysConsolePerm || isAtLimit('tpmstate'));
me.down('#addci').setDisabled(noSysConsolePerm || hasCloudInit);
if (!rec) {
@ -588,6 +596,7 @@ Ext.define('PVE.qemu.HardwareView', {
const isUsedDisk = !isUnusedDisk && row.isOnStorageBus && !isCDRom && !isCloudInit;
const isDisk = isCloudInit || isUnusedDisk || isUsedDisk;
const isEfi = key === 'efidisk0';
const tpmMoveable = key === 'tpmstate0' && !me.pveSelNode.data.running;
remove_btn.setDisabled(
deleted ||
@ -608,7 +617,7 @@ Ext.define('PVE.qemu.HardwareView', {
resize_btn.setDisabled(pending || !isUsedDisk || !diskCap);
move_btn.setDisabled(pending || !(isUsedDisk || isEfi) || !diskCap);
move_btn.setDisabled(pending || !(isUsedDisk || isEfi || tpmMoveable) || !diskCap);
revert_btn.setDisabled(!pending);
};
@ -666,6 +675,20 @@ Ext.define('PVE.qemu.HardwareView', {
},
},
efidisk_menuitem,
{
text: gettext('TPM State'),
itemId: 'addtpmstate',
iconCls: 'fa fa-fw fa-hdd-o black',
disabled: !caps.vms['VM.Config.Disk'],
handler: function() {
var win = Ext.create('PVE.qemu.TPMDiskEdit', {
url: '/api2/extjs/' + baseurl,
pveSelNode: me.pveSelNode,
});
win.on('destroy', me.reload, me);
win.show();
},
},
{
text: gettext('USB Device'),
itemId: 'addusb',