pve-manager/www/manager6/qemu/USBEdit.js
Dominik Csapak 17dcba38dd ui: qemu: increase available usb ports depending on machine and ostype
in the backend, we allow up to 14 usb ports, but only if the vm can
use the qemu-xhci controller which is only possible since machine
version 7.1 and if the ostype is l26 or windows > 7

for this we introduce two helpers:
* qemu_min_version: modeled after the signature of 'min_version' from
  qemu-server, expects two arrays of versions and returns true if
  the first parameter is equal or greater than the second version
* get_max_usb_count looks at the given ostype and machine string
  and returns the proper maximum number

since we don't currently have the actual running version of the vm in
the gui, this is only a heuristic for running vms. but since the actual
running version could only be lower if none is set (e.g. for
migrated/long-running vms) we allow more in the gui and the backend will
do the proper thing (either hotplug it, or make it a pending change)

Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
2022-11-10 17:06:41 +01:00

183 lines
3.8 KiB
JavaScript

Ext.define('PVE.qemu.USBInputPanel', {
extend: 'Proxmox.panel.InputPanel',
mixins: ['Proxmox.Mixin.CBind'],
autoComplete: false,
onlineHelp: 'qm_usb_passthrough',
viewModel: {
data: {},
},
setVMConfig: function(vmconfig) {
var me = this;
me.vmconfig = vmconfig;
let max_usb = PVE.Utils.get_max_usb_count(me.vmconfig.ostype, me.vmconfig.machine);
if (max_usb > PVE.Utils.hardware_counts.usb_old) {
me.down('field[name=usb3]').setDisabled(true);
}
},
onGetValues: function(values) {
var me = this;
if (!me.confid) {
let max_usb = PVE.Utils.get_max_usb_count(me.vmconfig.ostype, me.vmconfig.machine);
for (let i = 0; i < max_usb; i++) {
let id = 'usb' + i.toString();
if (!me.vmconfig[id]) {
me.confid = id;
break;
}
}
}
var val = "";
var type = me.down('radiofield').getGroupValue();
switch (type) {
case 'spice':
val = 'spice';
break;
case 'hostdevice':
case 'port':
val = 'host=' + values[type];
delete values[type];
break;
default:
throw "invalid type selected";
}
if (values.usb3) {
delete values.usb3;
val += ',usb3=1';
}
values[me.confid] = val;
return values;
},
items: [
{
xtype: 'fieldcontainer',
defaultType: 'radiofield',
layout: 'fit',
items: [
{
name: 'usb',
inputValue: 'spice',
boxLabel: gettext('Spice Port'),
submitValue: false,
checked: true,
},
{
name: 'usb',
inputValue: 'hostdevice',
boxLabel: gettext('Use USB Vendor/Device ID'),
reference: 'hostdevice',
submitValue: false,
},
{
xtype: 'pveUSBSelector',
disabled: true,
type: 'device',
name: 'hostdevice',
cbind: { pveSelNode: '{pveSelNode}' },
bind: { disabled: '{!hostdevice.checked}' },
editable: true,
allowBlank: false,
fieldLabel: gettext('Choose Device'),
labelAlign: 'right',
},
{
name: 'usb',
inputValue: 'port',
boxLabel: gettext('Use USB Port'),
reference: 'port',
submitValue: false,
},
{
xtype: 'pveUSBSelector',
disabled: true,
name: 'port',
cbind: { pveSelNode: '{pveSelNode}' },
bind: { disabled: '{!port.checked}' },
editable: true,
type: 'port',
allowBlank: false,
fieldLabel: gettext('Choose Port'),
labelAlign: 'right',
},
{
xtype: 'checkbox',
name: 'usb3',
inputValue: true,
checked: true,
reference: 'usb3',
fieldLabel: gettext('Use USB3'),
},
],
},
],
});
Ext.define('PVE.qemu.USBEdit', {
extend: 'Proxmox.window.Edit',
vmconfig: undefined,
isAdd: true,
width: 400,
subject: gettext('USB Device'),
initComponent: function() {
var me = this;
me.isCreate = !me.confid;
var ipanel = Ext.create('PVE.qemu.USBInputPanel', {
confid: me.confid,
pveSelNode: me.pveSelNode,
});
Ext.apply(me, {
items: [ipanel],
});
me.callParent();
me.load({
success: function(response, options) {
ipanel.setVMConfig(response.result.data);
if (me.isCreate) {
return;
}
var data = response.result.data[me.confid].split(',');
var port, hostdevice, usb3 = false;
var type = 'spice';
for (let i = 0; i < data.length; i++) {
if (/^(host=)?(0x)?[a-zA-Z0-9]{4}:(0x)?[a-zA-Z0-9]{4}$/.test(data[i])) {
hostdevice = data[i];
hostdevice = hostdevice.replace('host=', '').replace('0x', '');
type = 'hostdevice';
} else if (/^(host=)?(\d+)-(\d+(\.\d+)*)$/.test(data[i])) {
port = data[i];
port = port.replace('host=', '');
type = 'port';
}
if (/^usb3=(1|on|true)$/.test(data[i])) {
usb3 = true;
}
}
var values = {
usb: type,
hostdevice: hostdevice,
port: port,
usb3: usb3,
};
ipanel.setValues(values);
},
});
},
});