]> git.proxmox.com Git - pve-manager.git/commitdiff
ui: qemu: increase available usb ports depending on machine and ostype
authorDominik Csapak <d.csapak@proxmox.com>
Thu, 10 Nov 2022 14:36:00 +0000 (15:36 +0100)
committerThomas Lamprecht <t.lamprecht@proxmox.com>
Thu, 10 Nov 2022 16:06:41 +0000 (17:06 +0100)
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>
www/manager6/Utils.js
www/manager6/qemu/HardwareView.js
www/manager6/qemu/USBEdit.js

index 7ca6a271bfe1a1e66b653da4d5770db7ca1f69e8..adcf082ffdf6a60242d8bf84def5119c373c2f7b 100644 (file)
@@ -1569,7 +1569,58 @@ Ext.define('PVE.Utils', {
        }
     },
 
-    hardware_counts: { net: 32, usb: 5, hostpci: 16, audio: 1, efidisk: 1, serial: 4, rng: 1, tpmstate: 1 },
+    hardware_counts: {
+       net: 32,
+       usb: 14,
+       usb_old: 5,
+       hostpci: 16,
+       audio: 1,
+       efidisk: 1,
+       serial: 4,
+       rng: 1,
+       tpmstate: 1,
+    },
+
+    // we can have usb6 and up only for specific machine/ostypes
+    get_max_usb_count: function(ostype, machine) {
+       if (!ostype) {
+           return PVE.Utils.hardware_counts.usb_old;
+       }
+
+       let match = /-(\d+).(\d+)/.exec(machine ?? '');
+       if (!match || PVE.Utils.qemu_min_version([match[1], match[2]], [7, 1])) {
+           if (ostype === 'l26') {
+               return PVE.Utils.hardware_counts.usb;
+           }
+           let os_match = /^win(\d+)$/.exec(ostype);
+           if (os_match && os_match[1] > 7) {
+               return PVE.Utils.hardware_counts.usb;
+           }
+       }
+
+       return PVE.Utils.hardware_counts.usb_old;
+    },
+
+    // parameters are expected to be arrays, e.g. [7,1], [4,0,1]
+    // returns true if toCheck is equal or greater than minVersion
+    qemu_min_version: function(toCheck, minVersion) {
+       let i;
+       for (i = 0; i < toCheck.length && i < minVersion.length; i++) {
+           if (toCheck[i] < minVersion[i]) {
+               return false;
+           }
+       }
+
+       if (minVersion.length > toCheck.length) {
+           for (; i < minVersion.length; i++) {
+               if (minVersion[i] !== 0) {
+                   return false;
+               }
+           }
+       }
+
+       return true;
+    },
 
     cleanEmptyObjectKeys: function(obj) {
        for (const propName of Object.keys(obj)) {
index 6e9d03b4a36867defbe2dd1c606c3979d67e8dcc..96fd37e98ca7e1c3c2a782c4dcab7587f4e13a19 100644 (file)
@@ -544,6 +544,11 @@ Ext.define('PVE.qemu.HardwareView', {
 
        let counts = {};
        let isAtLimit = (type) => counts[type] >= PVE.Utils.hardware_counts[type];
+       let isAtUsbLimit = () => {
+           let ostype = me.getObjectValue('ostype');
+           let machine = me.getObjectValue('machine');
+           return counts.usb >= PVE.Utils.get_max_usb_count(ostype, machine);
+       };
 
        let set_button_status = function() {
            let selection_model = me.getSelectionModel();
@@ -570,7 +575,7 @@ Ext.define('PVE.qemu.HardwareView', {
            const noVMConfigNetPerm = !caps.vms['VM.Config.Network'];
            const noVMConfigDiskPerm = !caps.vms['VM.Config.Disk'];
 
-           me.down('#addUsb').setDisabled(noSysConsolePerm || isAtLimit('usb'));
+           me.down('#addUsb').setDisabled(noSysConsolePerm || isAtUsbLimit());
            me.down('#addPci').setDisabled(noSysConsolePerm || isAtLimit('hostpci'));
            me.down('#addAudio').setDisabled(noVMConfigHWTypePerm || isAtLimit('audio'));
            me.down('#addSerial').setDisabled(noVMConfigHWTypePerm || isAtLimit('serial'));
index 4373f82c3511b8c606240b7341ef5e1312f2903f..fe51d186f1948e7f353abb657ac3459e16ff47df 100644 (file)
@@ -12,12 +12,17 @@ Ext.define('PVE.qemu.USBInputPanel', {
     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) {
-           for (let i = 0; i < PVE.Utils.hardware_counts.usb; i++) {
+           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;