all lists on lists.proxmox.com
 help / color / mirror / Atom feed
* [pve-devel] [PATCH v2 qemu-server 01/10] introduce DriveDevice module
       [not found] <20250716163415.1837210-1-alexandre.derumier@groupe-cyllene.com>
@ 2025-07-16 16:34 ` Alexandre Derumier via pve-devel
  2025-07-16 16:34 ` [pve-devel] [PATCH v2 qemu-server 02/10] add print_drivedevice_controller && print_drivedevice_iothread Alexandre Derumier via pve-devel
                   ` (8 subsequent siblings)
  9 siblings, 0 replies; 10+ messages in thread
From: Alexandre Derumier via pve-devel @ 2025-07-16 16:34 UTC (permalink / raw)
  To: pve-devel; +Cc: Alexandre Derumier

[-- Attachment #1: Type: message/rfc822, Size: 16740 bytes --]

From: Alexandre Derumier <alexandre.derumier@groupe-cyllene.com>
To: pve-devel@lists.proxmox.com
Subject: [PATCH v2 qemu-server 01/10] introduce DriveDevice module
Date: Wed, 16 Jul 2025 18:34:06 +0200
Message-ID: <20250716163415.1837210-2-alexandre.derumier@groupe-cyllene.com>

and move print_drivedevice_full

Signed-off-by: Alexandre Derumier <alexandre.derumier@groupe-cyllene.com>
---
 src/PVE/QemuServer.pm             | 144 +-------------------------
 src/PVE/QemuServer/DriveDevice.pm | 164 ++++++++++++++++++++++++++++++
 src/PVE/QemuServer/Makefile       |   1 +
 3 files changed, 166 insertions(+), 143 deletions(-)
 create mode 100644 src/PVE/QemuServer/DriveDevice.pm

diff --git a/src/PVE/QemuServer.pm b/src/PVE/QemuServer.pm
index ec554c4a..4c60cba9 100644
--- a/src/PVE/QemuServer.pm
+++ b/src/PVE/QemuServer.pm
@@ -72,6 +72,7 @@ use PVE::QemuServer::Drive qw(
     print_drive
     storage_allows_io_uring_default
 );
+use PVE::QemuServer::DriveDevice qw(print_drivedevice_full scsihw_infos);
 use PVE::QemuServer::Machine;
 use PVE::QemuServer::Memory qw(get_current_memory);
 use PVE::QemuServer::MetaInfo;
@@ -1196,127 +1197,6 @@ sub print_keyboarddevice_full {
     return "usb-kbd,id=keyboard,bus=ehci.0,port=2";
 }
 
-sub print_drivedevice_full {
-    my ($storecfg, $conf, $vmid, $drive, $bridges, $arch, $machine_type) = @_;
-
-    my $device = '';
-    my $maxdev = 0;
-
-    my $machine_version = extract_version($machine_type, kvm_user_version());
-
-    my $drive_id = PVE::QemuServer::Drive::get_drive_id($drive);
-    if ($drive->{interface} eq 'virtio') {
-        my $pciaddr = print_pci_addr("$drive_id", $bridges, $arch);
-        $device = 'virtio-blk-pci';
-        # for the switch to -blockdev, there is no blockdev for 'none'
-        if (!min_version($machine_version, 10, 0) || $drive->{file} ne 'none') {
-            $device .= ",drive=drive-$drive_id";
-        }
-        $device .= ",id=${drive_id}${pciaddr}";
-        $device .= ",iothread=iothread-$drive_id" if $drive->{iothread};
-    } elsif ($drive->{interface} eq 'scsi') {
-
-        my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $drive);
-        my $unit = $drive->{index} % $maxdev;
-
-        my $device_type =
-            PVE::QemuServer::Drive::get_scsi_device_type($drive, $storecfg, $machine_version);
-
-        if (!$conf->{scsihw} || $conf->{scsihw} =~ m/^lsi/ || $conf->{scsihw} eq 'pvscsi') {
-            $device = "scsi-$device_type,bus=$controller_prefix$controller.0,scsi-id=$unit";
-        } else {
-            $device = "scsi-$device_type,bus=$controller_prefix$controller.0,channel=0,scsi-id=0"
-                . ",lun=$drive->{index}";
-        }
-        # for the switch to -blockdev, there is no blockdev for 'none'
-        if (!min_version($machine_version, 10, 0) || $drive->{file} ne 'none') {
-            $device .= ",drive=drive-$drive_id";
-        }
-        $device .= ",id=$drive_id";
-
-        if ($drive->{ssd} && ($device_type eq 'block' || $device_type eq 'hd')) {
-            $device .= ",rotation_rate=1";
-        }
-        $device .= ",wwn=$drive->{wwn}" if $drive->{wwn};
-
-        # only scsi-hd and scsi-cd support passing vendor and product information
-        if ($device_type eq 'hd' || $device_type eq 'cd') {
-            if (my $vendor = $drive->{vendor}) {
-                $device .= ",vendor=$vendor";
-            }
-            if (my $product = $drive->{product}) {
-                $device .= ",product=$product";
-            }
-        }
-
-    } elsif ($drive->{interface} eq 'ide' || $drive->{interface} eq 'sata') {
-        my $maxdev = ($drive->{interface} eq 'sata') ? $PVE::QemuServer::Drive::MAX_SATA_DISKS : 2;
-        my $controller = int($drive->{index} / $maxdev);
-        my $unit = $drive->{index} % $maxdev;
-
-        # machine type q35 only supports unit=0 for IDE rather than 2 units. This wasn't handled
-        # correctly before, so e.g. index=2 was mapped to controller=1,unit=0 rather than
-        # controller=2,unit=0. Note that odd indices never worked, as they would be mapped to
-        # unit=1, so to keep backwards compat for migration, it suffices to keep even ones as they
-        # were before. Move odd ones up by 2 where they don't clash.
-        if (PVE::QemuServer::Machine::machine_type_is_q35($conf) && $drive->{interface} eq 'ide') {
-            $controller += 2 * ($unit % 2);
-            $unit = 0;
-        }
-
-        my $device_type = ($drive->{media} && $drive->{media} eq 'cdrom') ? "cd" : "hd";
-
-        $device = "ide-$device_type";
-        if ($drive->{interface} eq 'ide') {
-            $device .= ",bus=ide.$controller,unit=$unit";
-        } else {
-            $device .= ",bus=ahci$controller.$unit";
-        }
-        if (!min_version($machine_version, 10, 0) || $drive->{file} ne 'none') {
-            $device .= ",drive=drive-$drive_id";
-        }
-        $device .= ",id=$drive_id";
-
-        if ($device_type eq 'hd') {
-            if (my $model = $drive->{model}) {
-                $model = URI::Escape::uri_unescape($model);
-                $device .= ",model=$model";
-            }
-            if ($drive->{ssd}) {
-                $device .= ",rotation_rate=1";
-            }
-        }
-        $device .= ",wwn=$drive->{wwn}" if $drive->{wwn};
-    } elsif ($drive->{interface} eq 'usb') {
-        die "implement me";
-        #  -device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0
-    } else {
-        die "unsupported interface type";
-    }
-
-    $device .= ",bootindex=$drive->{bootindex}" if $drive->{bootindex};
-
-    if (my $serial = $drive->{serial}) {
-        $serial = URI::Escape::uri_unescape($serial);
-        $device .= ",serial=$serial";
-    }
-
-    if (min_version($machine_version, 10, 0)) { # for the switch to -blockdev
-        if (!drive_is_cdrom($drive)) {
-            my $write_cache = 'on';
-            if (my $cache = $drive->{cache}) {
-                $write_cache = 'off' if $cache eq 'writethrough' || $cache eq 'directsync';
-            }
-            $device .= ",write-cache=$write_cache";
-        }
-        for my $o (qw(rerror werror)) {
-            $device .= ",$o=$drive->{$o}" if defined($drive->{$o});
-        }
-    }
-
-    return $device;
-}
-
 sub print_drive_commandline_full {
     my ($storecfg, $vmid, $drive, $live_restore_name) = @_;
 
@@ -7932,28 +7812,6 @@ sub vm_iothreads_list {
     return $iothreads;
 }
 
-sub scsihw_infos {
-    my ($conf, $drive) = @_;
-
-    my $maxdev = 0;
-
-    if (!$conf->{scsihw} || ($conf->{scsihw} =~ m/^lsi/)) {
-        $maxdev = 7;
-    } elsif ($conf->{scsihw} && ($conf->{scsihw} eq 'virtio-scsi-single')) {
-        $maxdev = 1;
-    } else {
-        $maxdev = 256;
-    }
-
-    my $controller = int($drive->{index} / $maxdev);
-    my $controller_prefix =
-        ($conf->{scsihw} && $conf->{scsihw} eq 'virtio-scsi-single')
-        ? "virtioscsi"
-        : "scsihw";
-
-    return ($maxdev, $controller, $controller_prefix);
-}
-
 sub resolve_dst_disk_format {
     my ($storecfg, $storeid, $src_volid, $format) = @_;
 
diff --git a/src/PVE/QemuServer/DriveDevice.pm b/src/PVE/QemuServer/DriveDevice.pm
new file mode 100644
index 00000000..2e7b0247
--- /dev/null
+++ b/src/PVE/QemuServer/DriveDevice.pm
@@ -0,0 +1,164 @@
+package PVE::QemuServer::DriveDevice;
+
+use strict;
+use warnings;
+
+use URI::Escape;
+
+use PVE::QemuServer::Drive qw (drive_is_cdrom);
+use PVE::QemuServer::Helpers qw(kvm_user_version min_version);
+use PVE::QemuServer::Machine;
+use PVE::QemuServer::PCI qw(print_pci_addr);
+
+use base qw(Exporter);
+
+our @EXPORT_OK = qw(
+    print_drivedevice_full
+    scsihw_infos
+);
+
+sub scsihw_infos {
+    my ($conf, $drive) = @_;
+
+    my $maxdev = 0;
+
+    if (!$conf->{scsihw} || ($conf->{scsihw} =~ m/^lsi/)) {
+        $maxdev = 7;
+    } elsif ($conf->{scsihw} && ($conf->{scsihw} eq 'virtio-scsi-single')) {
+        $maxdev = 1;
+    } else {
+        $maxdev = 256;
+    }
+
+    my $controller = int($drive->{index} / $maxdev);
+    my $controller_prefix =
+        ($conf->{scsihw} && $conf->{scsihw} eq 'virtio-scsi-single')
+        ? "virtioscsi"
+        : "scsihw";
+
+    return ($maxdev, $controller, $controller_prefix);
+}
+
+sub print_drivedevice_full {
+    my ($storecfg, $conf, $vmid, $drive, $bridges, $arch, $machine_type) = @_;
+
+    my $device = '';
+    my $maxdev = 0;
+
+    my $machine_version =
+        PVE::QemuServer::Machine::extract_version($machine_type, kvm_user_version());
+
+    my $drive_id = PVE::QemuServer::Drive::get_drive_id($drive);
+    if ($drive->{interface} eq 'virtio') {
+        my $pciaddr = print_pci_addr("$drive_id", $bridges, $arch);
+        $device = 'virtio-blk-pci';
+        # for the switch to -blockdev, there is no blockdev for 'none'
+        if (!min_version($machine_version, 10, 0) || $drive->{file} ne 'none') {
+            $device .= ",drive=drive-$drive_id";
+        }
+        $device .= ",id=${drive_id}${pciaddr}";
+        $device .= ",iothread=iothread-$drive_id" if $drive->{iothread};
+    } elsif ($drive->{interface} eq 'scsi') {
+
+        my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $drive);
+        my $unit = $drive->{index} % $maxdev;
+
+        my $device_type =
+            PVE::QemuServer::Drive::get_scsi_device_type($drive, $storecfg, $machine_version);
+
+        if (!$conf->{scsihw} || $conf->{scsihw} =~ m/^lsi/ || $conf->{scsihw} eq 'pvscsi') {
+            $device = "scsi-$device_type,bus=$controller_prefix$controller.0,scsi-id=$unit";
+        } else {
+            $device = "scsi-$device_type,bus=$controller_prefix$controller.0,channel=0,scsi-id=0"
+                . ",lun=$drive->{index}";
+        }
+        # for the switch to -blockdev, there is no blockdev for 'none'
+        if (!min_version($machine_version, 10, 0) || $drive->{file} ne 'none') {
+            $device .= ",drive=drive-$drive_id";
+        }
+        $device .= ",id=$drive_id";
+
+        if ($drive->{ssd} && ($device_type eq 'block' || $device_type eq 'hd')) {
+            $device .= ",rotation_rate=1";
+        }
+        $device .= ",wwn=$drive->{wwn}" if $drive->{wwn};
+
+        # only scsi-hd and scsi-cd support passing vendor and product information
+        if ($device_type eq 'hd' || $device_type eq 'cd') {
+            if (my $vendor = $drive->{vendor}) {
+                $device .= ",vendor=$vendor";
+            }
+            if (my $product = $drive->{product}) {
+                $device .= ",product=$product";
+            }
+        }
+
+    } elsif ($drive->{interface} eq 'ide' || $drive->{interface} eq 'sata') {
+        my $maxdev = ($drive->{interface} eq 'sata') ? $PVE::QemuServer::Drive::MAX_SATA_DISKS : 2;
+        my $controller = int($drive->{index} / $maxdev);
+        my $unit = $drive->{index} % $maxdev;
+
+        # machine type q35 only supports unit=0 for IDE rather than 2 units. This wasn't handled
+        # correctly before, so e.g. index=2 was mapped to controller=1,unit=0 rather than
+        # controller=2,unit=0. Note that odd indices never worked, as they would be mapped to
+        # unit=1, so to keep backwards compat for migration, it suffices to keep even ones as they
+        # were before. Move odd ones up by 2 where they don't clash.
+        if (PVE::QemuServer::Machine::machine_type_is_q35($conf) && $drive->{interface} eq 'ide') {
+            $controller += 2 * ($unit % 2);
+            $unit = 0;
+        }
+
+        my $device_type = ($drive->{media} && $drive->{media} eq 'cdrom') ? "cd" : "hd";
+
+        $device = "ide-$device_type";
+        if ($drive->{interface} eq 'ide') {
+            $device .= ",bus=ide.$controller,unit=$unit";
+        } else {
+            $device .= ",bus=ahci$controller.$unit";
+        }
+        if (!min_version($machine_version, 10, 0) || $drive->{file} ne 'none') {
+            $device .= ",drive=drive-$drive_id";
+        }
+        $device .= ",id=$drive_id";
+
+        if ($device_type eq 'hd') {
+            if (my $model = $drive->{model}) {
+                $model = URI::Escape::uri_unescape($model);
+                $device .= ",model=$model";
+            }
+            if ($drive->{ssd}) {
+                $device .= ",rotation_rate=1";
+            }
+        }
+        $device .= ",wwn=$drive->{wwn}" if $drive->{wwn};
+    } elsif ($drive->{interface} eq 'usb') {
+        die "implement me";
+        #  -device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0
+    } else {
+        die "unsupported interface type";
+    }
+
+    $device .= ",bootindex=$drive->{bootindex}" if $drive->{bootindex};
+
+    if (my $serial = $drive->{serial}) {
+        $serial = URI::Escape::uri_unescape($serial);
+        $device .= ",serial=$serial";
+    }
+
+    if (min_version($machine_version, 10, 0)) { # for the switch to -blockdev
+        if (!drive_is_cdrom($drive)) {
+            my $write_cache = 'on';
+            if (my $cache = $drive->{cache}) {
+                $write_cache = 'off' if $cache eq 'writethrough' || $cache eq 'directsync';
+            }
+            $device .= ",write-cache=$write_cache";
+        }
+        for my $o (qw(rerror werror)) {
+            $device .= ",$o=$drive->{$o}" if defined($drive->{$o});
+        }
+    }
+
+    return $device;
+}
+
+1;
diff --git a/src/PVE/QemuServer/Makefile b/src/PVE/QemuServer/Makefile
index ca30a0ad..150f2229 100644
--- a/src/PVE/QemuServer/Makefile
+++ b/src/PVE/QemuServer/Makefile
@@ -9,6 +9,7 @@ SOURCES=Agent.pm	\
 	Cloudinit.pm	\
 	CPUConfig.pm	\
 	Drive.pm	\
+	DriveDevice.pm  \
 	Helpers.pm	\
 	ImportDisk.pm	\
 	Machine.pm	\
-- 
2.39.5



[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [pve-devel] [PATCH v2 qemu-server 02/10] add print_drivedevice_controller && print_drivedevice_iothread
       [not found] <20250716163415.1837210-1-alexandre.derumier@groupe-cyllene.com>
  2025-07-16 16:34 ` [pve-devel] [PATCH v2 qemu-server 01/10] introduce DriveDevice module Alexandre Derumier via pve-devel
@ 2025-07-16 16:34 ` Alexandre Derumier via pve-devel
  2025-07-16 16:34 ` [pve-devel] [PATCH v2 qemu-server 03/10] hotplug: drive controller : use print_drivedevice_iothread && print_drivedevice_controller Alexandre Derumier via pve-devel
                   ` (7 subsequent siblings)
  9 siblings, 0 replies; 10+ messages in thread
From: Alexandre Derumier via pve-devel @ 2025-07-16 16:34 UTC (permalink / raw)
  To: pve-devel; +Cc: Alexandre Derumier

[-- Attachment #1: Type: message/rfc822, Size: 9779 bytes --]

From: Alexandre Derumier <alexandre.derumier@groupe-cyllene.com>
To: pve-devel@lists.proxmox.com
Subject: [PATCH v2 qemu-server 02/10] add print_drivedevice_controller && print_drivedevice_iothread
Date: Wed, 16 Jul 2025 18:34:07 +0200
Message-ID: <20250716163415.1837210-3-alexandre.derumier@groupe-cyllene.com>

Signed-off-by: Alexandre Derumier <alexandre.derumier@groupe-cyllene.com>
---
 src/PVE/QemuServer.pm             | 63 ++++----------------------
 src/PVE/QemuServer/DriveDevice.pm | 74 +++++++++++++++++++++++++++++++
 2 files changed, 83 insertions(+), 54 deletions(-)

diff --git a/src/PVE/QemuServer.pm b/src/PVE/QemuServer.pm
index 4c60cba9..102d924c 100644
--- a/src/PVE/QemuServer.pm
+++ b/src/PVE/QemuServer.pm
@@ -72,7 +72,8 @@ use PVE::QemuServer::Drive qw(
     print_drive
     storage_allows_io_uring_default
 );
-use PVE::QemuServer::DriveDevice qw(print_drivedevice_full scsihw_infos);
+use PVE::QemuServer::DriveDevice
+    qw(print_drivedevice_controller print_drivedevice_full print_drivedevice_iothread scsihw_infos);
 use PVE::QemuServer::Machine;
 use PVE::QemuServer::Memory qw(get_current_memory);
 use PVE::QemuServer::MetaInfo;
@@ -3443,8 +3444,7 @@ sub config_to_command {
         push @$devices, '-watchdog-action', $wdopts->{action} if $wdopts->{action};
     }
 
-    my $scsicontroller = {};
-    my $ahcicontroller = {};
+    my $used_controller = {};
     my $scsihw = defined($conf->{scsihw}) ? $conf->{scsihw} : $defaults->{scsihw};
 
     # Add iscsi initiator name if available
@@ -3466,58 +3466,13 @@ sub config_to_command {
 
             $drive->{bootindex} = $bootorder->{$ds} if $bootorder->{$ds};
 
-            if ($drive->{interface} eq 'virtio') {
-                push @$cmd, '-object', "iothread,id=iothread-$ds" if $drive->{iothread};
-            }
-
-            if ($drive->{interface} eq 'scsi') {
-
-                my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $drive);
-
-                die
-                    "scsi$drive->{index}: machine version 4.1~pve2 or higher is required to use more than 14 SCSI disks\n"
-                    if $drive->{index} > 13 && !&$version_guard(4, 1, 2);
-
-                my $pciaddr = print_pci_addr("$controller_prefix$controller", $bridges, $arch);
-                my $scsihw_type =
-                    $scsihw =~ m/^virtio-scsi-single/ ? "virtio-scsi-pci" : $scsihw;
-
-                my $iothread = '';
-                if (
-                    $conf->{scsihw}
-                    && $conf->{scsihw} eq "virtio-scsi-single"
-                    && $drive->{iothread}
-                ) {
-                    $iothread .= ",iothread=iothread-$controller_prefix$controller";
-                    push @$cmd, '-object', "iothread,id=iothread-$controller_prefix$controller";
-                } elsif ($drive->{iothread}) {
-                    log_warn(
-                        "iothread is only valid with virtio disk or virtio-scsi-single controller, ignoring\n"
-                    );
-                }
+            my $iothread = print_drivedevice_iothread($conf, $drive);
+            push @$cmd, '-object', $iothread if $iothread;
 
-                my $queues = '';
-                if (
-                    $conf->{scsihw}
-                    && $conf->{scsihw} eq "virtio-scsi-single"
-                    && $drive->{queues}
-                ) {
-                    $queues = ",num_queues=$drive->{queues}";
-                }
-
-                push @$devices, '-device',
-                    "$scsihw_type,id=$controller_prefix$controller$pciaddr$iothread$queues"
-                    if !$scsicontroller->{$controller};
-                $scsicontroller->{$controller} = 1;
-            }
-
-            if ($drive->{interface} eq 'sata') {
-                my $controller = int($drive->{index} / $PVE::QemuServer::Drive::MAX_SATA_DISKS);
-                my $pciaddr = print_pci_addr("ahci$controller", $bridges, $arch);
-                push @$devices, '-device', "ahci,id=ahci$controller,multifunction=on$pciaddr"
-                    if !$ahcicontroller->{$controller};
-                $ahcicontroller->{$controller} = 1;
-            }
+            my $controller = print_drivedevice_controller(
+                $conf, $drive, $scsihw, $arch, $bridges, $used_controller,
+            );
+            push @$devices, '-device', $controller if $controller;
 
             my $live_restore = $live_restore_backing->{$ds};
 
diff --git a/src/PVE/QemuServer/DriveDevice.pm b/src/PVE/QemuServer/DriveDevice.pm
index 2e7b0247..15c80f00 100644
--- a/src/PVE/QemuServer/DriveDevice.pm
+++ b/src/PVE/QemuServer/DriveDevice.pm
@@ -14,6 +14,8 @@ use base qw(Exporter);
 
 our @EXPORT_OK = qw(
     print_drivedevice_full
+    print_drivedevice_controller
+    print_drivedevice_iothread
     scsihw_infos
 );
 
@@ -161,4 +163,76 @@ sub print_drivedevice_full {
     return $device;
 }
 
+sub print_drivedevice_controller {
+    my ($conf, $drive, $scsihw, $arch, $bridges, $used_controller) = @_;
+
+    if ($drive->{interface} eq 'scsi') {
+
+        my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $drive);
+        return if $used_controller->{scsi}->{$controller};
+
+        my $pciaddr = print_pci_addr("$controller_prefix$controller", $bridges, $arch);
+        my $scsihw_type = $scsihw =~ m/^virtio-scsi-single/ ? "virtio-scsi-pci" : $scsihw;
+
+        my $iothread = '';
+        if (
+            $conf->{scsihw}
+            && $conf->{scsihw} eq "virtio-scsi-single"
+            && $drive->{iothread}
+        ) {
+            $iothread .= ",iothread=iothread-$controller_prefix$controller";
+        }
+
+        my $queues = '';
+        if (
+            $conf->{scsihw}
+            && $conf->{scsihw} eq "virtio-scsi-single"
+            && $drive->{queues}
+        ) {
+            $queues = ",num_queues=$drive->{queues}";
+        }
+
+        $used_controller->{scsi}->{$controller} = 1;
+        return "$scsihw_type,id=$controller_prefix$controller$pciaddr$iothread$queues";
+    }
+
+    if ($drive->{interface} eq 'sata') {
+        my $controller = int($drive->{index} / $PVE::QemuServer::Drive::MAX_SATA_DISKS);
+        return if $used_controller->{ahci}->{$controller};
+
+        my $pciaddr = print_pci_addr("ahci$controller", $bridges, $arch);
+
+        $used_controller->{ahci}->{$controller} = 1;
+        return "ahci,id=ahci$controller,multifunction=on$pciaddr";
+
+    }
+}
+
+sub print_drivedevice_iothread {
+    my ($conf, $drive) = @_;
+
+    my $drive_id = PVE::QemuServer::Drive::get_drive_id($drive);
+
+    if ($drive->{interface} eq 'virtio') {
+        return "iothread,id=iothread-$drive_id" if $drive->{iothread};
+    }
+
+    if ($drive->{interface} eq 'scsi') {
+
+        my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $drive);
+
+        if (
+            $conf->{scsihw}
+            && $conf->{scsihw} eq "virtio-scsi-single"
+            && $drive->{iothread}
+        ) {
+            return "iothread,id=iothread-$controller_prefix$controller";
+        } elsif ($drive->{iothread}) {
+            log_warn(
+                "iothread is only valid with virtio disk or virtio-scsi-single controller, ignoring\n"
+            );
+        }
+    }
+}
+
 1;
-- 
2.39.5



[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [pve-devel] [PATCH v2 qemu-server 03/10] hotplug: drive controller : use print_drivedevice_iothread && print_drivedevice_controller
       [not found] <20250716163415.1837210-1-alexandre.derumier@groupe-cyllene.com>
  2025-07-16 16:34 ` [pve-devel] [PATCH v2 qemu-server 01/10] introduce DriveDevice module Alexandre Derumier via pve-devel
  2025-07-16 16:34 ` [pve-devel] [PATCH v2 qemu-server 02/10] add print_drivedevice_controller && print_drivedevice_iothread Alexandre Derumier via pve-devel
@ 2025-07-16 16:34 ` Alexandre Derumier via pve-devel
  2025-07-16 16:34 ` [pve-devel] [PATCH v2 qemu-server 04/10] pci: add get_pci_addr Alexandre Derumier via pve-devel
                   ` (6 subsequent siblings)
  9 siblings, 0 replies; 10+ messages in thread
From: Alexandre Derumier via pve-devel @ 2025-07-16 16:34 UTC (permalink / raw)
  To: pve-devel; +Cc: Alexandre Derumier

[-- Attachment #1: Type: message/rfc822, Size: 4396 bytes --]

From: Alexandre Derumier <alexandre.derumier@groupe-cyllene.com>
To: pve-devel@lists.proxmox.com
Subject: [PATCH v2 qemu-server 03/10] hotplug: drive controller : use print_drivedevice_iothread && print_drivedevice_controller
Date: Wed, 16 Jul 2025 18:34:08 +0200
Message-ID: <20250716163415.1837210-4-alexandre.derumier@groupe-cyllene.com>

Signed-off-by: Alexandre Derumier <alexandre.derumier@groupe-cyllene.com>
---
 src/PVE/QemuServer.pm | 18 ++++--------------
 1 file changed, 4 insertions(+), 14 deletions(-)

diff --git a/src/PVE/QemuServer.pm b/src/PVE/QemuServer.pm
index 102d924c..cd9e568f 100644
--- a/src/PVE/QemuServer.pm
+++ b/src/PVE/QemuServer.pm
@@ -3747,21 +3747,11 @@ sub vm_deviceplug {
         }
     } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
         my $scsihw = defined($conf->{scsihw}) ? $conf->{scsihw} : "lsi";
-        my $pciaddr = print_pci_addr($deviceid, undef, $arch);
-        my $scsihw_type = $scsihw eq 'virtio-scsi-single' ? "virtio-scsi-pci" : $scsihw;
-
-        my $devicefull = "$scsihw_type,id=$deviceid$pciaddr";
-
-        if ($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{iothread}) {
-            qemu_iothread_add($vmid, $deviceid, $device);
-            $devicefull .= ",iothread=iothread-$deviceid";
-        }
+        my $iothread = print_drivedevice_iothread($conf, $device);
+        my $controller = print_drivedevice_controller($conf, $device, $scsihw, $arch);
 
-        if ($deviceid =~ m/^virtioscsi(\d+)$/ && $device->{queues}) {
-            $devicefull .= ",num_queues=$device->{queues}";
-        }
-
-        qemu_deviceadd($vmid, $devicefull);
+        qemu_iothread_add($vmid, $deviceid, $device) if $iothread;
+        qemu_deviceadd($vmid, $controller);
         qemu_deviceaddverify($vmid, $deviceid);
     } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
         qemu_findorcreatescsihw($storecfg, $conf, $vmid, $device, $arch, $machine_type);
-- 
2.39.5



[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [pve-devel] [PATCH v2 qemu-server 04/10] pci: add get_pci_addr
       [not found] <20250716163415.1837210-1-alexandre.derumier@groupe-cyllene.com>
                   ` (2 preceding siblings ...)
  2025-07-16 16:34 ` [pve-devel] [PATCH v2 qemu-server 03/10] hotplug: drive controller : use print_drivedevice_iothread && print_drivedevice_controller Alexandre Derumier via pve-devel
@ 2025-07-16 16:34 ` Alexandre Derumier via pve-devel
  2025-07-16 16:34 ` [pve-devel] [PATCH v2 qemu-server 05/10] qmphelpers: add qmp_deviceadd && qmp_devicedel Alexandre Derumier via pve-devel
                   ` (5 subsequent siblings)
  9 siblings, 0 replies; 10+ messages in thread
From: Alexandre Derumier via pve-devel @ 2025-07-16 16:34 UTC (permalink / raw)
  To: pve-devel; +Cc: Alexandre Derumier

[-- Attachment #1: Type: message/rfc822, Size: 5030 bytes --]

From: Alexandre Derumier <alexandre.derumier@groupe-cyllene.com>
To: pve-devel@lists.proxmox.com
Subject: [PATCH v2 qemu-server 04/10] pci: add get_pci_addr
Date: Wed, 16 Jul 2025 18:34:09 +0200
Message-ID: <20250716163415.1837210-5-alexandre.derumier@groupe-cyllene.com>

return a hash with pci bus && pci address

Signed-off-by: Alexandre Derumier <alexandre.derumier@groupe-cyllene.com>
---
 src/PVE/QemuServer/PCI.pm | 17 ++++++++++++++---
 1 file changed, 14 insertions(+), 3 deletions(-)

diff --git a/src/PVE/QemuServer/PCI.pm b/src/PVE/QemuServer/PCI.pm
index e7a9a610..94fd10bd 100644
--- a/src/PVE/QemuServer/PCI.pm
+++ b/src/PVE/QemuServer/PCI.pm
@@ -16,6 +16,7 @@ use PVE::QemuServer::Machine;
 use base 'Exporter';
 
 our @EXPORT_OK = qw(
+    get_pci_addr
     print_pci_addr
     print_pcie_addr
     print_pcie_root_port
@@ -288,12 +289,12 @@ my $get_addr_mapping_from_id = sub {
     return { bus => $d->{bus}, addr => sprintf("0x%x", $d->{addr}) };
 };
 
-sub print_pci_addr {
+sub get_pci_addr {
     my ($id, $bridges, $arch) = @_;
 
     die "aarch64 cannot use IDE devices\n" if $arch eq 'aarch64' && $id =~ /^ide/;
 
-    my $res = '';
+    my $res = {};
 
     my $map = get_pci_addr_map();
     if (my $d = $get_addr_mapping_from_id->($map, $id)) {
@@ -301,13 +302,23 @@ sub print_pci_addr {
         # virt machine has an initial pcie.0. The other pci bridges that get added are called pci.N.
         my $busname = $arch eq 'aarch64' && $d->{bus} eq 0 ? 'pcie' : 'pci';
 
-        $res = ",bus=$busname.$d->{bus},addr=$d->{addr}";
+        $res = { bus => "$busname.$d->{bus}", addr => $d->{addr} };
         $bridges->{ $d->{bus} } = 1 if $bridges;
     }
 
     return $res;
 }
 
+sub print_pci_addr {
+    my ($id, $bridges, $arch) = @_;
+
+    my $pci = get_pci_addr($id, $bridges, $arch);
+    my $res = "";
+    $res .= ",bus=$pci->{bus}" if $pci->{bus};
+    $res .= ",addr=$pci->{addr}" if $pci->{addr};
+    return $res;
+}
+
 my $pcie_addr_map;
 
 sub get_pcie_addr_map {
-- 
2.39.5



[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [pve-devel] [PATCH v2 qemu-server 05/10] qmphelpers: add qmp_deviceadd && qmp_devicedel
       [not found] <20250716163415.1837210-1-alexandre.derumier@groupe-cyllene.com>
                   ` (3 preceding siblings ...)
  2025-07-16 16:34 ` [pve-devel] [PATCH v2 qemu-server 04/10] pci: add get_pci_addr Alexandre Derumier via pve-devel
@ 2025-07-16 16:34 ` Alexandre Derumier via pve-devel
  2025-07-16 16:34 ` [pve-devel] [PATCH v2 qemu-server 06/10] convert drive device to json format Alexandre Derumier via pve-devel
                   ` (4 subsequent siblings)
  9 siblings, 0 replies; 10+ messages in thread
From: Alexandre Derumier via pve-devel @ 2025-07-16 16:34 UTC (permalink / raw)
  To: pve-devel; +Cc: Alexandre Derumier

[-- Attachment #1: Type: message/rfc822, Size: 3846 bytes --]

From: Alexandre Derumier <alexandre.derumier@groupe-cyllene.com>
To: pve-devel@lists.proxmox.com
Subject: [PATCH v2 qemu-server 05/10] qmphelpers: add qmp_deviceadd && qmp_devicedel
Date: Wed, 16 Jul 2025 18:34:10 +0200
Message-ID: <20250716163415.1837210-6-alexandre.derumier@groupe-cyllene.com>

old hmp methos can be removed when everything will be
converted to hash/json

Signed-off-by: Alexandre Derumier <alexandre.derumier@groupe-cyllene.com>
---
 src/PVE/QemuServer/QMPHelpers.pm | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/src/PVE/QemuServer/QMPHelpers.pm b/src/PVE/QemuServer/QMPHelpers.pm
index c3be2b8e..327ecec4 100644
--- a/src/PVE/QemuServer/QMPHelpers.pm
+++ b/src/PVE/QemuServer/QMPHelpers.pm
@@ -9,6 +9,8 @@ use PVE::QemuServer::Monitor qw(mon_cmd);
 use base 'Exporter';
 
 our @EXPORT_OK = qw(
+    qmp_deviceadd
+    qmp_devicedel
     qemu_deviceadd
     qemu_devicedel
     qemu_objectadd
@@ -35,6 +37,20 @@ sub qemu_devicedel {
     PVE::QemuServer::Monitor::hmp_cmd($vmid, "device_del $deviceid", 25);
 }
 
+sub qmp_deviceadd {
+    my ($vmid, $opts) = @_;
+
+    $opts->{timeout} = 25;
+    mon_cmd($vmid, "device_add", %$opts);
+}
+
+sub qmp_devicedel {
+    my ($vmid, $deviceid) = @_;
+
+    my $opts = { id => $deviceid, timeout => 25 };
+    mon_cmd($vmid, "device_del", %$opts);
+}
+
 sub qemu_objectadd {
     my ($vmid, $objectid, $qomtype) = @_;
 
-- 
2.39.5



[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [pve-devel] [PATCH v2 qemu-server 06/10] convert drive device to json format
       [not found] <20250716163415.1837210-1-alexandre.derumier@groupe-cyllene.com>
                   ` (4 preceding siblings ...)
  2025-07-16 16:34 ` [pve-devel] [PATCH v2 qemu-server 05/10] qmphelpers: add qmp_deviceadd && qmp_devicedel Alexandre Derumier via pve-devel
@ 2025-07-16 16:34 ` Alexandre Derumier via pve-devel
  2025-07-16 16:34 ` [pve-devel] [PATCH v2 qemu-server 07/10] convert iothread to json Alexandre Derumier via pve-devel
                   ` (3 subsequent siblings)
  9 siblings, 0 replies; 10+ messages in thread
From: Alexandre Derumier via pve-devel @ 2025-07-16 16:34 UTC (permalink / raw)
  To: pve-devel; +Cc: Alexandre Derumier

[-- Attachment #1: Type: message/rfc822, Size: 13486 bytes --]

From: Alexandre Derumier <alexandre.derumier@groupe-cyllene.com>
To: pve-devel@lists.proxmox.com
Subject: [PATCH v2 qemu-server 06/10] convert drive device to json format
Date: Wed, 16 Jul 2025 18:34:11 +0200
Message-ID: <20250716163415.1837210-7-alexandre.derumier@groupe-cyllene.com>

Signed-off-by: Alexandre Derumier <alexandre.derumier@groupe-cyllene.com>
---
 src/PVE/QemuServer.pm             | 28 ++++++------
 src/PVE/QemuServer/DriveDevice.pm | 76 +++++++++++++++++--------------
 2 files changed, 56 insertions(+), 48 deletions(-)

diff --git a/src/PVE/QemuServer.pm b/src/PVE/QemuServer.pm
index cd9e568f..f9c195a0 100644
--- a/src/PVE/QemuServer.pm
+++ b/src/PVE/QemuServer.pm
@@ -73,7 +73,7 @@ use PVE::QemuServer::Drive qw(
     storage_allows_io_uring_default
 );
 use PVE::QemuServer::DriveDevice
-    qw(print_drivedevice_controller print_drivedevice_full print_drivedevice_iothread scsihw_infos);
+    qw(print_drivedevice_controller get_drivedevice print_drivedevice_iothread scsihw_infos);
 use PVE::QemuServer::Machine;
 use PVE::QemuServer::Memory qw(get_current_memory);
 use PVE::QemuServer::MetaInfo;
@@ -82,7 +82,8 @@ use PVE::QemuServer::Network;
 use PVE::QemuServer::OVMF;
 use PVE::QemuServer::PCI qw(print_pci_addr print_pcie_addr print_pcie_root_port parse_hostpci);
 use PVE::QemuServer::QemuImage;
-use PVE::QemuServer::QMPHelpers qw(qemu_deviceadd qemu_devicedel qemu_objectadd qemu_objectdel);
+use PVE::QemuServer::QMPHelpers
+    qw(qemu_deviceadd qemu_devicedel qemu_objectadd qemu_objectdel qmp_deviceadd qmp_devicedel);
 use PVE::QemuServer::RNG qw(parse_rng print_rng_device_commandline print_rng_object_commandline);
 use PVE::QemuServer::RunState;
 use PVE::QemuServer::StateFile;
@@ -3509,10 +3510,9 @@ sub config_to_command {
                 push @$devices, '-drive', $drive_cmd;
             }
 
-            push @$devices, '-device',
-                print_drivedevice_full(
-                    $storecfg, $conf, $vmid, $drive, $bridges, $arch, $machine_type,
-                );
+            my $drive_device =
+                get_drivedevice($storecfg, $conf, $vmid, $drive, $bridges, $arch, $machine_type);
+            push @$devices, '-device', to_json($drive_device, { canonical => 1 });
         },
     );
 
@@ -3735,10 +3735,10 @@ sub vm_deviceplug {
         qemu_iothread_add($vmid, $deviceid, $device);
 
         qemu_driveadd($storecfg, $vmid, $device);
-        my $devicefull =
-            print_drivedevice_full($storecfg, $conf, $vmid, $device, undef, $arch, $machine_type);
+        my $drive_device =
+            get_drivedevice($storecfg, $conf, $vmid, $device, undef, $arch, $machine_type);
 
-        qemu_deviceadd($vmid, $devicefull);
+        qmp_deviceadd($vmid, $drive_device);
         eval { qemu_deviceaddverify($vmid, $deviceid); };
         if (my $err = $@) {
             eval { qemu_drivedel($vmid, $deviceid); };
@@ -3757,9 +3757,9 @@ sub vm_deviceplug {
         qemu_findorcreatescsihw($storecfg, $conf, $vmid, $device, $arch, $machine_type);
         qemu_driveadd($storecfg, $vmid, $device);
 
-        my $devicefull =
-            print_drivedevice_full($storecfg, $conf, $vmid, $device, undef, $arch, $machine_type);
-        eval { qemu_deviceadd($vmid, $devicefull); };
+        my $drive_device =
+            get_drivedevice($storecfg, $conf, $vmid, $device, undef, $arch, $machine_type);
+        eval { qmp_deviceadd($vmid, $drive_device); };
         if (my $err = $@) {
             eval { qemu_drivedel($vmid, $deviceid); };
             warn $@ if $@;
@@ -3828,7 +3828,7 @@ sub vm_deviceunplug {
     } elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
         my $device = parse_drive($deviceid, $conf->{$deviceid});
 
-        qemu_devicedel($vmid, $deviceid);
+        qmp_devicedel($vmid, $deviceid);
         qemu_devicedelverify($vmid, $deviceid);
         qemu_drivedel($vmid, $deviceid);
         qemu_iothread_del($vmid, $deviceid, $device);
@@ -3838,7 +3838,7 @@ sub vm_deviceunplug {
     } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
         my $device = parse_drive($deviceid, $conf->{$deviceid});
 
-        qemu_devicedel($vmid, $deviceid);
+        qmp_devicedel($vmid, $deviceid);
         qemu_devicedelverify($vmid, $deviceid);
         qemu_drivedel($vmid, $deviceid);
         qemu_deletescsihw($conf, $vmid, $deviceid);
diff --git a/src/PVE/QemuServer/DriveDevice.pm b/src/PVE/QemuServer/DriveDevice.pm
index 15c80f00..34ebb335 100644
--- a/src/PVE/QemuServer/DriveDevice.pm
+++ b/src/PVE/QemuServer/DriveDevice.pm
@@ -8,12 +8,12 @@ use URI::Escape;
 use PVE::QemuServer::Drive qw (drive_is_cdrom);
 use PVE::QemuServer::Helpers qw(kvm_user_version min_version);
 use PVE::QemuServer::Machine;
-use PVE::QemuServer::PCI qw(print_pci_addr);
+use PVE::QemuServer::PCI qw(get_pci_addr print_pci_addr);
 
 use base qw(Exporter);
 
 our @EXPORT_OK = qw(
-    print_drivedevice_full
+    get_drivedevice
     print_drivedevice_controller
     print_drivedevice_iothread
     scsihw_infos
@@ -41,25 +41,31 @@ sub scsihw_infos {
     return ($maxdev, $controller, $controller_prefix);
 }
 
-sub print_drivedevice_full {
+sub get_drivedevice {
     my ($storecfg, $conf, $vmid, $drive, $bridges, $arch, $machine_type) = @_;
 
-    my $device = '';
+    my $device = {};
+
     my $maxdev = 0;
 
     my $machine_version =
         PVE::QemuServer::Machine::extract_version($machine_type, kvm_user_version());
 
     my $drive_id = PVE::QemuServer::Drive::get_drive_id($drive);
+
     if ($drive->{interface} eq 'virtio') {
-        my $pciaddr = print_pci_addr("$drive_id", $bridges, $arch);
-        $device = 'virtio-blk-pci';
+        my $pciaddr = get_pci_addr("$drive_id", $bridges, $arch);
+        $device = {
+            id => $drive_id,
+            driver => 'virtio-blk-pci',
+            bus => $pciaddr->{bus},
+            addr => $pciaddr->{addr},
+        };
         # for the switch to -blockdev, there is no blockdev for 'none'
         if (!min_version($machine_version, 10, 0) || $drive->{file} ne 'none') {
-            $device .= ",drive=drive-$drive_id";
+            $device->{drive} = "drive-$drive_id";
         }
-        $device .= ",id=${drive_id}${pciaddr}";
-        $device .= ",iothread=iothread-$drive_id" if $drive->{iothread};
+        $device->{iothread} = "iothread-$drive_id" if $drive->{iothread};
     } elsif ($drive->{interface} eq 'scsi') {
 
         my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $drive);
@@ -68,30 +74,35 @@ sub print_drivedevice_full {
         my $device_type =
             PVE::QemuServer::Drive::get_scsi_device_type($drive, $storecfg, $machine_version);
 
+        $device = {
+            id => $drive_id,
+            driver => "scsi-$device_type",
+            bus => "$controller_prefix$controller.0",
+        };
+
         if (!$conf->{scsihw} || $conf->{scsihw} =~ m/^lsi/ || $conf->{scsihw} eq 'pvscsi') {
-            $device = "scsi-$device_type,bus=$controller_prefix$controller.0,scsi-id=$unit";
+            $device->{'scsi-id'} = $unit;
         } else {
-            $device = "scsi-$device_type,bus=$controller_prefix$controller.0,channel=0,scsi-id=0"
-                . ",lun=$drive->{index}";
+            $device->{'scsi-id'} = 0;
+            $device->{channel} = 0;
+            $device->{lun} = int($drive->{index});
         }
         # for the switch to -blockdev, there is no blockdev for 'none'
         if (!min_version($machine_version, 10, 0) || $drive->{file} ne 'none') {
-            $device .= ",drive=drive-$drive_id";
+            $device->{drive} = "drive-$drive_id";
         }
-        $device .= ",id=$drive_id";
 
         if ($drive->{ssd} && ($device_type eq 'block' || $device_type eq 'hd')) {
-            $device .= ",rotation_rate=1";
+            $device->{'rotation-rate'} = 1;
         }
-        $device .= ",wwn=$drive->{wwn}" if $drive->{wwn};
-
+        $device->{wwn} = $drive->{wwn} if $drive->{wwn};
         # only scsi-hd and scsi-cd support passing vendor and product information
         if ($device_type eq 'hd' || $device_type eq 'cd') {
             if (my $vendor = $drive->{vendor}) {
-                $device .= ",vendor=$vendor";
+                $device->{vendor} = $vendor;
             }
             if (my $product = $drive->{product}) {
-                $device .= ",product=$product";
+                $device->{product} = $product;
             }
         }
 
@@ -111,28 +122,26 @@ sub print_drivedevice_full {
         }
 
         my $device_type = ($drive->{media} && $drive->{media} eq 'cdrom') ? "cd" : "hd";
-
-        $device = "ide-$device_type";
+        $device = { id => $drive_id, driver => "ide-$device_type" };
         if ($drive->{interface} eq 'ide') {
-            $device .= ",bus=ide.$controller,unit=$unit";
+            $device->{bus} = "ide.$controller";
+            $device->{unit} = $unit;
         } else {
-            $device .= ",bus=ahci$controller.$unit";
+            $device->{bus} = "ahci$controller.$unit";
         }
         if (!min_version($machine_version, 10, 0) || $drive->{file} ne 'none') {
-            $device .= ",drive=drive-$drive_id";
+            $device->{drive} = "drive-$drive_id";
         }
-        $device .= ",id=$drive_id";
 
         if ($device_type eq 'hd') {
             if (my $model = $drive->{model}) {
-                $model = URI::Escape::uri_unescape($model);
-                $device .= ",model=$model";
+                $device->{model} = URI::Escape::uri_unescape($model);
             }
             if ($drive->{ssd}) {
-                $device .= ",rotation_rate=1";
+                $device->{'rotation-rate'} = 1;
             }
         }
-        $device .= ",wwn=$drive->{wwn}" if $drive->{wwn};
+        $device->{wwn} = $drive->{wwn} if $drive->{wwn};
     } elsif ($drive->{interface} eq 'usb') {
         die "implement me";
         #  -device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0
@@ -140,11 +149,10 @@ sub print_drivedevice_full {
         die "unsupported interface type";
     }
 
-    $device .= ",bootindex=$drive->{bootindex}" if $drive->{bootindex};
+    $device->{bootindex} = $drive->{bootindex} if $drive->{bootindex};
 
     if (my $serial = $drive->{serial}) {
-        $serial = URI::Escape::uri_unescape($serial);
-        $device .= ",serial=$serial";
+        $device->{serial} = URI::Escape::uri_unescape($serial);
     }
 
     if (min_version($machine_version, 10, 0)) { # for the switch to -blockdev
@@ -153,10 +161,10 @@ sub print_drivedevice_full {
             if (my $cache = $drive->{cache}) {
                 $write_cache = 'off' if $cache eq 'writethrough' || $cache eq 'directsync';
             }
-            $device .= ",write-cache=$write_cache";
+            $device->{'write-cache'} = $write_cache;
         }
         for my $o (qw(rerror werror)) {
-            $device .= ",$o=$drive->{$o}" if defined($drive->{$o});
+            $device->{$o} = $drive->{$o} if defined($drive->{$o});
         }
     }
 
-- 
2.39.5



[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [pve-devel] [PATCH v2 qemu-server 07/10] convert iothread to json
       [not found] <20250716163415.1837210-1-alexandre.derumier@groupe-cyllene.com>
                   ` (5 preceding siblings ...)
  2025-07-16 16:34 ` [pve-devel] [PATCH v2 qemu-server 06/10] convert drive device to json format Alexandre Derumier via pve-devel
@ 2025-07-16 16:34 ` Alexandre Derumier via pve-devel
  2025-07-16 16:34 ` [pve-devel] [PATCH v2 qemu-server 08/10] convert disk controller device to json format Alexandre Derumier via pve-devel
                   ` (2 subsequent siblings)
  9 siblings, 0 replies; 10+ messages in thread
From: Alexandre Derumier via pve-devel @ 2025-07-16 16:34 UTC (permalink / raw)
  To: pve-devel; +Cc: Alexandre Derumier

[-- Attachment #1: Type: message/rfc822, Size: 5950 bytes --]

From: Alexandre Derumier <alexandre.derumier@groupe-cyllene.com>
To: pve-devel@lists.proxmox.com
Subject: [PATCH v2 qemu-server 07/10] convert iothread to json
Date: Wed, 16 Jul 2025 18:34:12 +0200
Message-ID: <20250716163415.1837210-8-alexandre.derumier@groupe-cyllene.com>

Signed-off-by: Alexandre Derumier <alexandre.derumier@groupe-cyllene.com>
---
 src/PVE/QemuServer.pm             | 8 ++++----
 src/PVE/QemuServer/DriveDevice.pm | 8 ++++----
 2 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/src/PVE/QemuServer.pm b/src/PVE/QemuServer.pm
index f9c195a0..5590bfbe 100644
--- a/src/PVE/QemuServer.pm
+++ b/src/PVE/QemuServer.pm
@@ -73,7 +73,7 @@ use PVE::QemuServer::Drive qw(
     storage_allows_io_uring_default
 );
 use PVE::QemuServer::DriveDevice
-    qw(print_drivedevice_controller get_drivedevice print_drivedevice_iothread scsihw_infos);
+    qw(print_drivedevice_controller get_drivedevice get_drivedevice_iothread scsihw_infos);
 use PVE::QemuServer::Machine;
 use PVE::QemuServer::Memory qw(get_current_memory);
 use PVE::QemuServer::MetaInfo;
@@ -3467,8 +3467,8 @@ sub config_to_command {
 
             $drive->{bootindex} = $bootorder->{$ds} if $bootorder->{$ds};
 
-            my $iothread = print_drivedevice_iothread($conf, $drive);
-            push @$cmd, '-object', $iothread if $iothread;
+            my $iothread = get_drivedevice_iothread($conf, $drive);
+            push @$cmd, '-object', to_json($iothread, { canonical => 1 }) if $iothread;
 
             my $controller = print_drivedevice_controller(
                 $conf, $drive, $scsihw, $arch, $bridges, $used_controller,
@@ -3747,7 +3747,7 @@ sub vm_deviceplug {
         }
     } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
         my $scsihw = defined($conf->{scsihw}) ? $conf->{scsihw} : "lsi";
-        my $iothread = print_drivedevice_iothread($conf, $device);
+        my $iothread = get_drivedevice_iothread($conf, $device);
         my $controller = print_drivedevice_controller($conf, $device, $scsihw, $arch);
 
         qemu_iothread_add($vmid, $deviceid, $device) if $iothread;
diff --git a/src/PVE/QemuServer/DriveDevice.pm b/src/PVE/QemuServer/DriveDevice.pm
index 34ebb335..c19f80d4 100644
--- a/src/PVE/QemuServer/DriveDevice.pm
+++ b/src/PVE/QemuServer/DriveDevice.pm
@@ -15,7 +15,7 @@ use base qw(Exporter);
 our @EXPORT_OK = qw(
     get_drivedevice
     print_drivedevice_controller
-    print_drivedevice_iothread
+    get_drivedevice_iothread
     scsihw_infos
 );
 
@@ -216,13 +216,13 @@ sub print_drivedevice_controller {
     }
 }
 
-sub print_drivedevice_iothread {
+sub get_drivedevice_iothread {
     my ($conf, $drive) = @_;
 
     my $drive_id = PVE::QemuServer::Drive::get_drive_id($drive);
 
     if ($drive->{interface} eq 'virtio') {
-        return "iothread,id=iothread-$drive_id" if $drive->{iothread};
+        return { 'qom-type' => 'iothread', id => "iothread-$drive_id" } if $drive->{iothread};
     }
 
     if ($drive->{interface} eq 'scsi') {
@@ -234,7 +234,7 @@ sub print_drivedevice_iothread {
             && $conf->{scsihw} eq "virtio-scsi-single"
             && $drive->{iothread}
         ) {
-            return "iothread,id=iothread-$controller_prefix$controller";
+            return { 'qom-type' => 'iothread', id => "iothread-$controller_prefix$controller" };
         } elsif ($drive->{iothread}) {
             log_warn(
                 "iothread is only valid with virtio disk or virtio-scsi-single controller, ignoring\n"
-- 
2.39.5



[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [pve-devel] [PATCH v2 qemu-server 08/10] convert disk controller device to json format
       [not found] <20250716163415.1837210-1-alexandre.derumier@groupe-cyllene.com>
                   ` (6 preceding siblings ...)
  2025-07-16 16:34 ` [pve-devel] [PATCH v2 qemu-server 07/10] convert iothread to json Alexandre Derumier via pve-devel
@ 2025-07-16 16:34 ` Alexandre Derumier via pve-devel
  2025-07-16 16:34 ` [pve-devel] [PATCH v2 qemu-server 09/10] tests: cfg2cmd: convert drive devices " Alexandre Derumier via pve-devel
  2025-07-16 16:34 ` [pve-devel] [PATCH v2 qemu-server 10/10] RFC: add multiple iothreads support Alexandre Derumier via pve-devel
  9 siblings, 0 replies; 10+ messages in thread
From: Alexandre Derumier via pve-devel @ 2025-07-16 16:34 UTC (permalink / raw)
  To: pve-devel; +Cc: Alexandre Derumier

[-- Attachment #1: Type: message/rfc822, Size: 8363 bytes --]

From: Alexandre Derumier <alexandre.derumier@groupe-cyllene.com>
To: pve-devel@lists.proxmox.com
Subject: [PATCH v2 qemu-server 08/10] convert disk controller device to json format
Date: Wed, 16 Jul 2025 18:34:13 +0200
Message-ID: <20250716163415.1837210-9-alexandre.derumier@groupe-cyllene.com>

Signed-off-by: Alexandre Derumier <alexandre.derumier@groupe-cyllene.com>
---
 src/PVE/QemuServer.pm             | 13 ++++++------
 src/PVE/QemuServer/DriveDevice.pm | 33 +++++++++++++++++++++----------
 2 files changed, 30 insertions(+), 16 deletions(-)

diff --git a/src/PVE/QemuServer.pm b/src/PVE/QemuServer.pm
index 5590bfbe..29fccffb 100644
--- a/src/PVE/QemuServer.pm
+++ b/src/PVE/QemuServer.pm
@@ -73,7 +73,7 @@ use PVE::QemuServer::Drive qw(
     storage_allows_io_uring_default
 );
 use PVE::QemuServer::DriveDevice
-    qw(print_drivedevice_controller get_drivedevice get_drivedevice_iothread scsihw_infos);
+    qw(get_drivedevice_controller get_drivedevice get_drivedevice_iothread scsihw_infos);
 use PVE::QemuServer::Machine;
 use PVE::QemuServer::Memory qw(get_current_memory);
 use PVE::QemuServer::MetaInfo;
@@ -3470,10 +3470,11 @@ sub config_to_command {
             my $iothread = get_drivedevice_iothread($conf, $drive);
             push @$cmd, '-object', to_json($iothread, { canonical => 1 }) if $iothread;
 
-            my $controller = print_drivedevice_controller(
+            my $drive_controller = get_drivedevice_controller(
                 $conf, $drive, $scsihw, $arch, $bridges, $used_controller,
             );
-            push @$devices, '-device', $controller if $controller;
+            push @$devices, '-device', to_json($drive_controller, { canonical => 1 })
+                if $drive_controller;
 
             my $live_restore = $live_restore_backing->{$ds};
 
@@ -3748,10 +3749,10 @@ sub vm_deviceplug {
     } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
         my $scsihw = defined($conf->{scsihw}) ? $conf->{scsihw} : "lsi";
         my $iothread = get_drivedevice_iothread($conf, $device);
-        my $controller = print_drivedevice_controller($conf, $device, $scsihw, $arch);
+        my $controller = get_drivedevice_controller($conf, $device, $scsihw, $arch);
 
         qemu_iothread_add($vmid, $deviceid, $device) if $iothread;
-        qemu_deviceadd($vmid, $controller);
+        qmp_deviceadd($vmid, $controller);
         qemu_deviceaddverify($vmid, $deviceid);
     } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
         qemu_findorcreatescsihw($storecfg, $conf, $vmid, $device, $arch, $machine_type);
@@ -3833,7 +3834,7 @@ sub vm_deviceunplug {
         qemu_drivedel($vmid, $deviceid);
         qemu_iothread_del($vmid, $deviceid, $device);
     } elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
-        qemu_devicedel($vmid, $deviceid);
+        qmp_devicedel($vmid, $deviceid);
         qemu_devicedelverify($vmid, $deviceid);
     } elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
         my $device = parse_drive($deviceid, $conf->{$deviceid});
diff --git a/src/PVE/QemuServer/DriveDevice.pm b/src/PVE/QemuServer/DriveDevice.pm
index c19f80d4..65555a58 100644
--- a/src/PVE/QemuServer/DriveDevice.pm
+++ b/src/PVE/QemuServer/DriveDevice.pm
@@ -14,7 +14,7 @@ use base qw(Exporter);
 
 our @EXPORT_OK = qw(
     get_drivedevice
-    print_drivedevice_controller
+    get_drivedevice_controller
     get_drivedevice_iothread
     scsihw_infos
 );
@@ -171,7 +171,7 @@ sub get_drivedevice {
     return $device;
 }
 
-sub print_drivedevice_controller {
+sub get_drivedevice_controller {
     my ($conf, $drive, $scsihw, $arch, $bridges, $used_controller) = @_;
 
     if ($drive->{interface} eq 'scsi') {
@@ -179,16 +179,23 @@ sub print_drivedevice_controller {
         my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $drive);
         return if $used_controller->{scsi}->{$controller};
 
-        my $pciaddr = print_pci_addr("$controller_prefix$controller", $bridges, $arch);
+        my $controllerid = "$controller_prefix$controller";
+        my $pciaddr = get_pci_addr($controllerid, $bridges, $arch);
         my $scsihw_type = $scsihw =~ m/^virtio-scsi-single/ ? "virtio-scsi-pci" : $scsihw;
 
-        my $iothread = '';
+        my $device = {
+            id => $controllerid,
+            driver => $scsihw_type,
+            addr => $pciaddr->{addr},
+            bus => $pciaddr->{bus},
+        };
+
         if (
             $conf->{scsihw}
             && $conf->{scsihw} eq "virtio-scsi-single"
             && $drive->{iothread}
         ) {
-            $iothread .= ",iothread=iothread-$controller_prefix$controller";
+            $device->{iothread} = "iothread-$controllerid";
         }
 
         my $queues = '';
@@ -197,22 +204,28 @@ sub print_drivedevice_controller {
             && $conf->{scsihw} eq "virtio-scsi-single"
             && $drive->{queues}
         ) {
-            $queues = ",num_queues=$drive->{queues}";
+            $device->{'num_queues'} = int($drive->{queues});
         }
 
         $used_controller->{scsi}->{$controller} = 1;
-        return "$scsihw_type,id=$controller_prefix$controller$pciaddr$iothread$queues";
+        return $device;
     }
 
     if ($drive->{interface} eq 'sata') {
         my $controller = int($drive->{index} / $PVE::QemuServer::Drive::MAX_SATA_DISKS);
         return if $used_controller->{ahci}->{$controller};
 
-        my $pciaddr = print_pci_addr("ahci$controller", $bridges, $arch);
+        my $controllerid = "ahci$controller";
+        my $pciaddr = get_pci_addr($controllerid, $bridges, $arch);
 
         $used_controller->{ahci}->{$controller} = 1;
-        return "ahci,id=ahci$controller,multifunction=on$pciaddr";
-
+        return {
+            driver => 'ahci',
+            id => $controllerid,
+            multifunction => 'on',
+            addr => $pciaddr->{addr},
+            bus => $pciaddr->{bus},
+        };
     }
 }
 
-- 
2.39.5



[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [pve-devel] [PATCH v2 qemu-server 09/10] tests: cfg2cmd: convert drive devices to json format
       [not found] <20250716163415.1837210-1-alexandre.derumier@groupe-cyllene.com>
                   ` (7 preceding siblings ...)
  2025-07-16 16:34 ` [pve-devel] [PATCH v2 qemu-server 08/10] convert disk controller device to json format Alexandre Derumier via pve-devel
@ 2025-07-16 16:34 ` Alexandre Derumier via pve-devel
  2025-07-16 16:34 ` [pve-devel] [PATCH v2 qemu-server 10/10] RFC: add multiple iothreads support Alexandre Derumier via pve-devel
  9 siblings, 0 replies; 10+ messages in thread
From: Alexandre Derumier via pve-devel @ 2025-07-16 16:34 UTC (permalink / raw)
  To: pve-devel; +Cc: Alexandre Derumier

[-- Attachment #1: Type: message/rfc822, Size: 88657 bytes --]

From: Alexandre Derumier <alexandre.derumier@groupe-cyllene.com>
To: pve-devel@lists.proxmox.com
Subject: [PATCH v2 qemu-server 09/10] tests: cfg2cmd: convert drive devices to json format
Date: Wed, 16 Jul 2025 18:34:14 +0200
Message-ID: <20250716163415.1837210-10-alexandre.derumier@groupe-cyllene.com>

Signed-off-by: Alexandre Derumier <alexandre.derumier@groupe-cyllene.com>
---
 src/test/cfg2cmd/aio.conf.cmd                 | 32 +++++++++----------
 src/test/cfg2cmd/bootorder-empty.conf.cmd     | 14 ++++----
 src/test/cfg2cmd/bootorder-legacy.conf.cmd    | 14 ++++----
 src/test/cfg2cmd/bootorder.conf.cmd           | 14 ++++----
 ...putype-icelake-client-deprecation.conf.cmd |  6 ++--
 src/test/cfg2cmd/ide.conf.cmd                 | 12 +++----
 .../cfg2cmd/pinned-version-pxe-pve.conf.cmd   |  6 ++--
 src/test/cfg2cmd/pinned-version-pxe.conf.cmd  |  6 ++--
 src/test/cfg2cmd/pinned-version.conf.cmd      |  6 ++--
 src/test/cfg2cmd/q35-ide.conf.cmd             | 12 +++----
 .../q35-linux-hostpci-template.conf.cmd       |  4 +--
 src/test/cfg2cmd/seabios_serial.conf.cmd      |  6 ++--
 src/test/cfg2cmd/simple-backingchain.conf.cmd |  6 ++--
 ...imple-balloon-free-page-reporting.conf.cmd |  6 ++--
 src/test/cfg2cmd/simple-btrfs.conf.cmd        | 12 +++----
 src/test/cfg2cmd/simple-cifs.conf.cmd         | 12 +++----
 .../cfg2cmd/simple-disk-passthrough.conf.cmd  |  8 ++---
 src/test/cfg2cmd/simple-lvm.conf.cmd          | 10 +++---
 src/test/cfg2cmd/simple-lvmthin.conf.cmd      | 10 +++---
 src/test/cfg2cmd/simple-rbd.conf.cmd          | 20 ++++++------
 src/test/cfg2cmd/simple-virtio-blk.conf.cmd   |  6 ++--
 .../cfg2cmd/simple-zfs-over-iscsi.conf.cmd    | 12 +++----
 src/test/cfg2cmd/simple1-template.conf.cmd    | 10 +++---
 src/test/cfg2cmd/simple1.conf.cmd             |  6 ++--
 24 files changed, 125 insertions(+), 125 deletions(-)

diff --git a/src/test/cfg2cmd/aio.conf.cmd b/src/test/cfg2cmd/aio.conf.cmd
index 272c6cd6..7ddfa6dd 100644
--- a/src/test/cfg2cmd/aio.conf.cmd
+++ b/src/test/cfg2cmd/aio.conf.cmd
@@ -37,34 +37,34 @@
   -device 'VGA,id=vga,bus=pci.0,addr=0x2' \
   -device 'virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3,free-page-reporting=on' \
   -iscsi 'initiator-name=iqn.1993-08.org.debian:01:aabbccddeeff' \
-  -device 'lsi,id=scsihw0,bus=pci.0,addr=0x5' \
+  -device '{"addr":"0x5","bus":"pci.0","driver":"lsi","id":"scsihw0"}' \
   -blockdev '{"driver":"throttle","file":{"cache":{"direct":true,"no-flush":false},"driver":"raw","file":{"aio":"threads","cache":{"direct":true,"no-flush":false},"detect-zeroes":"unmap","discard":"unmap","driver":"file","filename":"/var/lib/vz/images/8006/vm-8006-disk-0.raw","node-name":"e3b2553803d55d43b9986a0aac3e9a7","read-only":false},"node-name":"f3b2553803d55d43b9986a0aac3e9a7","read-only":false},"node-name":"drive-scsi0","throttle-group":"throttle-drive-scsi0"}' \
-  -device 'scsi-hd,bus=scsihw0.0,scsi-id=0,drive=drive-scsi0,id=scsi0,write-cache=on' \
+  -device '{"bus":"scsihw0.0","drive":"drive-scsi0","driver":"scsi-hd","id":"scsi0","scsi-id":0,"write-cache":"on"}' \
   -blockdev '{"driver":"throttle","file":{"cache":{"direct":true,"no-flush":false},"driver":"raw","file":{"aio":"native","cache":{"direct":true,"no-flush":false},"detect-zeroes":"unmap","discard":"unmap","driver":"file","filename":"/var/lib/vz/images/8006/vm-8006-disk-1.raw","node-name":"e08707d013893852b3d4d42301a4298","read-only":false},"node-name":"f08707d013893852b3d4d42301a4298","read-only":false},"node-name":"drive-scsi1","throttle-group":"throttle-drive-scsi1"}' \
-  -device 'scsi-hd,bus=scsihw0.0,scsi-id=1,drive=drive-scsi1,id=scsi1,write-cache=on' \
+  -device '{"bus":"scsihw0.0","drive":"drive-scsi1","driver":"scsi-hd","id":"scsi1","scsi-id":1,"write-cache":"on"}' \
   -blockdev '{"driver":"throttle","file":{"cache":{"direct":true,"no-flush":false},"driver":"raw","file":{"aio":"io_uring","cache":{"direct":true,"no-flush":false},"detect-zeroes":"unmap","discard":"unmap","driver":"file","filename":"/var/lib/vz/images/8006/vm-8006-disk-2.raw","node-name":"edb0854bba55e8b2544ad937c9f5afc","read-only":false},"node-name":"fdb0854bba55e8b2544ad937c9f5afc","read-only":false},"node-name":"drive-scsi2","throttle-group":"throttle-drive-scsi2"}' \
-  -device 'scsi-hd,bus=scsihw0.0,scsi-id=2,drive=drive-scsi2,id=scsi2,write-cache=on' \
+  -device '{"bus":"scsihw0.0","drive":"drive-scsi2","driver":"scsi-hd","id":"scsi2","scsi-id":2,"write-cache":"on"}' \
   -blockdev '{"driver":"throttle","file":{"cache":{"direct":true,"no-flush":false},"driver":"raw","file":{"aio":"io_uring","cache":{"direct":true,"no-flush":false},"detect-zeroes":"unmap","discard":"unmap","driver":"file","filename":"/var/lib/vz/images/8006/vm-8006-disk-3.raw","node-name":"e9c170cb9491763cad3f31718205efc","read-only":false},"node-name":"f9c170cb9491763cad3f31718205efc","read-only":false},"node-name":"drive-scsi3","throttle-group":"throttle-drive-scsi3"}' \
-  -device 'scsi-hd,bus=scsihw0.0,scsi-id=3,drive=drive-scsi3,id=scsi3,write-cache=on' \
+  -device '{"bus":"scsihw0.0","drive":"drive-scsi3","driver":"scsi-hd","id":"scsi3","scsi-id":3,"write-cache":"on"}' \
   -blockdev '{"driver":"throttle","file":{"cache":{"direct":true,"no-flush":false},"driver":"raw","file":{"aio":"native","cache":{"direct":true,"no-flush":false},"detect-zeroes":"unmap","discard":"unmap","driver":"file","filename":"/mnt/pve/cifs-store/images/8006/vm-8006-disk-4.raw","node-name":"ea34ecc24c40da0d53420ef344ced37","read-only":false},"node-name":"fa34ecc24c40da0d53420ef344ced37","read-only":false},"node-name":"drive-scsi4","throttle-group":"throttle-drive-scsi4"}' \
-  -device 'scsi-hd,bus=scsihw0.0,scsi-id=4,drive=drive-scsi4,id=scsi4,write-cache=on' \
+  -device '{"bus":"scsihw0.0","drive":"drive-scsi4","driver":"scsi-hd","id":"scsi4","scsi-id":4,"write-cache":"on"}' \
   -blockdev '{"driver":"throttle","file":{"cache":{"direct":true,"no-flush":false},"driver":"raw","file":{"aio":"io_uring","cache":{"direct":true,"no-flush":false},"detect-zeroes":"unmap","discard":"unmap","driver":"file","filename":"/mnt/pve/cifs-store/images/8006/vm-8006-disk-5.raw","node-name":"e39cacf47a4f4877072601505d90949","read-only":false},"node-name":"f39cacf47a4f4877072601505d90949","read-only":false},"node-name":"drive-scsi5","throttle-group":"throttle-drive-scsi5"}' \
-  -device 'scsi-hd,bus=scsihw0.0,scsi-id=5,drive=drive-scsi5,id=scsi5,write-cache=on' \
+  -device '{"bus":"scsihw0.0","drive":"drive-scsi5","driver":"scsi-hd","id":"scsi5","scsi-id":5,"write-cache":"on"}' \
   -blockdev '{"driver":"throttle","file":{"cache":{"direct":true,"no-flush":false},"driver":"raw","file":{"aio":"io_uring","cache":{"direct":true,"no-flush":false},"detect-zeroes":"unmap","discard":"unmap","driver":"host_device","filename":"/dev/rbd-pve/fc4181a6-56eb-4f68-b452-8ba1f381ca2a/cpool/vm-8006-disk-6","node-name":"e7db1ee70981087e4a2861bc7da417b","read-only":false},"node-name":"f7db1ee70981087e4a2861bc7da417b","read-only":false},"node-name":"drive-scsi6","throttle-group":"throttle-drive-scsi6"}' \
-  -device 'scsi-hd,bus=scsihw0.0,scsi-id=6,drive=drive-scsi6,id=scsi6,write-cache=on' \
-  -device 'lsi,id=scsihw1,bus=pci.0,addr=0x6' \
+  -device '{"bus":"scsihw0.0","drive":"drive-scsi6","driver":"scsi-hd","id":"scsi6","scsi-id":6,"write-cache":"on"}' \
+  -device '{"addr":"0x6","bus":"pci.0","driver":"lsi","id":"scsihw1"}' \
   -blockdev '{"driver":"throttle","file":{"cache":{"direct":true,"no-flush":false},"driver":"raw","file":{"aio":"io_uring","cache":{"direct":true,"no-flush":false},"detect-zeroes":"unmap","discard":"unmap","driver":"host_device","filename":"/dev/rbd-pve/fc4181a6-56eb-4f68-b452-8ba1f381ca2a/cpool/vm-8006-disk-7","node-name":"e2d2deac808301140a96c862fe3ea85","read-only":false},"node-name":"f2d2deac808301140a96c862fe3ea85","read-only":false},"node-name":"drive-scsi7","throttle-group":"throttle-drive-scsi7"}' \
-  -device 'scsi-hd,bus=scsihw1.0,scsi-id=0,drive=drive-scsi7,id=scsi7,write-cache=on' \
+  -device '{"bus":"scsihw1.0","drive":"drive-scsi7","driver":"scsi-hd","id":"scsi7","scsi-id":0,"write-cache":"on"}' \
   -blockdev '{"driver":"throttle","file":{"cache":{"direct":false,"no-flush":false},"driver":"raw","file":{"aio":"threads","cache":{"direct":false,"no-flush":false},"detect-zeroes":"unmap","discard":"unmap","driver":"host_device","filename":"/dev/rbd-pve/fc4181a6-56eb-4f68-b452-8ba1f381ca2a/cpool/vm-8006-disk-8","node-name":"e9796b73db57b8943746ede7d0d3060","read-only":false},"node-name":"f9796b73db57b8943746ede7d0d3060","read-only":false},"node-name":"drive-scsi8","throttle-group":"throttle-drive-scsi8"}' \
-  -device 'scsi-hd,bus=scsihw1.0,scsi-id=1,drive=drive-scsi8,id=scsi8,write-cache=on' \
+  -device '{"bus":"scsihw1.0","drive":"drive-scsi8","driver":"scsi-hd","id":"scsi8","scsi-id":1,"write-cache":"on"}' \
   -blockdev '{"driver":"throttle","file":{"cache":{"direct":false,"no-flush":false},"driver":"raw","file":{"aio":"io_uring","cache":{"direct":false,"no-flush":false},"detect-zeroes":"unmap","discard":"unmap","driver":"host_device","filename":"/dev/rbd-pve/fc4181a6-56eb-4f68-b452-8ba1f381ca2a/cpool/vm-8006-disk-9","node-name":"efa538892acc012edbdc5810035bf7d","read-only":false},"node-name":"ffa538892acc012edbdc5810035bf7d","read-only":false},"node-name":"drive-scsi9","throttle-group":"throttle-drive-scsi9"}' \
-  -device 'scsi-hd,bus=scsihw1.0,scsi-id=2,drive=drive-scsi9,id=scsi9,write-cache=on' \
+  -device '{"bus":"scsihw1.0","drive":"drive-scsi9","driver":"scsi-hd","id":"scsi9","scsi-id":2,"write-cache":"on"}' \
   -blockdev '{"driver":"throttle","file":{"cache":{"direct":true,"no-flush":false},"driver":"raw","file":{"auth-client-required":["none"],"cache":{"direct":true,"no-flush":false},"detect-zeroes":"unmap","discard":"unmap","driver":"rbd","image":"vm-8006-disk-8","node-name":"e6f4cbffa741d16bba69304eb2800ef","pool":"cpool","read-only":false,"server":[{"host":"127.0.0.42","port":"3300"},{"host":"127.0.0.21","port":"3300"},{"host":"::1","port":"3300"}]},"node-name":"f6f4cbffa741d16bba69304eb2800ef","read-only":false},"node-name":"drive-scsi10","throttle-group":"throttle-drive-scsi10"}' \
-  -device 'scsi-hd,bus=scsihw1.0,scsi-id=3,drive=drive-scsi10,id=scsi10,write-cache=on' \
+  -device '{"bus":"scsihw1.0","drive":"drive-scsi10","driver":"scsi-hd","id":"scsi10","scsi-id":3,"write-cache":"on"}' \
   -blockdev '{"driver":"throttle","file":{"cache":{"direct":true,"no-flush":false},"driver":"raw","file":{"auth-client-required":["none"],"cache":{"direct":true,"no-flush":false},"detect-zeroes":"unmap","discard":"unmap","driver":"rbd","image":"vm-8006-disk-8","node-name":"e42375c54de70f5f4be966d98c90255","pool":"cpool","read-only":false,"server":[{"host":"127.0.0.42","port":"3300"},{"host":"127.0.0.21","port":"3300"},{"host":"::1","port":"3300"}]},"node-name":"f42375c54de70f5f4be966d98c90255","read-only":false},"node-name":"drive-scsi11","throttle-group":"throttle-drive-scsi11"}' \
-  -device 'scsi-hd,bus=scsihw1.0,scsi-id=4,drive=drive-scsi11,id=scsi11,write-cache=on' \
+  -device '{"bus":"scsihw1.0","drive":"drive-scsi11","driver":"scsi-hd","id":"scsi11","scsi-id":4,"write-cache":"on"}' \
   -blockdev '{"driver":"throttle","file":{"cache":{"direct":true,"no-flush":false},"driver":"raw","file":{"aio":"native","cache":{"direct":true,"no-flush":false},"detect-zeroes":"unmap","discard":"unmap","driver":"host_device","filename":"/dev/veegee/vm-8006-disk-9","node-name":"ed7b2c9e0133619fcf6cb8ce5903502","read-only":false},"node-name":"fd7b2c9e0133619fcf6cb8ce5903502","read-only":false},"node-name":"drive-scsi12","throttle-group":"throttle-drive-scsi12"}' \
-  -device 'scsi-hd,bus=scsihw1.0,scsi-id=5,drive=drive-scsi12,id=scsi12,write-cache=on' \
+  -device '{"bus":"scsihw1.0","drive":"drive-scsi12","driver":"scsi-hd","id":"scsi12","scsi-id":5,"write-cache":"on"}' \
   -blockdev '{"driver":"throttle","file":{"cache":{"direct":true,"no-flush":false},"driver":"raw","file":{"aio":"io_uring","cache":{"direct":true,"no-flush":false},"detect-zeroes":"unmap","discard":"unmap","driver":"host_device","filename":"/dev/veegee/vm-8006-disk-9","node-name":"ed85420a880203ca1401d00a8edf132","read-only":false},"node-name":"fd85420a880203ca1401d00a8edf132","read-only":false},"node-name":"drive-scsi13","throttle-group":"throttle-drive-scsi13"}' \
-  -device 'scsi-hd,bus=scsihw1.0,scsi-id=6,drive=drive-scsi13,id=scsi13,write-cache=on' \
+  -device '{"bus":"scsihw1.0","drive":"drive-scsi13","driver":"scsi-hd","id":"scsi13","scsi-id":6,"write-cache":"on"}' \
   -machine 'type=pc+pve0'
diff --git a/src/test/cfg2cmd/bootorder-empty.conf.cmd b/src/test/cfg2cmd/bootorder-empty.conf.cmd
index 84b38221..f2d51d64 100644
--- a/src/test/cfg2cmd/bootorder-empty.conf.cmd
+++ b/src/test/cfg2cmd/bootorder-empty.conf.cmd
@@ -16,9 +16,9 @@
   -cpu kvm64,enforce,+kvm_pv_eoi,+kvm_pv_unhalt,+lahf_lm,+sep \
   -m 768 \
   -object '{"id":"throttle-drive-scsi4","limits":{},"qom-type":"throttle-group"}' \
-  -object 'iothread,id=iothread-virtio0' \
+  -object '{"id":"iothread-virtio0","qom-type":"iothread"}' \
   -object '{"id":"throttle-drive-virtio0","limits":{},"qom-type":"throttle-group"}' \
-  -object 'iothread,id=iothread-virtio1' \
+  -object '{"id":"iothread-virtio1","qom-type":"iothread"}' \
   -object '{"id":"throttle-drive-virtio1","limits":{},"qom-type":"throttle-group"}' \
   -global 'PIIX4_PM.disable_s3=1' \
   -global 'PIIX4_PM.disable_s4=1' \
@@ -30,14 +30,14 @@
   -device 'VGA,id=vga,bus=pci.0,addr=0x2' \
   -device 'virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3,free-page-reporting=on' \
   -iscsi 'initiator-name=iqn.1993-08.org.debian:01:aabbccddeeff' \
-  -device 'ide-cd,bus=ide.1,unit=0,id=ide2' \
-  -device 'lsi,id=scsihw0,bus=pci.0,addr=0x5' \
+  -device '{"bus":"ide.1","driver":"ide-cd","id":"ide2","unit":0}' \
+  -device '{"addr":"0x5","bus":"pci.0","driver":"lsi","id":"scsihw0"}' \
   -blockdev '{"driver":"throttle","file":{"cache":{"direct":true,"no-flush":false},"driver":"qcow2","file":{"aio":"io_uring","cache":{"direct":true,"no-flush":false},"detect-zeroes":"unmap","discard":"unmap","driver":"file","filename":"/var/lib/vz/images/8006/vm-8006-disk-0.qcow2","node-name":"e6bf62e20f6c14a2c19bd6f1f5ac36c","read-only":false},"node-name":"f6bf62e20f6c14a2c19bd6f1f5ac36c","read-only":false},"node-name":"drive-scsi4","throttle-group":"throttle-drive-scsi4"}' \
-  -device 'scsi-hd,bus=scsihw0.0,scsi-id=4,drive=drive-scsi4,id=scsi4,write-cache=on' \
+  -device '{"bus":"scsihw0.0","drive":"drive-scsi4","driver":"scsi-hd","id":"scsi4","scsi-id":4,"write-cache":"on"}' \
   -blockdev '{"driver":"throttle","file":{"cache":{"direct":true,"no-flush":false},"driver":"qcow2","file":{"aio":"io_uring","cache":{"direct":true,"no-flush":false},"detect-zeroes":"unmap","discard":"unmap","driver":"file","filename":"/var/lib/vz/images/8006/vm-8006-disk-0.qcow2","node-name":"edd19f6c1b3a6d5a6248c3376a91a16","read-only":false},"node-name":"fdd19f6c1b3a6d5a6248c3376a91a16","read-only":false},"node-name":"drive-virtio0","throttle-group":"throttle-drive-virtio0"}' \
-  -device 'virtio-blk-pci,drive=drive-virtio0,id=virtio0,bus=pci.0,addr=0xa,iothread=iothread-virtio0,write-cache=on' \
+  -device '{"addr":"0xa","bus":"pci.0","drive":"drive-virtio0","driver":"virtio-blk-pci","id":"virtio0","iothread":"iothread-virtio0","write-cache":"on"}' \
   -blockdev '{"driver":"throttle","file":{"cache":{"direct":true,"no-flush":false},"driver":"qcow2","file":{"aio":"io_uring","cache":{"direct":true,"no-flush":false},"detect-zeroes":"unmap","discard":"unmap","driver":"file","filename":"/var/lib/vz/images/8006/vm-8006-disk-0.qcow2","node-name":"eeb683fb9c516c1a8707c917f0d7a38","read-only":false},"node-name":"feb683fb9c516c1a8707c917f0d7a38","read-only":false},"node-name":"drive-virtio1","throttle-group":"throttle-drive-virtio1"}' \
-  -device 'virtio-blk-pci,drive=drive-virtio1,id=virtio1,bus=pci.0,addr=0xb,iothread=iothread-virtio1,write-cache=on' \
+  -device '{"addr":"0xb","bus":"pci.0","drive":"drive-virtio1","driver":"virtio-blk-pci","id":"virtio1","iothread":"iothread-virtio1","write-cache":"on"}' \
   -netdev 'type=tap,id=net0,ifname=tap8006i0,script=/usr/libexec/qemu-server/pve-bridge,downscript=/usr/libexec/qemu-server/pve-bridgedown,vhost=on' \
   -device 'virtio-net-pci,mac=A2:C0:43:77:08:A0,netdev=net0,bus=pci.0,addr=0x12,id=net0,rx_queue_size=1024,tx_queue_size=256' \
   -machine 'type=pc+pve0'
diff --git a/src/test/cfg2cmd/bootorder-legacy.conf.cmd b/src/test/cfg2cmd/bootorder-legacy.conf.cmd
index 5f64a62f..2472e0c0 100644
--- a/src/test/cfg2cmd/bootorder-legacy.conf.cmd
+++ b/src/test/cfg2cmd/bootorder-legacy.conf.cmd
@@ -16,9 +16,9 @@
   -cpu kvm64,enforce,+kvm_pv_eoi,+kvm_pv_unhalt,+lahf_lm,+sep \
   -m 768 \
   -object '{"id":"throttle-drive-scsi4","limits":{},"qom-type":"throttle-group"}' \
-  -object 'iothread,id=iothread-virtio0' \
+  -object '{"id":"iothread-virtio0","qom-type":"iothread"}' \
   -object '{"id":"throttle-drive-virtio0","limits":{},"qom-type":"throttle-group"}' \
-  -object 'iothread,id=iothread-virtio1' \
+  -object '{"id":"iothread-virtio1","qom-type":"iothread"}' \
   -object '{"id":"throttle-drive-virtio1","limits":{},"qom-type":"throttle-group"}' \
   -global 'PIIX4_PM.disable_s3=1' \
   -global 'PIIX4_PM.disable_s4=1' \
@@ -30,14 +30,14 @@
   -device 'VGA,id=vga,bus=pci.0,addr=0x2' \
   -device 'virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3,free-page-reporting=on' \
   -iscsi 'initiator-name=iqn.1993-08.org.debian:01:aabbccddeeff' \
-  -device 'ide-cd,bus=ide.1,unit=0,id=ide2,bootindex=200' \
-  -device 'lsi,id=scsihw0,bus=pci.0,addr=0x5' \
+  -device '{"bootindex":200,"bus":"ide.1","driver":"ide-cd","id":"ide2","unit":0}' \
+  -device '{"addr":"0x5","bus":"pci.0","driver":"lsi","id":"scsihw0"}' \
   -blockdev '{"driver":"throttle","file":{"cache":{"direct":true,"no-flush":false},"driver":"qcow2","file":{"aio":"io_uring","cache":{"direct":true,"no-flush":false},"detect-zeroes":"unmap","discard":"unmap","driver":"file","filename":"/var/lib/vz/images/8006/vm-8006-disk-0.qcow2","node-name":"e6bf62e20f6c14a2c19bd6f1f5ac36c","read-only":false},"node-name":"f6bf62e20f6c14a2c19bd6f1f5ac36c","read-only":false},"node-name":"drive-scsi4","throttle-group":"throttle-drive-scsi4"}' \
-  -device 'scsi-hd,bus=scsihw0.0,scsi-id=4,drive=drive-scsi4,id=scsi4,write-cache=on' \
+  -device '{"bus":"scsihw0.0","drive":"drive-scsi4","driver":"scsi-hd","id":"scsi4","scsi-id":4,"write-cache":"on"}' \
   -blockdev '{"driver":"throttle","file":{"cache":{"direct":true,"no-flush":false},"driver":"qcow2","file":{"aio":"io_uring","cache":{"direct":true,"no-flush":false},"detect-zeroes":"unmap","discard":"unmap","driver":"file","filename":"/var/lib/vz/images/8006/vm-8006-disk-0.qcow2","node-name":"edd19f6c1b3a6d5a6248c3376a91a16","read-only":false},"node-name":"fdd19f6c1b3a6d5a6248c3376a91a16","read-only":false},"node-name":"drive-virtio0","throttle-group":"throttle-drive-virtio0"}' \
-  -device 'virtio-blk-pci,drive=drive-virtio0,id=virtio0,bus=pci.0,addr=0xa,iothread=iothread-virtio0,write-cache=on' \
+  -device '{"addr":"0xa","bus":"pci.0","drive":"drive-virtio0","driver":"virtio-blk-pci","id":"virtio0","iothread":"iothread-virtio0","write-cache":"on"}' \
   -blockdev '{"driver":"throttle","file":{"cache":{"direct":true,"no-flush":false},"driver":"qcow2","file":{"aio":"io_uring","cache":{"direct":true,"no-flush":false},"detect-zeroes":"unmap","discard":"unmap","driver":"file","filename":"/var/lib/vz/images/8006/vm-8006-disk-0.qcow2","node-name":"eeb683fb9c516c1a8707c917f0d7a38","read-only":false},"node-name":"feb683fb9c516c1a8707c917f0d7a38","read-only":false},"node-name":"drive-virtio1","throttle-group":"throttle-drive-virtio1"}' \
-  -device 'virtio-blk-pci,drive=drive-virtio1,id=virtio1,bus=pci.0,addr=0xb,iothread=iothread-virtio1,bootindex=302,write-cache=on' \
+  -device '{"addr":"0xb","bootindex":302,"bus":"pci.0","drive":"drive-virtio1","driver":"virtio-blk-pci","id":"virtio1","iothread":"iothread-virtio1","write-cache":"on"}' \
   -netdev 'type=tap,id=net0,ifname=tap8006i0,script=/usr/libexec/qemu-server/pve-bridge,downscript=/usr/libexec/qemu-server/pve-bridgedown,vhost=on' \
   -device 'virtio-net-pci,mac=A2:C0:43:77:08:A0,netdev=net0,bus=pci.0,addr=0x12,id=net0,rx_queue_size=1024,tx_queue_size=256,bootindex=100' \
   -machine 'type=pc+pve0'
diff --git a/src/test/cfg2cmd/bootorder.conf.cmd b/src/test/cfg2cmd/bootorder.conf.cmd
index c0f19a04..2e2fd0f3 100644
--- a/src/test/cfg2cmd/bootorder.conf.cmd
+++ b/src/test/cfg2cmd/bootorder.conf.cmd
@@ -16,9 +16,9 @@
   -cpu kvm64,enforce,+kvm_pv_eoi,+kvm_pv_unhalt,+lahf_lm,+sep \
   -m 768 \
   -object '{"id":"throttle-drive-scsi4","limits":{},"qom-type":"throttle-group"}' \
-  -object 'iothread,id=iothread-virtio0' \
+  -object '{"id":"iothread-virtio0","qom-type":"iothread"}' \
   -object '{"id":"throttle-drive-virtio0","limits":{},"qom-type":"throttle-group"}' \
-  -object 'iothread,id=iothread-virtio1' \
+  -object '{"id":"iothread-virtio1","qom-type":"iothread"}' \
   -object '{"id":"throttle-drive-virtio1","limits":{},"qom-type":"throttle-group"}' \
   -global 'PIIX4_PM.disable_s3=1' \
   -global 'PIIX4_PM.disable_s4=1' \
@@ -30,14 +30,14 @@
   -device 'VGA,id=vga,bus=pci.0,addr=0x2' \
   -device 'virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3,free-page-reporting=on' \
   -iscsi 'initiator-name=iqn.1993-08.org.debian:01:aabbccddeeff' \
-  -device 'ide-cd,bus=ide.1,unit=0,id=ide2,bootindex=103' \
-  -device 'lsi,id=scsihw0,bus=pci.0,addr=0x5' \
+  -device '{"bootindex":103,"bus":"ide.1","driver":"ide-cd","id":"ide2","unit":0}' \
+  -device '{"addr":"0x5","bus":"pci.0","driver":"lsi","id":"scsihw0"}' \
   -blockdev '{"driver":"throttle","file":{"cache":{"direct":true,"no-flush":false},"driver":"qcow2","file":{"aio":"io_uring","cache":{"direct":true,"no-flush":false},"detect-zeroes":"unmap","discard":"unmap","driver":"file","filename":"/var/lib/vz/images/8006/vm-8006-disk-0.qcow2","node-name":"e6bf62e20f6c14a2c19bd6f1f5ac36c","read-only":false},"node-name":"f6bf62e20f6c14a2c19bd6f1f5ac36c","read-only":false},"node-name":"drive-scsi4","throttle-group":"throttle-drive-scsi4"}' \
-  -device 'scsi-hd,bus=scsihw0.0,scsi-id=4,drive=drive-scsi4,id=scsi4,bootindex=102,write-cache=on' \
+  -device '{"bootindex":102,"bus":"scsihw0.0","drive":"drive-scsi4","driver":"scsi-hd","id":"scsi4","scsi-id":4,"write-cache":"on"}' \
   -blockdev '{"driver":"throttle","file":{"cache":{"direct":true,"no-flush":false},"driver":"qcow2","file":{"aio":"io_uring","cache":{"direct":true,"no-flush":false},"detect-zeroes":"unmap","discard":"unmap","driver":"file","filename":"/var/lib/vz/images/8006/vm-8006-disk-0.qcow2","node-name":"edd19f6c1b3a6d5a6248c3376a91a16","read-only":false},"node-name":"fdd19f6c1b3a6d5a6248c3376a91a16","read-only":false},"node-name":"drive-virtio0","throttle-group":"throttle-drive-virtio0"}' \
-  -device 'virtio-blk-pci,drive=drive-virtio0,id=virtio0,bus=pci.0,addr=0xa,iothread=iothread-virtio0,write-cache=on' \
+  -device '{"addr":"0xa","bus":"pci.0","drive":"drive-virtio0","driver":"virtio-blk-pci","id":"virtio0","iothread":"iothread-virtio0","write-cache":"on"}' \
   -blockdev '{"driver":"throttle","file":{"cache":{"direct":true,"no-flush":false},"driver":"qcow2","file":{"aio":"io_uring","cache":{"direct":true,"no-flush":false},"detect-zeroes":"unmap","discard":"unmap","driver":"file","filename":"/var/lib/vz/images/8006/vm-8006-disk-0.qcow2","node-name":"eeb683fb9c516c1a8707c917f0d7a38","read-only":false},"node-name":"feb683fb9c516c1a8707c917f0d7a38","read-only":false},"node-name":"drive-virtio1","throttle-group":"throttle-drive-virtio1"}' \
-  -device 'virtio-blk-pci,drive=drive-virtio1,id=virtio1,bus=pci.0,addr=0xb,iothread=iothread-virtio1,bootindex=100,write-cache=on' \
+  -device '{"addr":"0xb","bootindex":100,"bus":"pci.0","drive":"drive-virtio1","driver":"virtio-blk-pci","id":"virtio1","iothread":"iothread-virtio1","write-cache":"on"}' \
   -netdev 'type=tap,id=net0,ifname=tap8006i0,script=/usr/libexec/qemu-server/pve-bridge,downscript=/usr/libexec/qemu-server/pve-bridgedown,vhost=on' \
   -device 'virtio-net-pci,mac=A2:C0:43:77:08:A0,netdev=net0,bus=pci.0,addr=0x12,id=net0,rx_queue_size=1024,tx_queue_size=256,bootindex=101' \
   -machine 'type=pc+pve0'
diff --git a/src/test/cfg2cmd/cputype-icelake-client-deprecation.conf.cmd b/src/test/cfg2cmd/cputype-icelake-client-deprecation.conf.cmd
index 5269e673..f091c5ce 100644
--- a/src/test/cfg2cmd/cputype-icelake-client-deprecation.conf.cmd
+++ b/src/test/cfg2cmd/cputype-icelake-client-deprecation.conf.cmd
@@ -26,8 +26,8 @@
   -device 'VGA,id=vga,bus=pci.0,addr=0x2' \
   -device 'virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3,free-page-reporting=on' \
   -iscsi 'initiator-name=iqn.1993-08.org.debian:01:aabbccddeeff' \
-  -device 'ide-cd,bus=ide.1,unit=0,id=ide2,bootindex=200' \
-  -device 'virtio-scsi-pci,id=scsihw0,bus=pci.0,addr=0x5' \
+  -device '{"bootindex":200,"bus":"ide.1","driver":"ide-cd","id":"ide2","unit":0}' \
+  -device '{"addr":"0x5","bus":"pci.0","driver":"virtio-scsi-pci","id":"scsihw0"}' \
   -blockdev '{"driver":"throttle","file":{"cache":{"direct":true,"no-flush":false},"driver":"qcow2","file":{"aio":"io_uring","cache":{"direct":true,"no-flush":false},"detect-zeroes":"unmap","discard":"unmap","driver":"file","filename":"/var/lib/vz/images/8006/base-8006-disk-0.qcow2","node-name":"e417d5947e69c5890b1e3ddf8a68167","read-only":false},"node-name":"f417d5947e69c5890b1e3ddf8a68167","read-only":false},"node-name":"drive-scsi0","throttle-group":"throttle-drive-scsi0"}' \
-  -device 'scsi-hd,bus=scsihw0.0,channel=0,scsi-id=0,lun=0,drive=drive-scsi0,id=scsi0,bootindex=100,write-cache=on' \
+  -device '{"bootindex":100,"bus":"scsihw0.0","channel":0,"drive":"drive-scsi0","driver":"scsi-hd","id":"scsi0","lun":0,"scsi-id":0,"write-cache":"on"}' \
   -machine 'type=pc+pve0'
diff --git a/src/test/cfg2cmd/ide.conf.cmd b/src/test/cfg2cmd/ide.conf.cmd
index 78fe7550..705fb288 100644
--- a/src/test/cfg2cmd/ide.conf.cmd
+++ b/src/test/cfg2cmd/ide.conf.cmd
@@ -31,16 +31,16 @@
   -device 'virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3,free-page-reporting=on' \
   -iscsi 'initiator-name=iqn.1993-08.org.debian:01:aabbccddeeff' \
   -blockdev '{"driver":"throttle","file":{"cache":{"direct":false,"no-flush":false},"driver":"raw","file":{"aio":"io_uring","cache":{"direct":false,"no-flush":false},"driver":"file","filename":"/var/lib/vz/template/iso/zero.iso","node-name":"e19e15bf93b8cf09e2a5d1669648165","read-only":true},"node-name":"f19e15bf93b8cf09e2a5d1669648165","read-only":true},"node-name":"drive-ide0","throttle-group":"throttle-drive-ide0"}' \
-  -device 'ide-cd,bus=ide.0,unit=0,drive=drive-ide0,id=ide0,bootindex=200' \
+  -device '{"bootindex":200,"bus":"ide.0","drive":"drive-ide0","driver":"ide-cd","id":"ide0","unit":0}' \
   -blockdev '{"driver":"throttle","file":{"cache":{"direct":false,"no-flush":false},"driver":"raw","file":{"aio":"threads","cache":{"direct":false,"no-flush":false},"driver":"file","filename":"/mnt/pve/cifs-store/template/iso/one.iso","node-name":"e247a6535f864815c8e9dbb5a118336","read-only":true},"node-name":"f247a6535f864815c8e9dbb5a118336","read-only":true},"node-name":"drive-ide1","throttle-group":"throttle-drive-ide1"}' \
-  -device 'ide-cd,bus=ide.0,unit=1,drive=drive-ide1,id=ide1,bootindex=201' \
+  -device '{"bootindex":201,"bus":"ide.0","drive":"drive-ide1","driver":"ide-cd","id":"ide1","unit":1}' \
   -blockdev '{"driver":"throttle","file":{"cache":{"direct":false,"no-flush":false},"driver":"raw","file":{"aio":"threads","cache":{"direct":false,"no-flush":false},"driver":"file","filename":"/mnt/pve/cifs-store/template/iso/two.iso","node-name":"ec78a64f692c2fa9f873a111580aebd","read-only":true},"node-name":"fc78a64f692c2fa9f873a111580aebd","read-only":true},"node-name":"drive-ide2","throttle-group":"throttle-drive-ide2"}' \
-  -device 'ide-cd,bus=ide.1,unit=0,drive=drive-ide2,id=ide2,bootindex=202' \
+  -device '{"bootindex":202,"bus":"ide.1","drive":"drive-ide2","driver":"ide-cd","id":"ide2","unit":0}' \
   -blockdev '{"driver":"throttle","file":{"cache":{"direct":false,"no-flush":false},"driver":"raw","file":{"aio":"threads","cache":{"direct":false,"no-flush":false},"driver":"file","filename":"/mnt/pve/cifs-store/template/iso/three.iso","node-name":"e35557bae4bcbf9edc9f7ff7f132f30","read-only":true},"node-name":"f35557bae4bcbf9edc9f7ff7f132f30","read-only":true},"node-name":"drive-ide3","throttle-group":"throttle-drive-ide3"}' \
-  -device 'ide-cd,bus=ide.1,unit=1,drive=drive-ide3,id=ide3,bootindex=203' \
-  -device 'virtio-scsi-pci,id=scsihw0,bus=pci.0,addr=0x5' \
+  -device '{"bootindex":203,"bus":"ide.1","drive":"drive-ide3","driver":"ide-cd","id":"ide3","unit":1}' \
+  -device '{"addr":"0x5","bus":"pci.0","driver":"virtio-scsi-pci","id":"scsihw0"}' \
   -blockdev '{"driver":"throttle","file":{"cache":{"direct":true,"no-flush":false},"driver":"qcow2","file":{"aio":"io_uring","cache":{"direct":true,"no-flush":false},"detect-zeroes":"on","discard":"ignore","driver":"file","filename":"/var/lib/vz/images/100/vm-100-disk-2.qcow2","node-name":"ec11e0572184321efc5835152b95d5d","read-only":false},"node-name":"fc11e0572184321efc5835152b95d5d","read-only":false},"node-name":"drive-scsi0","throttle-group":"throttle-drive-scsi0"}' \
-  -device 'scsi-hd,bus=scsihw0.0,channel=0,scsi-id=0,lun=0,drive=drive-scsi0,id=scsi0,bootindex=100,write-cache=on' \
+  -device '{"bootindex":100,"bus":"scsihw0.0","channel":0,"drive":"drive-scsi0","driver":"scsi-hd","id":"scsi0","lun":0,"scsi-id":0,"write-cache":"on"}' \
   -netdev 'type=tap,id=net0,ifname=tap8006i0,script=/usr/libexec/qemu-server/pve-bridge,downscript=/usr/libexec/qemu-server/pve-bridgedown,vhost=on' \
   -device 'virtio-net-pci,mac=2E:01:68:F9:9C:87,netdev=net0,bus=pci.0,addr=0x12,id=net0,rx_queue_size=1024,tx_queue_size=256,bootindex=300' \
   -machine 'type=pc+pve0'
diff --git a/src/test/cfg2cmd/pinned-version-pxe-pve.conf.cmd b/src/test/cfg2cmd/pinned-version-pxe-pve.conf.cmd
index 7301e3fa..25faa8e8 100644
--- a/src/test/cfg2cmd/pinned-version-pxe-pve.conf.cmd
+++ b/src/test/cfg2cmd/pinned-version-pxe-pve.conf.cmd
@@ -24,10 +24,10 @@
   -device 'virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3' \
   -iscsi 'initiator-name=iqn.1993-08.org.debian:01:aabbccddeeff' \
   -drive 'if=none,id=drive-ide2,media=cdrom,aio=io_uring' \
-  -device 'ide-cd,bus=ide.1,unit=0,drive=drive-ide2,id=ide2,bootindex=200' \
-  -device 'virtio-scsi-pci,id=scsihw0,bus=pci.0,addr=0x5' \
+  -device '{"bootindex":200,"bus":"ide.1","drive":"drive-ide2","driver":"ide-cd","id":"ide2","unit":0}' \
+  -device '{"addr":"0x5","bus":"pci.0","driver":"virtio-scsi-pci","id":"scsihw0"}' \
   -drive 'file=/var/lib/vz/images/8006/vm-8006-disk-0.raw,if=none,id=drive-scsi0,discard=on,format=raw,cache=none,aio=io_uring,detect-zeroes=unmap' \
-  -device 'scsi-hd,bus=scsihw0.0,channel=0,scsi-id=0,lun=0,drive=drive-scsi0,id=scsi0,bootindex=100' \
+  -device '{"bootindex":100,"bus":"scsihw0.0","channel":0,"drive":"drive-scsi0","driver":"scsi-hd","id":"scsi0","lun":0,"scsi-id":0}' \
   -netdev 'type=tap,id=net0,ifname=tap8006i0,script=/usr/libexec/qemu-server/pve-bridge,downscript=/usr/libexec/qemu-server/pve-bridgedown,vhost=on' \
   -device 'virtio-net-pci,mac=A2:C0:43:77:08:A1,netdev=net0,bus=pci.0,addr=0x12,id=net0,bootindex=300,romfile=pxe-virtio.rom' \
   -machine 'type=pc-q35-4.1+pve2'
diff --git a/src/test/cfg2cmd/pinned-version-pxe.conf.cmd b/src/test/cfg2cmd/pinned-version-pxe.conf.cmd
index 89be8c69..ee954f9d 100644
--- a/src/test/cfg2cmd/pinned-version-pxe.conf.cmd
+++ b/src/test/cfg2cmd/pinned-version-pxe.conf.cmd
@@ -22,10 +22,10 @@
   -device 'virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3' \
   -iscsi 'initiator-name=iqn.1993-08.org.debian:01:aabbccddeeff' \
   -drive 'if=none,id=drive-ide2,media=cdrom,aio=io_uring' \
-  -device 'ide-cd,bus=ide.1,unit=0,drive=drive-ide2,id=ide2,bootindex=200' \
-  -device 'virtio-scsi-pci,id=scsihw0,bus=pci.0,addr=0x5' \
+  -device '{"bootindex":200,"bus":"ide.1","drive":"drive-ide2","driver":"ide-cd","id":"ide2","unit":0}' \
+  -device '{"addr":"0x5","bus":"pci.0","driver":"virtio-scsi-pci","id":"scsihw0"}' \
   -drive 'file=/var/lib/vz/images/8006/vm-8006-disk-0.raw,if=none,id=drive-scsi0,discard=on,format=raw,cache=none,aio=io_uring,detect-zeroes=unmap' \
-  -device 'scsi-hd,bus=scsihw0.0,channel=0,scsi-id=0,lun=0,drive=drive-scsi0,id=scsi0,bootindex=100' \
+  -device '{"bootindex":100,"bus":"scsihw0.0","channel":0,"drive":"drive-scsi0","driver":"scsi-hd","id":"scsi0","lun":0,"scsi-id":0}' \
   -netdev 'type=tap,id=net0,ifname=tap8006i0,script=/usr/libexec/qemu-server/pve-bridge,downscript=/usr/libexec/qemu-server/pve-bridgedown,vhost=on' \
   -device 'virtio-net-pci,mac=A2:C0:43:77:08:A1,netdev=net0,bus=pci.0,addr=0x12,id=net0,bootindex=300,romfile=pxe-virtio.rom' \
   -machine 'type=pc-q35-5.1+pve0'
diff --git a/src/test/cfg2cmd/pinned-version.conf.cmd b/src/test/cfg2cmd/pinned-version.conf.cmd
index da161ad9..daa04fc2 100644
--- a/src/test/cfg2cmd/pinned-version.conf.cmd
+++ b/src/test/cfg2cmd/pinned-version.conf.cmd
@@ -22,10 +22,10 @@
   -device 'virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3' \
   -iscsi 'initiator-name=iqn.1993-08.org.debian:01:aabbccddeeff' \
   -drive 'if=none,id=drive-ide2,media=cdrom,aio=io_uring' \
-  -device 'ide-cd,bus=ide.1,unit=0,drive=drive-ide2,id=ide2,bootindex=200' \
-  -device 'virtio-scsi-pci,id=scsihw0,bus=pci.0,addr=0x5' \
+  -device '{"bootindex":200,"bus":"ide.1","drive":"drive-ide2","driver":"ide-cd","id":"ide2","unit":0}' \
+  -device '{"addr":"0x5","bus":"pci.0","driver":"virtio-scsi-pci","id":"scsihw0"}' \
   -drive 'file=/var/lib/vz/images/8006/vm-8006-disk-0.raw,if=none,id=drive-scsi0,discard=on,format=raw,cache=none,aio=io_uring,detect-zeroes=unmap' \
-  -device 'scsi-hd,bus=scsihw0.0,channel=0,scsi-id=0,lun=0,drive=drive-scsi0,id=scsi0,bootindex=100' \
+  -device '{"bootindex":100,"bus":"scsihw0.0","channel":0,"drive":"drive-scsi0","driver":"scsi-hd","id":"scsi0","lun":0,"scsi-id":0}' \
   -netdev 'type=tap,id=net0,ifname=tap8006i0,script=/usr/libexec/qemu-server/pve-bridge,downscript=/usr/libexec/qemu-server/pve-bridgedown,vhost=on' \
   -device 'virtio-net-pci,mac=A2:C0:43:77:08:A1,netdev=net0,bus=pci.0,addr=0x12,id=net0,bootindex=300' \
   -machine 'type=pc-q35-3.1+pve0'
diff --git a/src/test/cfg2cmd/q35-ide.conf.cmd b/src/test/cfg2cmd/q35-ide.conf.cmd
index f94accb9..df3106b7 100644
--- a/src/test/cfg2cmd/q35-ide.conf.cmd
+++ b/src/test/cfg2cmd/q35-ide.conf.cmd
@@ -30,16 +30,16 @@
   -device 'virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3,free-page-reporting=on' \
   -iscsi 'initiator-name=iqn.1993-08.org.debian:01:aabbccddeeff' \
   -blockdev '{"driver":"throttle","file":{"cache":{"direct":false,"no-flush":false},"driver":"raw","file":{"aio":"threads","cache":{"direct":false,"no-flush":false},"driver":"file","filename":"/mnt/pve/cifs-store/template/iso/zero.iso","node-name":"e1677eafc00b7016099210662868e38","read-only":true},"node-name":"f1677eafc00b7016099210662868e38","read-only":true},"node-name":"drive-ide0","throttle-group":"throttle-drive-ide0"}' \
-  -device 'ide-cd,bus=ide.0,unit=0,drive=drive-ide0,id=ide0,bootindex=200' \
+  -device '{"bootindex":200,"bus":"ide.0","drive":"drive-ide0","driver":"ide-cd","id":"ide0","unit":0}' \
   -blockdev '{"driver":"throttle","file":{"cache":{"direct":false,"no-flush":false},"driver":"raw","file":{"aio":"threads","cache":{"direct":false,"no-flush":false},"driver":"file","filename":"/mnt/pve/cifs-store/template/iso/one.iso","node-name":"e247a6535f864815c8e9dbb5a118336","read-only":true},"node-name":"f247a6535f864815c8e9dbb5a118336","read-only":true},"node-name":"drive-ide1","throttle-group":"throttle-drive-ide1"}' \
-  -device 'ide-cd,bus=ide.2,unit=0,drive=drive-ide1,id=ide1,bootindex=201' \
+  -device '{"bootindex":201,"bus":"ide.2","drive":"drive-ide1","driver":"ide-cd","id":"ide1","unit":0}' \
   -blockdev '{"driver":"throttle","file":{"cache":{"direct":false,"no-flush":false},"driver":"raw","file":{"aio":"threads","cache":{"direct":false,"no-flush":false},"driver":"file","filename":"/mnt/pve/cifs-store/template/iso/two.iso","node-name":"ec78a64f692c2fa9f873a111580aebd","read-only":true},"node-name":"fc78a64f692c2fa9f873a111580aebd","read-only":true},"node-name":"drive-ide2","throttle-group":"throttle-drive-ide2"}' \
-  -device 'ide-cd,bus=ide.1,unit=0,drive=drive-ide2,id=ide2,bootindex=202' \
+  -device '{"bootindex":202,"bus":"ide.1","drive":"drive-ide2","driver":"ide-cd","id":"ide2","unit":0}' \
   -blockdev '{"driver":"throttle","file":{"cache":{"direct":false,"no-flush":false},"driver":"raw","file":{"aio":"threads","cache":{"direct":false,"no-flush":false},"driver":"file","filename":"/mnt/pve/cifs-store/template/iso/three.iso","node-name":"e35557bae4bcbf9edc9f7ff7f132f30","read-only":true},"node-name":"f35557bae4bcbf9edc9f7ff7f132f30","read-only":true},"node-name":"drive-ide3","throttle-group":"throttle-drive-ide3"}' \
-  -device 'ide-cd,bus=ide.3,unit=0,drive=drive-ide3,id=ide3,bootindex=203' \
-  -device 'virtio-scsi-pci,id=scsihw0,bus=pci.0,addr=0x5' \
+  -device '{"bootindex":203,"bus":"ide.3","drive":"drive-ide3","driver":"ide-cd","id":"ide3","unit":0}' \
+  -device '{"addr":"0x5","bus":"pci.0","driver":"virtio-scsi-pci","id":"scsihw0"}' \
   -blockdev '{"driver":"throttle","file":{"cache":{"direct":true,"no-flush":false},"driver":"qcow2","file":{"aio":"io_uring","cache":{"direct":true,"no-flush":false},"detect-zeroes":"on","discard":"ignore","driver":"file","filename":"/var/lib/vz/images/100/vm-100-disk-2.qcow2","node-name":"ec11e0572184321efc5835152b95d5d","read-only":false},"node-name":"fc11e0572184321efc5835152b95d5d","read-only":false},"node-name":"drive-scsi0","throttle-group":"throttle-drive-scsi0"}' \
-  -device 'scsi-hd,bus=scsihw0.0,channel=0,scsi-id=0,lun=0,drive=drive-scsi0,id=scsi0,bootindex=100,write-cache=on' \
+  -device '{"bootindex":100,"bus":"scsihw0.0","channel":0,"drive":"drive-scsi0","driver":"scsi-hd","id":"scsi0","lun":0,"scsi-id":0,"write-cache":"on"}' \
   -netdev 'type=tap,id=net0,ifname=tap8006i0,script=/usr/libexec/qemu-server/pve-bridge,downscript=/usr/libexec/qemu-server/pve-bridgedown,vhost=on' \
   -device 'virtio-net-pci,mac=2E:01:68:F9:9C:87,netdev=net0,bus=pci.0,addr=0x12,id=net0,rx_queue_size=1024,tx_queue_size=256,bootindex=300' \
   -machine 'type=q35+pve0'
diff --git a/src/test/cfg2cmd/q35-linux-hostpci-template.conf.cmd b/src/test/cfg2cmd/q35-linux-hostpci-template.conf.cmd
index ddc87814..4d8edab9 100644
--- a/src/test/cfg2cmd/q35-linux-hostpci-template.conf.cmd
+++ b/src/test/cfg2cmd/q35-linux-hostpci-template.conf.cmd
@@ -27,8 +27,8 @@
   -device 'usb-tablet,id=tablet,bus=uhci.0,port=1' \
   -device 'virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3,free-page-reporting=on' \
   -iscsi 'initiator-name=iqn.1993-08.org.debian:01:aabbccddeeff' \
-  -device 'virtio-scsi-pci,id=scsihw0,bus=pci.0,addr=0x5' \
+  -device '{"addr":"0x5","bus":"pci.0","driver":"virtio-scsi-pci","id":"scsihw0"}' \
   -blockdev '{"driver":"throttle","file":{"cache":{"direct":true,"no-flush":false},"driver":"raw","file":{"aio":"io_uring","cache":{"direct":true,"no-flush":false},"detect-zeroes":"on","discard":"ignore","driver":"file","filename":"/var/lib/vz/images/100/base-100-disk-2.raw","node-name":"e24dfe239201bb9924fc4cfb899ca70","read-only":true},"node-name":"f24dfe239201bb9924fc4cfb899ca70","read-only":true},"node-name":"drive-scsi0","throttle-group":"throttle-drive-scsi0"}' \
-  -device 'scsi-hd,bus=scsihw0.0,channel=0,scsi-id=0,lun=0,drive=drive-scsi0,id=scsi0,write-cache=on' \
+  -device '{"bus":"scsihw0.0","channel":0,"drive":"drive-scsi0","driver":"scsi-hd","id":"scsi0","lun":0,"scsi-id":0,"write-cache":"on"}' \
   -machine 'pflash0=pflash0,pflash1=drive-efidisk0,accel=tcg,type=pc+pve0' \
   -snapshot
diff --git a/src/test/cfg2cmd/seabios_serial.conf.cmd b/src/test/cfg2cmd/seabios_serial.conf.cmd
index fc421d16..3d769cc4 100644
--- a/src/test/cfg2cmd/seabios_serial.conf.cmd
+++ b/src/test/cfg2cmd/seabios_serial.conf.cmd
@@ -26,10 +26,10 @@
   -device 'isa-serial,chardev=serial0' \
   -device 'virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3,free-page-reporting=on' \
   -iscsi 'initiator-name=iqn.1993-08.org.debian:01:aabbccddeeff' \
-  -device 'ide-cd,bus=ide.1,unit=0,id=ide2,bootindex=200' \
-  -device 'virtio-scsi-pci,id=scsihw0,bus=pci.0,addr=0x5' \
+  -device '{"bootindex":200,"bus":"ide.1","driver":"ide-cd","id":"ide2","unit":0}' \
+  -device '{"addr":"0x5","bus":"pci.0","driver":"virtio-scsi-pci","id":"scsihw0"}' \
   -blockdev '{"driver":"throttle","file":{"cache":{"direct":true,"no-flush":false},"driver":"qcow2","file":{"aio":"io_uring","cache":{"direct":true,"no-flush":false},"detect-zeroes":"unmap","discard":"unmap","driver":"file","filename":"/var/lib/vz/images/8006/vm-8006-disk-0.qcow2","node-name":"ecd04be4259153b8293415fefa2a84c","read-only":false},"node-name":"fcd04be4259153b8293415fefa2a84c","read-only":false},"node-name":"drive-scsi0","throttle-group":"throttle-drive-scsi0"}' \
-  -device 'scsi-hd,bus=scsihw0.0,channel=0,scsi-id=0,lun=0,drive=drive-scsi0,id=scsi0,bootindex=100,write-cache=on' \
+  -device '{"bootindex":100,"bus":"scsihw0.0","channel":0,"drive":"drive-scsi0","driver":"scsi-hd","id":"scsi0","lun":0,"scsi-id":0,"write-cache":"on"}' \
   -netdev 'type=tap,id=net0,ifname=tap8006i0,script=/usr/libexec/qemu-server/pve-bridge,downscript=/usr/libexec/qemu-server/pve-bridgedown,vhost=on' \
   -device 'virtio-net-pci,mac=A2:C0:43:77:08:A0,netdev=net0,bus=pci.0,addr=0x12,id=net0,rx_queue_size=1024,tx_queue_size=256,bootindex=300' \
   -machine 'smm=off,type=pc+pve0'
diff --git a/src/test/cfg2cmd/simple-backingchain.conf.cmd b/src/test/cfg2cmd/simple-backingchain.conf.cmd
index 40c957f5..0dae9e05 100644
--- a/src/test/cfg2cmd/simple-backingchain.conf.cmd
+++ b/src/test/cfg2cmd/simple-backingchain.conf.cmd
@@ -25,9 +25,9 @@
   -device 'VGA,id=vga,bus=pci.0,addr=0x2' \
   -device 'virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3,free-page-reporting=on' \
   -iscsi 'initiator-name=iqn.1993-08.org.debian:01:aabbccddeeff' \
-  -device 'lsi,id=scsihw0,bus=pci.0,addr=0x5' \
+  -device '{"addr":"0x5","bus":"pci.0","driver":"lsi","id":"scsihw0"}' \
   -blockdev '{"driver":"throttle","file":{"backing":{"backing":{"cache":{"direct":true,"no-flush":false},"driver":"qcow2","file":{"aio":"io_uring","cache":{"direct":true,"no-flush":false},"detect-zeroes":"on","discard":"ignore","driver":"file","filename":"/var/lib/vzsnapext/images/8006/snap1-vm-8006-disk-0.qcow2","node-name":"ea91a385a49a008a4735c0aec5c6749","read-only":false},"node-name":"fa91a385a49a008a4735c0aec5c6749","read-only":false},"cache":{"direct":true,"no-flush":false},"driver":"qcow2","file":{"aio":"io_uring","cache":{"direct":true,"no-flush":false},"detect-zeroes":"on","discard":"ignore","driver":"file","filename":"/var/lib/vzsnapext/images/8006/snap2-vm-8006-disk-0.qcow2","node-name":"ec0289317073959d450248d8cd7a480","read-only":false},"node-name":"fc0289317073959d450248d8cd7a480","read-only":false},"cache":{"direct":true,"no-flush":false},"driver":"qcow2","file":{"aio":"io_uring","cache":{"direct":true,"no-flush":false},"detect-zeroes":"on","discard":"ignore","driver":"file","filename":"/var/lib/vzsnapext/images/8006/vm-8006-disk-0.qcow2","node-name":"e74f4959037afb46eddc7313c43dfdd","read-only":false},"node-name":"f74f4959037afb46eddc7313c43dfdd","read-only":false},"node-name":"drive-scsi0","throttle-group":"throttle-drive-scsi0"}' \
-  -device 'scsi-hd,bus=scsihw0.0,scsi-id=0,drive=drive-scsi0,id=scsi0,write-cache=on' \
+  -device '{"bus":"scsihw0.0","drive":"drive-scsi0","driver":"scsi-hd","id":"scsi0","scsi-id":0,"write-cache":"on"}' \
   -blockdev '{"driver":"throttle","file":{"backing":{"backing":{"cache":{"direct":true,"no-flush":false},"driver":"qcow2","file":{"aio":"native","cache":{"direct":true,"no-flush":false},"detect-zeroes":"on","discard":"ignore","driver":"host_device","filename":"/dev/veegee/snap1-vm-8006-disk-0.qcow2","node-name":"e25f58d3e6e11f2065ad41253988915","read-only":false},"node-name":"f25f58d3e6e11f2065ad41253988915","read-only":false},"cache":{"direct":true,"no-flush":false},"driver":"qcow2","file":{"aio":"native","cache":{"direct":true,"no-flush":false},"detect-zeroes":"on","discard":"ignore","driver":"host_device","filename":"/dev/veegee/snap2-vm-8006-disk-0.qcow2","node-name":"e9415bb5e484c1e25d25063b01686fe","read-only":false},"node-name":"f9415bb5e484c1e25d25063b01686fe","read-only":false},"cache":{"direct":true,"no-flush":false},"driver":"qcow2","file":{"aio":"native","cache":{"direct":true,"no-flush":false},"detect-zeroes":"on","discard":"ignore","driver":"host_device","filename":"/dev/veegee/vm-8006-disk-0.qcow2","node-name":"e87358a470ca311f94d5cc61d1eb428","read-only":false},"node-name":"f87358a470ca311f94d5cc61d1eb428","read-only":false},"node-name":"drive-scsi1","throttle-group":"throttle-drive-scsi1"}' \
-  -device 'scsi-hd,bus=scsihw0.0,scsi-id=1,drive=drive-scsi1,id=scsi1,write-cache=on' \
+  -device '{"bus":"scsihw0.0","drive":"drive-scsi1","driver":"scsi-hd","id":"scsi1","scsi-id":1,"write-cache":"on"}' \
   -machine 'type=pc+pve0'
diff --git a/src/test/cfg2cmd/simple-balloon-free-page-reporting.conf.cmd b/src/test/cfg2cmd/simple-balloon-free-page-reporting.conf.cmd
index 0c61d334..a9364443 100644
--- a/src/test/cfg2cmd/simple-balloon-free-page-reporting.conf.cmd
+++ b/src/test/cfg2cmd/simple-balloon-free-page-reporting.conf.cmd
@@ -24,10 +24,10 @@
   -device 'virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3,free-page-reporting=on' \
   -iscsi 'initiator-name=iqn.1993-08.org.debian:01:aabbccddeeff' \
   -drive 'if=none,id=drive-ide2,media=cdrom,aio=io_uring' \
-  -device 'ide-cd,bus=ide.1,unit=0,drive=drive-ide2,id=ide2,bootindex=200' \
-  -device 'virtio-scsi-pci,id=scsihw0,bus=pci.0,addr=0x5' \
+  -device '{"bootindex":200,"bus":"ide.1","drive":"drive-ide2","driver":"ide-cd","id":"ide2","unit":0}' \
+  -device '{"addr":"0x5","bus":"pci.0","driver":"virtio-scsi-pci","id":"scsihw0"}' \
   -drive 'file=/var/lib/vz/images/8006/vm-8006-disk-0.qcow2,if=none,id=drive-scsi0,discard=on,format=qcow2,cache=none,aio=io_uring,detect-zeroes=unmap' \
-  -device 'scsi-hd,bus=scsihw0.0,channel=0,scsi-id=0,lun=0,drive=drive-scsi0,id=scsi0,bootindex=100' \
+  -device '{"bootindex":100,"bus":"scsihw0.0","channel":0,"drive":"drive-scsi0","driver":"scsi-hd","id":"scsi0","lun":0,"scsi-id":0}' \
   -netdev 'type=tap,id=net0,ifname=tap8006i0,script=/usr/libexec/qemu-server/pve-bridge,downscript=/usr/libexec/qemu-server/pve-bridgedown,vhost=on' \
   -device 'virtio-net-pci,mac=A2:C0:43:77:08:A0,netdev=net0,bus=pci.0,addr=0x12,id=net0,bootindex=300' \
   -machine 'type=pc-i440fx-6.2+pve0'
diff --git a/src/test/cfg2cmd/simple-btrfs.conf.cmd b/src/test/cfg2cmd/simple-btrfs.conf.cmd
index 810f1cc9..70c0233c 100644
--- a/src/test/cfg2cmd/simple-btrfs.conf.cmd
+++ b/src/test/cfg2cmd/simple-btrfs.conf.cmd
@@ -29,16 +29,16 @@
   -device 'VGA,id=vga,bus=pci.0,addr=0x2' \
   -device 'virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3,free-page-reporting=on' \
   -iscsi 'initiator-name=iqn.1993-08.org.debian:01:aabbccddeeff' \
-  -device 'ide-cd,bus=ide.1,unit=0,id=ide2,bootindex=200' \
-  -device 'virtio-scsi-pci,id=scsihw0,bus=pci.0,addr=0x5' \
+  -device '{"bootindex":200,"bus":"ide.1","driver":"ide-cd","id":"ide2","unit":0}' \
+  -device '{"addr":"0x5","bus":"pci.0","driver":"virtio-scsi-pci","id":"scsihw0"}' \
   -blockdev '{"driver":"throttle","file":{"cache":{"direct":false,"no-flush":false},"driver":"raw","file":{"aio":"io_uring","cache":{"direct":false,"no-flush":false},"detect-zeroes":"unmap","discard":"unmap","driver":"file","filename":"/butter/bread/images/8006/vm-8006-disk-0/disk.raw","node-name":"e99aff0ff797aa030a22e9f580076dd","read-only":false},"node-name":"f99aff0ff797aa030a22e9f580076dd","read-only":false},"node-name":"drive-scsi0","throttle-group":"throttle-drive-scsi0"}' \
-  -device 'scsi-hd,bus=scsihw0.0,channel=0,scsi-id=0,lun=0,drive=drive-scsi0,id=scsi0,bootindex=100,write-cache=on' \
+  -device '{"bootindex":100,"bus":"scsihw0.0","channel":0,"drive":"drive-scsi0","driver":"scsi-hd","id":"scsi0","lun":0,"scsi-id":0,"write-cache":"on"}' \
   -blockdev '{"driver":"throttle","file":{"cache":{"direct":false,"no-flush":false},"driver":"raw","file":{"aio":"io_uring","cache":{"direct":false,"no-flush":false},"detect-zeroes":"unmap","discard":"unmap","driver":"file","filename":"/butter/bread/images/8006/vm-8006-disk-0/disk.raw","node-name":"e7b2fd2a8c5dbfc550d9781e5df8841","read-only":false},"node-name":"f7b2fd2a8c5dbfc550d9781e5df8841","read-only":false},"node-name":"drive-scsi1","throttle-group":"throttle-drive-scsi1"}' \
-  -device 'scsi-hd,bus=scsihw0.0,channel=0,scsi-id=0,lun=1,drive=drive-scsi1,id=scsi1,write-cache=on' \
+  -device '{"bus":"scsihw0.0","channel":0,"drive":"drive-scsi1","driver":"scsi-hd","id":"scsi1","lun":1,"scsi-id":0,"write-cache":"on"}' \
   -blockdev '{"driver":"throttle","file":{"cache":{"direct":false,"no-flush":false},"driver":"raw","file":{"aio":"io_uring","cache":{"direct":false,"no-flush":false},"detect-zeroes":"unmap","discard":"unmap","driver":"file","filename":"/butter/bread/images/8006/vm-8006-disk-0/disk.raw","node-name":"ed78b07bb04c2cbd8aedc648e885569","read-only":false},"node-name":"fd78b07bb04c2cbd8aedc648e885569","read-only":false},"node-name":"drive-scsi2","throttle-group":"throttle-drive-scsi2"}' \
-  -device 'scsi-hd,bus=scsihw0.0,channel=0,scsi-id=0,lun=2,drive=drive-scsi2,id=scsi2,write-cache=off' \
+  -device '{"bus":"scsihw0.0","channel":0,"drive":"drive-scsi2","driver":"scsi-hd","id":"scsi2","lun":2,"scsi-id":0,"write-cache":"off"}' \
   -blockdev '{"driver":"throttle","file":{"cache":{"direct":true,"no-flush":false},"driver":"raw","file":{"aio":"io_uring","cache":{"direct":true,"no-flush":false},"detect-zeroes":"unmap","discard":"unmap","driver":"file","filename":"/butter/bread/images/8006/vm-8006-disk-0/disk.raw","node-name":"e7487c01d831e2b51a5446980170ec9","read-only":false},"node-name":"f7487c01d831e2b51a5446980170ec9","read-only":false},"node-name":"drive-scsi3","throttle-group":"throttle-drive-scsi3"}' \
-  -device 'scsi-hd,bus=scsihw0.0,channel=0,scsi-id=0,lun=3,drive=drive-scsi3,id=scsi3,write-cache=off' \
+  -device '{"bus":"scsihw0.0","channel":0,"drive":"drive-scsi3","driver":"scsi-hd","id":"scsi3","lun":3,"scsi-id":0,"write-cache":"off"}' \
   -netdev 'type=tap,id=net0,ifname=tap8006i0,script=/usr/libexec/qemu-server/pve-bridge,downscript=/usr/libexec/qemu-server/pve-bridgedown,vhost=on' \
   -device 'virtio-net-pci,mac=A2:C0:43:77:08:A0,netdev=net0,bus=pci.0,addr=0x12,id=net0,rx_queue_size=1024,tx_queue_size=256,bootindex=300' \
   -machine 'type=pc+pve0'
diff --git a/src/test/cfg2cmd/simple-cifs.conf.cmd b/src/test/cfg2cmd/simple-cifs.conf.cmd
index 8723bfff..6a8335b8 100644
--- a/src/test/cfg2cmd/simple-cifs.conf.cmd
+++ b/src/test/cfg2cmd/simple-cifs.conf.cmd
@@ -27,14 +27,14 @@
   -device 'VGA,id=vga,bus=pci.0,addr=0x2' \
   -device 'virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3,free-page-reporting=on' \
   -iscsi 'initiator-name=iqn.1993-08.org.debian:01:aabbccddeeff' \
-  -device 'ide-cd,bus=ide.1,unit=0,id=ide2,bootindex=200' \
-  -device 'virtio-scsi-pci,id=scsihw0,bus=pci.0,addr=0x5' \
+  -device '{"bootindex":200,"bus":"ide.1","driver":"ide-cd","id":"ide2","unit":0}' \
+  -device '{"addr":"0x5","bus":"pci.0","driver":"virtio-scsi-pci","id":"scsihw0"}' \
   -blockdev '{"driver":"throttle","file":{"cache":{"direct":true,"no-flush":false},"driver":"raw","file":{"aio":"native","cache":{"direct":true,"no-flush":false},"detect-zeroes":"unmap","discard":"unmap","driver":"file","filename":"/mnt/pve/cifs-store/images/8006/vm-8006-disk-0.raw","node-name":"e2b3b8f2d6a23adc1aa3ecd195dbaf5","read-only":false},"node-name":"f2b3b8f2d6a23adc1aa3ecd195dbaf5","read-only":false},"node-name":"drive-scsi0","throttle-group":"throttle-drive-scsi0"}' \
-  -device 'scsi-hd,bus=scsihw0.0,channel=0,scsi-id=0,lun=0,drive=drive-scsi0,id=scsi0,write-cache=on' \
+  -device '{"bus":"scsihw0.0","channel":0,"drive":"drive-scsi0","driver":"scsi-hd","id":"scsi0","lun":0,"scsi-id":0,"write-cache":"on"}' \
   -blockdev '{"driver":"throttle","file":{"cache":{"direct":false,"no-flush":false},"driver":"raw","file":{"aio":"threads","cache":{"direct":false,"no-flush":false},"detect-zeroes":"unmap","discard":"unmap","driver":"file","filename":"/mnt/pve/cifs-store/images/8006/vm-8006-disk-0.raw","node-name":"ee4d9a961200a669c1a8182632aba3e","read-only":false},"node-name":"fe4d9a961200a669c1a8182632aba3e","read-only":false},"node-name":"drive-scsi1","throttle-group":"throttle-drive-scsi1"}' \
-  -device 'scsi-hd,bus=scsihw0.0,channel=0,scsi-id=0,lun=1,drive=drive-scsi1,id=scsi1,write-cache=on' \
+  -device '{"bus":"scsihw0.0","channel":0,"drive":"drive-scsi1","driver":"scsi-hd","id":"scsi1","lun":1,"scsi-id":0,"write-cache":"on"}' \
   -blockdev '{"driver":"throttle","file":{"cache":{"direct":false,"no-flush":false},"driver":"raw","file":{"aio":"threads","cache":{"direct":false,"no-flush":false},"detect-zeroes":"unmap","discard":"unmap","driver":"file","filename":"/mnt/pve/cifs-store/images/8006/vm-8006-disk-0.raw","node-name":"e6a3bf7eee1e2636cbe31f62b537b6c","read-only":false},"node-name":"f6a3bf7eee1e2636cbe31f62b537b6c","read-only":false},"node-name":"drive-scsi2","throttle-group":"throttle-drive-scsi2"}' \
-  -device 'scsi-hd,bus=scsihw0.0,channel=0,scsi-id=0,lun=2,drive=drive-scsi2,id=scsi2,write-cache=off' \
+  -device '{"bus":"scsihw0.0","channel":0,"drive":"drive-scsi2","driver":"scsi-hd","id":"scsi2","lun":2,"scsi-id":0,"write-cache":"off"}' \
   -blockdev '{"driver":"throttle","file":{"cache":{"direct":true,"no-flush":false},"driver":"raw","file":{"aio":"native","cache":{"direct":true,"no-flush":false},"detect-zeroes":"unmap","discard":"unmap","driver":"file","filename":"/mnt/pve/cifs-store/images/8006/vm-8006-disk-0.raw","node-name":"e7042ee58e764b1296ad54014cb9a03","read-only":false},"node-name":"f7042ee58e764b1296ad54014cb9a03","read-only":false},"node-name":"drive-scsi3","throttle-group":"throttle-drive-scsi3"}' \
-  -device 'scsi-hd,bus=scsihw0.0,channel=0,scsi-id=0,lun=3,drive=drive-scsi3,id=scsi3,write-cache=off' \
+  -device '{"bus":"scsihw0.0","channel":0,"drive":"drive-scsi3","driver":"scsi-hd","id":"scsi3","lun":3,"scsi-id":0,"write-cache":"off"}' \
   -machine 'type=pc+pve0'
diff --git a/src/test/cfg2cmd/simple-disk-passthrough.conf.cmd b/src/test/cfg2cmd/simple-disk-passthrough.conf.cmd
index 58368210..4ba0de17 100644
--- a/src/test/cfg2cmd/simple-disk-passthrough.conf.cmd
+++ b/src/test/cfg2cmd/simple-disk-passthrough.conf.cmd
@@ -29,12 +29,12 @@
   -device 'virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3,free-page-reporting=on' \
   -iscsi 'initiator-name=iqn.1993-08.org.debian:01:aabbccddeeff' \
   -blockdev '{"driver":"throttle","file":{"cache":{"direct":false,"no-flush":false},"driver":"raw","file":{"aio":"io_uring","cache":{"direct":false,"no-flush":false},"driver":"host_cdrom","filename":"/dev/cdrom","node-name":"ee50e59431a6228dc388fc821b35696","read-only":true},"node-name":"fe50e59431a6228dc388fc821b35696","read-only":true},"node-name":"drive-ide2","throttle-group":"throttle-drive-ide2"}' \
-  -device 'ide-cd,bus=ide.1,unit=0,drive=drive-ide2,id=ide2,bootindex=200' \
-  -device 'virtio-scsi-pci,id=scsihw0,bus=pci.0,addr=0x5' \
+  -device '{"bootindex":200,"bus":"ide.1","drive":"drive-ide2","driver":"ide-cd","id":"ide2","unit":0}' \
+  -device '{"addr":"0x5","bus":"pci.0","driver":"virtio-scsi-pci","id":"scsihw0"}' \
   -blockdev '{"driver":"throttle","file":{"cache":{"direct":true,"no-flush":false},"driver":"raw","file":{"aio":"io_uring","cache":{"direct":true,"no-flush":false},"detect-zeroes":"on","discard":"ignore","driver":"host_device","filename":"/dev/sda","node-name":"eec235c1b362ebd19d5e98959b4c171","read-only":false},"node-name":"fec235c1b362ebd19d5e98959b4c171","read-only":false},"node-name":"drive-scsi0","throttle-group":"throttle-drive-scsi0"}' \
-  -device 'scsi-hd,bus=scsihw0.0,channel=0,scsi-id=0,lun=0,drive=drive-scsi0,id=scsi0,bootindex=100,write-cache=on' \
+  -device '{"bootindex":100,"bus":"scsihw0.0","channel":0,"drive":"drive-scsi0","driver":"scsi-hd","id":"scsi0","lun":0,"scsi-id":0,"write-cache":"on"}' \
   -blockdev '{"driver":"throttle","file":{"cache":{"direct":true,"no-flush":false},"driver":"raw","file":{"aio":"io_uring","cache":{"direct":true,"no-flush":false},"detect-zeroes":"on","discard":"ignore","driver":"file","filename":"/mnt/file.raw","node-name":"e234a4e3b89ac3adac9bdbf0c3dd6b4","read-only":false},"node-name":"f234a4e3b89ac3adac9bdbf0c3dd6b4","read-only":false},"node-name":"drive-scsi1","throttle-group":"throttle-drive-scsi1"}' \
-  -device 'scsi-hd,bus=scsihw0.0,channel=0,scsi-id=0,lun=1,drive=drive-scsi1,id=scsi1,write-cache=on' \
+  -device '{"bus":"scsihw0.0","channel":0,"drive":"drive-scsi1","driver":"scsi-hd","id":"scsi1","lun":1,"scsi-id":0,"write-cache":"on"}' \
   -netdev 'type=tap,id=net0,ifname=tap8006i0,script=/usr/libexec/qemu-server/pve-bridge,downscript=/usr/libexec/qemu-server/pve-bridgedown,vhost=on' \
   -device 'virtio-net-pci,mac=A2:C0:43:77:08:A0,netdev=net0,bus=pci.0,addr=0x12,id=net0,rx_queue_size=1024,tx_queue_size=256,bootindex=300' \
   -machine 'type=pc+pve0'
diff --git a/src/test/cfg2cmd/simple-lvm.conf.cmd b/src/test/cfg2cmd/simple-lvm.conf.cmd
index 650f0ac3..316a5f9e 100644
--- a/src/test/cfg2cmd/simple-lvm.conf.cmd
+++ b/src/test/cfg2cmd/simple-lvm.conf.cmd
@@ -27,13 +27,13 @@
   -device 'VGA,id=vga,bus=pci.0,addr=0x2' \
   -device 'virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3,free-page-reporting=on' \
   -iscsi 'initiator-name=iqn.1993-08.org.debian:01:aabbccddeeff' \
-  -device 'virtio-scsi-pci,id=scsihw0,bus=pci.0,addr=0x5' \
+  -device '{"addr":"0x5","bus":"pci.0","driver":"virtio-scsi-pci","id":"scsihw0"}' \
   -blockdev '{"driver":"throttle","file":{"cache":{"direct":true,"no-flush":false},"driver":"raw","file":{"aio":"native","cache":{"direct":true,"no-flush":false},"detect-zeroes":"unmap","discard":"unmap","driver":"host_device","filename":"/dev/veegee/vm-8006-disk-0","node-name":"e0378a375d635b0f473569544c7c207","read-only":false},"node-name":"f0378a375d635b0f473569544c7c207","read-only":false},"node-name":"drive-scsi0","throttle-group":"throttle-drive-scsi0"}' \
-  -device 'scsi-hd,bus=scsihw0.0,channel=0,scsi-id=0,lun=0,drive=drive-scsi0,id=scsi0,bootindex=100,write-cache=on' \
+  -device '{"bootindex":100,"bus":"scsihw0.0","channel":0,"drive":"drive-scsi0","driver":"scsi-hd","id":"scsi0","lun":0,"scsi-id":0,"write-cache":"on"}' \
   -blockdev '{"driver":"throttle","file":{"cache":{"direct":false,"no-flush":false},"driver":"raw","file":{"aio":"threads","cache":{"direct":false,"no-flush":false},"detect-zeroes":"unmap","discard":"unmap","driver":"host_device","filename":"/dev/veegee/vm-8006-disk-0","node-name":"e2fbae024c8a771f708f4a5391211b0","read-only":false},"node-name":"f2fbae024c8a771f708f4a5391211b0","read-only":false},"node-name":"drive-scsi1","throttle-group":"throttle-drive-scsi1"}' \
-  -device 'scsi-hd,bus=scsihw0.0,channel=0,scsi-id=0,lun=1,drive=drive-scsi1,id=scsi1,write-cache=on' \
+  -device '{"bus":"scsihw0.0","channel":0,"drive":"drive-scsi1","driver":"scsi-hd","id":"scsi1","lun":1,"scsi-id":0,"write-cache":"on"}' \
   -blockdev '{"driver":"throttle","file":{"cache":{"direct":false,"no-flush":false},"driver":"raw","file":{"aio":"threads","cache":{"direct":false,"no-flush":false},"detect-zeroes":"unmap","discard":"unmap","driver":"host_device","filename":"/dev/veegee/vm-8006-disk-0","node-name":"e4328c26b141e3efe1564cb60bf1155","read-only":false},"node-name":"f4328c26b141e3efe1564cb60bf1155","read-only":false},"node-name":"drive-scsi2","throttle-group":"throttle-drive-scsi2"}' \
-  -device 'scsi-hd,bus=scsihw0.0,channel=0,scsi-id=0,lun=2,drive=drive-scsi2,id=scsi2,write-cache=off' \
+  -device '{"bus":"scsihw0.0","channel":0,"drive":"drive-scsi2","driver":"scsi-hd","id":"scsi2","lun":2,"scsi-id":0,"write-cache":"off"}' \
   -blockdev '{"driver":"throttle","file":{"cache":{"direct":true,"no-flush":false},"driver":"raw","file":{"aio":"native","cache":{"direct":true,"no-flush":false},"detect-zeroes":"unmap","discard":"unmap","driver":"host_device","filename":"/dev/veegee/vm-8006-disk-0","node-name":"e68e10f8128f05fe5f7e85cc1f9922b","read-only":false},"node-name":"f68e10f8128f05fe5f7e85cc1f9922b","read-only":false},"node-name":"drive-scsi3","throttle-group":"throttle-drive-scsi3"}' \
-  -device 'scsi-hd,bus=scsihw0.0,channel=0,scsi-id=0,lun=3,drive=drive-scsi3,id=scsi3,write-cache=off' \
+  -device '{"bus":"scsihw0.0","channel":0,"drive":"drive-scsi3","driver":"scsi-hd","id":"scsi3","lun":3,"scsi-id":0,"write-cache":"off"}' \
   -machine 'type=pc+pve0'
diff --git a/src/test/cfg2cmd/simple-lvmthin.conf.cmd b/src/test/cfg2cmd/simple-lvmthin.conf.cmd
index 22251bc6..6cb1b1c1 100644
--- a/src/test/cfg2cmd/simple-lvmthin.conf.cmd
+++ b/src/test/cfg2cmd/simple-lvmthin.conf.cmd
@@ -27,13 +27,13 @@
   -device 'VGA,id=vga,bus=pci.0,addr=0x2' \
   -device 'virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3,free-page-reporting=on' \
   -iscsi 'initiator-name=iqn.1993-08.org.debian:01:aabbccddeeff' \
-  -device 'virtio-scsi-pci,id=scsihw0,bus=pci.0,addr=0x5' \
+  -device '{"addr":"0x5","bus":"pci.0","driver":"virtio-scsi-pci","id":"scsihw0"}' \
   -blockdev '{"driver":"throttle","file":{"cache":{"direct":true,"no-flush":false},"driver":"raw","file":{"aio":"io_uring","cache":{"direct":true,"no-flush":false},"detect-zeroes":"unmap","discard":"unmap","driver":"host_device","filename":"/dev/pve/vm-8006-disk-0","node-name":"e6d87b01b7bb888b8426534a542ff1c","read-only":false},"node-name":"f6d87b01b7bb888b8426534a542ff1c","read-only":false},"node-name":"drive-scsi0","throttle-group":"throttle-drive-scsi0"}' \
-  -device 'scsi-hd,bus=scsihw0.0,channel=0,scsi-id=0,lun=0,drive=drive-scsi0,id=scsi0,bootindex=100,write-cache=on' \
+  -device '{"bootindex":100,"bus":"scsihw0.0","channel":0,"drive":"drive-scsi0","driver":"scsi-hd","id":"scsi0","lun":0,"scsi-id":0,"write-cache":"on"}' \
   -blockdev '{"driver":"throttle","file":{"cache":{"direct":false,"no-flush":false},"driver":"raw","file":{"aio":"io_uring","cache":{"direct":false,"no-flush":false},"detect-zeroes":"unmap","discard":"unmap","driver":"host_device","filename":"/dev/pve/vm-8006-disk-0","node-name":"e96d9ece81aa4271aa2d8485184f66b","read-only":false},"node-name":"f96d9ece81aa4271aa2d8485184f66b","read-only":false},"node-name":"drive-scsi1","throttle-group":"throttle-drive-scsi1"}' \
-  -device 'scsi-hd,bus=scsihw0.0,channel=0,scsi-id=0,lun=1,drive=drive-scsi1,id=scsi1,write-cache=on' \
+  -device '{"bus":"scsihw0.0","channel":0,"drive":"drive-scsi1","driver":"scsi-hd","id":"scsi1","lun":1,"scsi-id":0,"write-cache":"on"}' \
   -blockdev '{"driver":"throttle","file":{"cache":{"direct":false,"no-flush":false},"driver":"raw","file":{"aio":"io_uring","cache":{"direct":false,"no-flush":false},"detect-zeroes":"unmap","discard":"unmap","driver":"host_device","filename":"/dev/pve/vm-8006-disk-0","node-name":"e0b89788ef97beda10a850ab45897d9","read-only":false},"node-name":"f0b89788ef97beda10a850ab45897d9","read-only":false},"node-name":"drive-scsi2","throttle-group":"throttle-drive-scsi2"}' \
-  -device 'scsi-hd,bus=scsihw0.0,channel=0,scsi-id=0,lun=2,drive=drive-scsi2,id=scsi2,write-cache=off' \
+  -device '{"bus":"scsihw0.0","channel":0,"drive":"drive-scsi2","driver":"scsi-hd","id":"scsi2","lun":2,"scsi-id":0,"write-cache":"off"}' \
   -blockdev '{"driver":"throttle","file":{"cache":{"direct":true,"no-flush":false},"driver":"raw","file":{"aio":"io_uring","cache":{"direct":true,"no-flush":false},"detect-zeroes":"unmap","discard":"unmap","driver":"host_device","filename":"/dev/pve/vm-8006-disk-0","node-name":"ea7b6871af66ca3e13e95bd74570aa2","read-only":false},"node-name":"fa7b6871af66ca3e13e95bd74570aa2","read-only":false},"node-name":"drive-scsi3","throttle-group":"throttle-drive-scsi3"}' \
-  -device 'scsi-hd,bus=scsihw0.0,channel=0,scsi-id=0,lun=3,drive=drive-scsi3,id=scsi3,write-cache=off' \
+  -device '{"bus":"scsihw0.0","channel":0,"drive":"drive-scsi3","driver":"scsi-hd","id":"scsi3","lun":3,"scsi-id":0,"write-cache":"off"}' \
   -machine 'type=pc+pve0'
diff --git a/src/test/cfg2cmd/simple-rbd.conf.cmd b/src/test/cfg2cmd/simple-rbd.conf.cmd
index ee86afea..9a89ad97 100644
--- a/src/test/cfg2cmd/simple-rbd.conf.cmd
+++ b/src/test/cfg2cmd/simple-rbd.conf.cmd
@@ -33,24 +33,24 @@
   -device 'VGA,id=vga,bus=pci.0,addr=0x2' \
   -device 'virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3,free-page-reporting=on' \
   -iscsi 'initiator-name=iqn.1993-08.org.debian:01:aabbccddeeff' \
-  -device 'ide-cd,bus=ide.1,unit=0,id=ide2,bootindex=200' \
-  -device 'virtio-scsi-pci,id=scsihw0,bus=pci.0,addr=0x5' \
+  -device '{"bootindex":200,"bus":"ide.1","driver":"ide-cd","id":"ide2","unit":0}' \
+  -device '{"addr":"0x5","bus":"pci.0","driver":"virtio-scsi-pci","id":"scsihw0"}' \
   -blockdev '{"driver":"throttle","file":{"cache":{"direct":true,"no-flush":false},"driver":"raw","file":{"auth-client-required":["none"],"cache":{"direct":true,"no-flush":false},"detect-zeroes":"unmap","discard":"unmap","driver":"rbd","image":"vm-8006-disk-0","node-name":"e8e1af6f55c6a2466f178045aa79710","pool":"cpool","read-only":false,"server":[{"host":"127.0.0.42","port":"3300"},{"host":"127.0.0.21","port":"3300"},{"host":"::1","port":"3300"}]},"node-name":"f8e1af6f55c6a2466f178045aa79710","read-only":false},"node-name":"drive-scsi0","throttle-group":"throttle-drive-scsi0"}' \
-  -device 'scsi-hd,bus=scsihw0.0,channel=0,scsi-id=0,lun=0,drive=drive-scsi0,id=scsi0,bootindex=100,write-cache=on' \
+  -device '{"bootindex":100,"bus":"scsihw0.0","channel":0,"drive":"drive-scsi0","driver":"scsi-hd","id":"scsi0","lun":0,"scsi-id":0,"write-cache":"on"}' \
   -blockdev '{"driver":"throttle","file":{"cache":{"direct":false,"no-flush":false},"driver":"raw","file":{"auth-client-required":["none"],"cache":{"direct":false,"no-flush":false},"detect-zeroes":"unmap","discard":"unmap","driver":"rbd","image":"vm-8006-disk-0","node-name":"e3990bba2ed1f48c5bb23e9f37b4cec","pool":"cpool","read-only":false,"server":[{"host":"127.0.0.42","port":"3300"},{"host":"127.0.0.21","port":"3300"},{"host":"::1","port":"3300"}]},"node-name":"f3990bba2ed1f48c5bb23e9f37b4cec","read-only":false},"node-name":"drive-scsi1","throttle-group":"throttle-drive-scsi1"}' \
-  -device 'scsi-hd,bus=scsihw0.0,channel=0,scsi-id=0,lun=1,drive=drive-scsi1,id=scsi1,write-cache=on' \
+  -device '{"bus":"scsihw0.0","channel":0,"drive":"drive-scsi1","driver":"scsi-hd","id":"scsi1","lun":1,"scsi-id":0,"write-cache":"on"}' \
   -blockdev '{"driver":"throttle","file":{"cache":{"direct":false,"no-flush":false},"driver":"raw","file":{"auth-client-required":["none"],"cache":{"direct":false,"no-flush":false},"detect-zeroes":"unmap","discard":"unmap","driver":"rbd","image":"vm-8006-disk-0","node-name":"e3beccc2a8f2eacb8b5df8055a7d093","pool":"cpool","read-only":false,"server":[{"host":"127.0.0.42","port":"3300"},{"host":"127.0.0.21","port":"3300"},{"host":"::1","port":"3300"}]},"node-name":"f3beccc2a8f2eacb8b5df8055a7d093","read-only":false},"node-name":"drive-scsi2","throttle-group":"throttle-drive-scsi2"}' \
-  -device 'scsi-hd,bus=scsihw0.0,channel=0,scsi-id=0,lun=2,drive=drive-scsi2,id=scsi2,write-cache=off' \
+  -device '{"bus":"scsihw0.0","channel":0,"drive":"drive-scsi2","driver":"scsi-hd","id":"scsi2","lun":2,"scsi-id":0,"write-cache":"off"}' \
   -blockdev '{"driver":"throttle","file":{"cache":{"direct":true,"no-flush":false},"driver":"raw","file":{"auth-client-required":["none"],"cache":{"direct":true,"no-flush":false},"detect-zeroes":"unmap","discard":"unmap","driver":"rbd","image":"vm-8006-disk-0","node-name":"eef923d5dfcee93fbc712b03f9f21af","pool":"cpool","read-only":false,"server":[{"host":"127.0.0.42","port":"3300"},{"host":"127.0.0.21","port":"3300"},{"host":"::1","port":"3300"}]},"node-name":"fef923d5dfcee93fbc712b03f9f21af","read-only":false},"node-name":"drive-scsi3","throttle-group":"throttle-drive-scsi3"}' \
-  -device 'scsi-hd,bus=scsihw0.0,channel=0,scsi-id=0,lun=3,drive=drive-scsi3,id=scsi3,write-cache=off' \
+  -device '{"bus":"scsihw0.0","channel":0,"drive":"drive-scsi3","driver":"scsi-hd","id":"scsi3","lun":3,"scsi-id":0,"write-cache":"off"}' \
   -blockdev '{"driver":"throttle","file":{"cache":{"direct":true,"no-flush":false},"driver":"raw","file":{"aio":"io_uring","cache":{"direct":true,"no-flush":false},"detect-zeroes":"unmap","discard":"unmap","driver":"host_device","filename":"/dev/rbd-pve/fc4181a6-56eb-4f68-b452-8ba1f381ca2a/cpool/vm-8006-disk-0","node-name":"eb2c7a292f03b9f6d015cf83ae79730","read-only":false},"node-name":"fb2c7a292f03b9f6d015cf83ae79730","read-only":false},"node-name":"drive-scsi4","throttle-group":"throttle-drive-scsi4"}' \
-  -device 'scsi-hd,bus=scsihw0.0,channel=0,scsi-id=0,lun=4,drive=drive-scsi4,id=scsi4,write-cache=on' \
+  -device '{"bus":"scsihw0.0","channel":0,"drive":"drive-scsi4","driver":"scsi-hd","id":"scsi4","lun":4,"scsi-id":0,"write-cache":"on"}' \
   -blockdev '{"driver":"throttle","file":{"cache":{"direct":false,"no-flush":false},"driver":"raw","file":{"aio":"threads","cache":{"direct":false,"no-flush":false},"detect-zeroes":"unmap","discard":"unmap","driver":"host_device","filename":"/dev/rbd-pve/fc4181a6-56eb-4f68-b452-8ba1f381ca2a/cpool/vm-8006-disk-0","node-name":"e5258ec75558b1f102af1e20e677fd0","read-only":false},"node-name":"f5258ec75558b1f102af1e20e677fd0","read-only":false},"node-name":"drive-scsi5","throttle-group":"throttle-drive-scsi5"}' \
-  -device 'scsi-hd,bus=scsihw0.0,channel=0,scsi-id=0,lun=5,drive=drive-scsi5,id=scsi5,write-cache=on' \
+  -device '{"bus":"scsihw0.0","channel":0,"drive":"drive-scsi5","driver":"scsi-hd","id":"scsi5","lun":5,"scsi-id":0,"write-cache":"on"}' \
   -blockdev '{"driver":"throttle","file":{"cache":{"direct":false,"no-flush":false},"driver":"raw","file":{"aio":"threads","cache":{"direct":false,"no-flush":false},"detect-zeroes":"unmap","discard":"unmap","driver":"host_device","filename":"/dev/rbd-pve/fc4181a6-56eb-4f68-b452-8ba1f381ca2a/cpool/vm-8006-disk-0","node-name":"edb33cdcea8ec3e2225509c4945227e","read-only":false},"node-name":"fdb33cdcea8ec3e2225509c4945227e","read-only":false},"node-name":"drive-scsi6","throttle-group":"throttle-drive-scsi6"}' \
-  -device 'scsi-hd,bus=scsihw0.0,channel=0,scsi-id=0,lun=6,drive=drive-scsi6,id=scsi6,write-cache=off' \
+  -device '{"bus":"scsihw0.0","channel":0,"drive":"drive-scsi6","driver":"scsi-hd","id":"scsi6","lun":6,"scsi-id":0,"write-cache":"off"}' \
   -blockdev '{"driver":"throttle","file":{"cache":{"direct":true,"no-flush":false},"driver":"raw","file":{"aio":"io_uring","cache":{"direct":true,"no-flush":false},"detect-zeroes":"unmap","discard":"unmap","driver":"host_device","filename":"/dev/rbd-pve/fc4181a6-56eb-4f68-b452-8ba1f381ca2a/cpool/vm-8006-disk-0","node-name":"eb0b017124a47505c97a5da052e0141","read-only":false},"node-name":"fb0b017124a47505c97a5da052e0141","read-only":false},"node-name":"drive-scsi7","throttle-group":"throttle-drive-scsi7"}' \
-  -device 'scsi-hd,bus=scsihw0.0,channel=0,scsi-id=0,lun=7,drive=drive-scsi7,id=scsi7,write-cache=off' \
+  -device '{"bus":"scsihw0.0","channel":0,"drive":"drive-scsi7","driver":"scsi-hd","id":"scsi7","lun":7,"scsi-id":0,"write-cache":"off"}' \
   -netdev 'type=tap,id=net0,ifname=tap8006i0,script=/usr/libexec/qemu-server/pve-bridge,downscript=/usr/libexec/qemu-server/pve-bridgedown,vhost=on' \
   -device 'virtio-net-pci,mac=A2:C0:43:77:08:A0,netdev=net0,bus=pci.0,addr=0x12,id=net0,rx_queue_size=1024,tx_queue_size=256,bootindex=300' \
   -machine 'type=pc+pve0'
diff --git a/src/test/cfg2cmd/simple-virtio-blk.conf.cmd b/src/test/cfg2cmd/simple-virtio-blk.conf.cmd
index 886f187b..e5e1d948 100644
--- a/src/test/cfg2cmd/simple-virtio-blk.conf.cmd
+++ b/src/test/cfg2cmd/simple-virtio-blk.conf.cmd
@@ -15,7 +15,7 @@
   -vnc 'unix:/var/run/qemu-server/8006.vnc,password=on' \
   -cpu kvm64,enforce,+kvm_pv_eoi,+kvm_pv_unhalt,+lahf_lm,+sep \
   -m 768 \
-  -object 'iothread,id=iothread-virtio0' \
+  -object '{"id":"iothread-virtio0","qom-type":"iothread"}' \
   -object '{"id":"throttle-drive-virtio0","limits":{},"qom-type":"throttle-group"}' \
   -global 'PIIX4_PM.disable_s3=1' \
   -global 'PIIX4_PM.disable_s4=1' \
@@ -27,9 +27,9 @@
   -device 'VGA,id=vga,bus=pci.0,addr=0x2' \
   -device 'virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3,free-page-reporting=on' \
   -iscsi 'initiator-name=iqn.1993-08.org.debian:01:aabbccddeeff' \
-  -device 'ide-cd,bus=ide.1,unit=0,id=ide2,bootindex=200' \
+  -device '{"bootindex":200,"bus":"ide.1","driver":"ide-cd","id":"ide2","unit":0}' \
   -blockdev '{"driver":"throttle","file":{"cache":{"direct":true,"no-flush":false},"driver":"qcow2","file":{"aio":"io_uring","cache":{"direct":true,"no-flush":false},"detect-zeroes":"unmap","discard":"unmap","driver":"file","filename":"/var/lib/vz/images/8006/vm-8006-disk-0.qcow2","node-name":"edd19f6c1b3a6d5a6248c3376a91a16","read-only":false},"node-name":"fdd19f6c1b3a6d5a6248c3376a91a16","read-only":false},"node-name":"drive-virtio0","throttle-group":"throttle-drive-virtio0"}' \
-  -device 'virtio-blk-pci,drive=drive-virtio0,id=virtio0,bus=pci.0,addr=0xa,iothread=iothread-virtio0,bootindex=100,write-cache=on' \
+  -device '{"addr":"0xa","bootindex":100,"bus":"pci.0","drive":"drive-virtio0","driver":"virtio-blk-pci","id":"virtio0","iothread":"iothread-virtio0","write-cache":"on"}' \
   -netdev 'type=tap,id=net0,ifname=tap8006i0,script=/usr/libexec/qemu-server/pve-bridge,downscript=/usr/libexec/qemu-server/pve-bridgedown,vhost=on' \
   -device 'virtio-net-pci,mac=A2:C0:43:77:08:A0,netdev=net0,bus=pci.0,addr=0x12,id=net0,rx_queue_size=1024,tx_queue_size=256,bootindex=300' \
   -machine 'type=pc+pve0'
diff --git a/src/test/cfg2cmd/simple-zfs-over-iscsi.conf.cmd b/src/test/cfg2cmd/simple-zfs-over-iscsi.conf.cmd
index 19302053..c07eaf38 100644
--- a/src/test/cfg2cmd/simple-zfs-over-iscsi.conf.cmd
+++ b/src/test/cfg2cmd/simple-zfs-over-iscsi.conf.cmd
@@ -29,16 +29,16 @@
   -device 'VGA,id=vga,bus=pci.0,addr=0x2' \
   -device 'virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3,free-page-reporting=on' \
   -iscsi 'initiator-name=iqn.1993-08.org.debian:01:aabbccddeeff' \
-  -device 'ide-cd,bus=ide.1,unit=0,id=ide2,bootindex=200' \
-  -device 'virtio-scsi-pci,id=scsihw0,bus=pci.0,addr=0x5' \
+  -device '{"bootindex":200,"bus":"ide.1","driver":"ide-cd","id":"ide2","unit":0}' \
+  -device '{"addr":"0x5","bus":"pci.0","driver":"virtio-scsi-pci","id":"scsihw0"}' \
   -blockdev '{"driver":"throttle","file":{"cache":{"direct":true,"no-flush":false},"driver":"raw","file":{"cache":{"direct":true,"no-flush":false},"detect-zeroes":"unmap","discard":"unmap","driver":"iscsi","lun":0,"node-name":"e7106ac43d4f125a1911487dd9e3e42","portal":"127.0.0.1","read-only":false,"target":"iqn.2019-10.org.test:foobar","transport":"tcp"},"node-name":"f7106ac43d4f125a1911487dd9e3e42","read-only":false},"node-name":"drive-scsi0","throttle-group":"throttle-drive-scsi0"}' \
-  -device 'scsi-hd,bus=scsihw0.0,channel=0,scsi-id=0,lun=0,drive=drive-scsi0,id=scsi0,bootindex=100,write-cache=on' \
+  -device '{"bootindex":100,"bus":"scsihw0.0","channel":0,"drive":"drive-scsi0","driver":"scsi-hd","id":"scsi0","lun":0,"scsi-id":0,"write-cache":"on"}' \
   -blockdev '{"driver":"throttle","file":{"cache":{"direct":false,"no-flush":false},"driver":"raw","file":{"cache":{"direct":false,"no-flush":false},"detect-zeroes":"unmap","discard":"unmap","driver":"iscsi","lun":0,"node-name":"efdb73e0d0acc5a60e3ff438cb20113","portal":"127.0.0.1","read-only":false,"target":"iqn.2019-10.org.test:foobar","transport":"tcp"},"node-name":"ffdb73e0d0acc5a60e3ff438cb20113","read-only":false},"node-name":"drive-scsi1","throttle-group":"throttle-drive-scsi1"}' \
-  -device 'scsi-hd,bus=scsihw0.0,channel=0,scsi-id=0,lun=1,drive=drive-scsi1,id=scsi1,write-cache=on' \
+  -device '{"bus":"scsihw0.0","channel":0,"drive":"drive-scsi1","driver":"scsi-hd","id":"scsi1","lun":1,"scsi-id":0,"write-cache":"on"}' \
   -blockdev '{"driver":"throttle","file":{"cache":{"direct":false,"no-flush":false},"driver":"raw","file":{"cache":{"direct":false,"no-flush":false},"detect-zeroes":"unmap","discard":"unmap","driver":"iscsi","lun":0,"node-name":"eab527a81b458aa9603dca5e2505f6e","portal":"127.0.0.1","read-only":false,"target":"iqn.2019-10.org.test:foobar","transport":"tcp"},"node-name":"fab527a81b458aa9603dca5e2505f6e","read-only":false},"node-name":"drive-scsi2","throttle-group":"throttle-drive-scsi2"}' \
-  -device 'scsi-hd,bus=scsihw0.0,channel=0,scsi-id=0,lun=2,drive=drive-scsi2,id=scsi2,write-cache=off' \
+  -device '{"bus":"scsihw0.0","channel":0,"drive":"drive-scsi2","driver":"scsi-hd","id":"scsi2","lun":2,"scsi-id":0,"write-cache":"off"}' \
   -blockdev '{"driver":"throttle","file":{"cache":{"direct":true,"no-flush":false},"driver":"raw","file":{"cache":{"direct":true,"no-flush":false},"detect-zeroes":"unmap","discard":"unmap","driver":"iscsi","lun":0,"node-name":"e915a332310039f7a3feed6901eb5da","portal":"127.0.0.1","read-only":false,"target":"iqn.2019-10.org.test:foobar","transport":"tcp"},"node-name":"f915a332310039f7a3feed6901eb5da","read-only":false},"node-name":"drive-scsi3","throttle-group":"throttle-drive-scsi3"}' \
-  -device 'scsi-hd,bus=scsihw0.0,channel=0,scsi-id=0,lun=3,drive=drive-scsi3,id=scsi3,write-cache=off' \
+  -device '{"bus":"scsihw0.0","channel":0,"drive":"drive-scsi3","driver":"scsi-hd","id":"scsi3","lun":3,"scsi-id":0,"write-cache":"off"}' \
   -netdev 'type=tap,id=net0,ifname=tap8006i0,script=/usr/libexec/qemu-server/pve-bridge,downscript=/usr/libexec/qemu-server/pve-bridgedown,vhost=on' \
   -device 'virtio-net-pci,mac=A2:C0:43:77:08:A0,netdev=net0,bus=pci.0,addr=0x12,id=net0,rx_queue_size=1024,tx_queue_size=256,bootindex=300' \
   -machine 'type=pc+pve0'
diff --git a/src/test/cfg2cmd/simple1-template.conf.cmd b/src/test/cfg2cmd/simple1-template.conf.cmd
index d63bd68a..e8faaae6 100644
--- a/src/test/cfg2cmd/simple1-template.conf.cmd
+++ b/src/test/cfg2cmd/simple1-template.conf.cmd
@@ -25,12 +25,12 @@
   -device 'usb-tablet,id=tablet,bus=uhci.0,port=1' \
   -device 'virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3,free-page-reporting=on' \
   -iscsi 'initiator-name=iqn.1993-08.org.debian:01:aabbccddeeff' \
-  -device 'ide-cd,bus=ide.1,unit=0,id=ide2,bootindex=200' \
-  -device 'virtio-scsi-pci,id=scsihw0,bus=pci.0,addr=0x5' \
+  -device '{"bootindex":200,"bus":"ide.1","driver":"ide-cd","id":"ide2","unit":0}' \
+  -device '{"addr":"0x5","bus":"pci.0","driver":"virtio-scsi-pci","id":"scsihw0"}' \
   -blockdev '{"driver":"throttle","file":{"cache":{"direct":true,"no-flush":false},"driver":"qcow2","file":{"aio":"io_uring","cache":{"direct":true,"no-flush":false},"detect-zeroes":"unmap","discard":"unmap","driver":"file","filename":"/var/lib/vz/images/8006/base-8006-disk-1.qcow2","node-name":"e1085774206ae4a6b6bf8426ff08f16","read-only":true},"node-name":"f1085774206ae4a6b6bf8426ff08f16","read-only":true},"node-name":"drive-scsi0","throttle-group":"throttle-drive-scsi0"}' \
-  -device 'scsi-hd,bus=scsihw0.0,channel=0,scsi-id=0,lun=0,drive=drive-scsi0,id=scsi0,write-cache=on' \
-  -device 'ahci,id=ahci0,multifunction=on,bus=pci.0,addr=0x7' \
+  -device '{"bus":"scsihw0.0","channel":0,"drive":"drive-scsi0","driver":"scsi-hd","id":"scsi0","lun":0,"scsi-id":0,"write-cache":"on"}' \
+  -device '{"addr":"0x7","bus":"pci.0","driver":"ahci","id":"ahci0","multifunction":"on"}' \
   -blockdev '{"driver":"throttle","file":{"cache":{"direct":true,"no-flush":false},"driver":"qcow2","file":{"aio":"io_uring","cache":{"direct":true,"no-flush":false},"detect-zeroes":"unmap","discard":"unmap","driver":"file","filename":"/var/lib/vz/images/8006/base-8006-disk-0.qcow2","node-name":"eab334c2e07734480f33dd80d89871b","read-only":false},"node-name":"fab334c2e07734480f33dd80d89871b","read-only":false},"node-name":"drive-sata0","throttle-group":"throttle-drive-sata0"}' \
-  -device 'ide-hd,bus=ahci0.0,drive=drive-sata0,id=sata0,write-cache=on' \
+  -device '{"bus":"ahci0.0","drive":"drive-sata0","driver":"ide-hd","id":"sata0","write-cache":"on"}' \
   -machine 'accel=tcg,smm=off,type=pc+pve0' \
   -snapshot
diff --git a/src/test/cfg2cmd/simple1.conf.cmd b/src/test/cfg2cmd/simple1.conf.cmd
index 513e41fc..0ecf8401 100644
--- a/src/test/cfg2cmd/simple1.conf.cmd
+++ b/src/test/cfg2cmd/simple1.conf.cmd
@@ -26,10 +26,10 @@
   -device 'VGA,id=vga,bus=pci.0,addr=0x2' \
   -device 'virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3,free-page-reporting=on' \
   -iscsi 'initiator-name=iqn.1993-08.org.debian:01:aabbccddeeff' \
-  -device 'ide-cd,bus=ide.1,unit=0,id=ide2,bootindex=200' \
-  -device 'virtio-scsi-pci,id=scsihw0,bus=pci.0,addr=0x5' \
+  -device '{"bootindex":200,"bus":"ide.1","driver":"ide-cd","id":"ide2","unit":0}' \
+  -device '{"addr":"0x5","bus":"pci.0","driver":"virtio-scsi-pci","id":"scsihw0"}' \
   -blockdev '{"driver":"throttle","file":{"cache":{"direct":true,"no-flush":false},"driver":"qcow2","file":{"aio":"io_uring","cache":{"direct":true,"no-flush":false},"detect-zeroes":"unmap","discard":"unmap","driver":"file","filename":"/var/lib/vz/images/8006/vm-8006-disk-0.qcow2","node-name":"ecd04be4259153b8293415fefa2a84c","read-only":false},"node-name":"fcd04be4259153b8293415fefa2a84c","read-only":false},"node-name":"drive-scsi0","throttle-group":"throttle-drive-scsi0"}' \
-  -device 'scsi-hd,bus=scsihw0.0,channel=0,scsi-id=0,lun=0,drive=drive-scsi0,id=scsi0,bootindex=100,write-cache=on' \
+  -device '{"bootindex":100,"bus":"scsihw0.0","channel":0,"drive":"drive-scsi0","driver":"scsi-hd","id":"scsi0","lun":0,"scsi-id":0,"write-cache":"on"}' \
   -netdev 'type=tap,id=net0,ifname=tap8006i0,script=/usr/libexec/qemu-server/pve-bridge,downscript=/usr/libexec/qemu-server/pve-bridgedown,vhost=on' \
   -device 'virtio-net-pci,mac=A2:C0:43:77:08:A0,netdev=net0,bus=pci.0,addr=0x12,id=net0,rx_queue_size=1024,tx_queue_size=256,bootindex=300' \
   -machine 'type=pc+pve0'
-- 
2.39.5



[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [pve-devel] [PATCH v2 qemu-server 10/10] RFC: add multiple iothreads support
       [not found] <20250716163415.1837210-1-alexandre.derumier@groupe-cyllene.com>
                   ` (8 preceding siblings ...)
  2025-07-16 16:34 ` [pve-devel] [PATCH v2 qemu-server 09/10] tests: cfg2cmd: convert drive devices " Alexandre Derumier via pve-devel
@ 2025-07-16 16:34 ` Alexandre Derumier via pve-devel
  9 siblings, 0 replies; 10+ messages in thread
From: Alexandre Derumier via pve-devel @ 2025-07-16 16:34 UTC (permalink / raw)
  To: pve-devel; +Cc: Alexandre Derumier

[-- Attachment #1: Type: message/rfc822, Size: 14595 bytes --]

From: Alexandre Derumier <alexandre.derumier@groupe-cyllene.com>
To: pve-devel@lists.proxmox.com
Subject: [PATCH v2 qemu-server 10/10] RFC: add multiple iothreads support
Date: Wed, 16 Jul 2025 18:34:15 +0200
Message-ID: <20250716163415.1837210-11-alexandre.derumier@groupe-cyllene.com>

This add support for multiple iothreads by disk.

iothreads are defined globally at vm start, and are shared across disk.

iothreads are different threads than vm vcpus, and can be optionally pinned
to host cpu cores (not yet implemented).

The number of iothreads can't be bigger than number of host cores.
(or performance will decrease because of context switches)

not implement: add an option to specify specific iothread mapping by disk.

Signed-off-by: Alexandre Derumier <alexandre.derumier@groupe-cyllene.com>
---
 src/PVE/QemuServer.pm               | 23 ++++++++++-
 src/PVE/QemuServer/DriveDevice.pm   | 59 ++++++++++++++++++++++++++++-
 src/test/cfg2cmd/iothreads.conf     |  7 ++++
 src/test/cfg2cmd/iothreads.conf.cmd | 45 ++++++++++++++++++++++
 4 files changed, 131 insertions(+), 3 deletions(-)
 create mode 100644 src/test/cfg2cmd/iothreads.conf
 create mode 100644 src/test/cfg2cmd/iothreads.conf.cmd

diff --git a/src/PVE/QemuServer.pm b/src/PVE/QemuServer.pm
index 29fccffb..b9500f1f 100644
--- a/src/PVE/QemuServer.pm
+++ b/src/PVE/QemuServer.pm
@@ -73,7 +73,7 @@ use PVE::QemuServer::Drive qw(
     storage_allows_io_uring_default
 );
 use PVE::QemuServer::DriveDevice
-    qw(get_drivedevice_controller get_drivedevice get_drivedevice_iothread scsihw_infos);
+    qw(get_drivedevice_controller get_drivedevice get_drivedevice_iothread parse_iothreads scsihw_infos);
 use PVE::QemuServer::Machine;
 use PVE::QemuServer::Memory qw(get_current_memory);
 use PVE::QemuServer::MetaInfo;
@@ -314,6 +314,16 @@ my $confdesc = {
         maximum => 262144,
         default => 'cgroup v1: 1024, cgroup v2: 100',
     },
+    iothreads => {
+        optional => 1,
+        type => 'string',
+        verbose_description =>
+            "Create multiple iothreads and share them between disks where iothread is enabled."
+            . "Iothreads can be optionally pinned to specific host cpu. (Ideally on different"
+            . "host cores than the vm vcpus)",
+        description => "Multiple iothreads configuration.",
+        format => $PVE::QemuServer::DriveDevice::iothreads_fmt,
+    },
     memory => {
         optional => 1,
         type => 'string',
@@ -3453,6 +3463,17 @@ sub config_to_command {
         push @$devices, '-iscsi', "initiator-name=$initiator";
     }
 
+    if ($conf->{iothreads}) {
+        my $iothreads = parse_iothreads($conf->{iothreads});
+        die "MAX $allowed_vcpus iothreads allowed per VM on this node\n"
+            if ($allowed_vcpus < $iothreads->{iothreads});
+
+        for (my $i = 0; $i < $iothreads->{iothreads}; $i++) {
+            my $iothread = { 'qom-type' => 'iothread', id => "iothread$i" };
+            push @$cmd, '-object', to_json($iothread, { canonical => 1 });
+        }
+    }
+
     PVE::QemuConfig->foreach_volume(
         $conf,
         sub {
diff --git a/src/PVE/QemuServer/DriveDevice.pm b/src/PVE/QemuServer/DriveDevice.pm
index 65555a58..e79bf128 100644
--- a/src/PVE/QemuServer/DriveDevice.pm
+++ b/src/PVE/QemuServer/DriveDevice.pm
@@ -5,6 +5,7 @@ use warnings;
 
 use URI::Escape;
 
+use PVE::JSONSchema qw(parse_property_string);
 use PVE::QemuServer::Drive qw (drive_is_cdrom);
 use PVE::QemuServer::Helpers qw(kvm_user_version min_version);
 use PVE::QemuServer::Machine;
@@ -16,9 +17,43 @@ our @EXPORT_OK = qw(
     get_drivedevice
     get_drivedevice_controller
     get_drivedevice_iothread
+    parse_iothreads
     scsihw_infos
 );
 
+our $iothreads_fmt = {
+    iothreads => {
+        optional => 1,
+        type => 'integer',
+        default_key => 1,
+        description => "Number of iothreads.",
+        minimum => 1,
+        default => 0,
+    },
+    affinity => {
+        type => 'string',
+        format => 'pve-cpuset',
+        format_description => "id[-id];...",
+        description => "List of host cores used to execute iothreads, for example: 0,5,8-11",
+        optional => 1,
+    },
+};
+
+sub parse_iothreads {
+    my ($data) = @_;
+
+    my $res = eval { parse_property_string($iothreads_fmt, $data) };
+    warn $@ if $@;
+    return $res;
+}
+
+sub print_iothreads {
+    my ($iothreads) = @_;
+    return PVE::JSONSchema::print_property_string($iothreads, $iothreads_fmt);
+}
+
+PVE::JSONSchema::register_format("pve-qm-iothreads", $iothreads_fmt);
+
 sub scsihw_infos {
     my ($conf, $drive) = @_;
 
@@ -41,6 +76,23 @@ sub scsihw_infos {
     return ($maxdev, $controller, $controller_prefix);
 }
 
+my sub add_iothread_mapping {
+    my ($conf, $device, $iothread_id) = @_;
+
+    if ($conf->{iothreads}) {
+        my $iothreads_mapping = [];
+        #if multiple iothreads are defined, we share them all by default
+        #improve me: add a manual mapping options for advanced users ?
+        my $iothreads = parse_iothreads($conf->{iothreads});
+        for (my $i = 0; $i < $iothreads->{iothreads}; $i++) {
+            push @$iothreads_mapping, { iothread => "iothread$i" };
+        }
+        $device->{'iothread-vq-mapping'} = $iothreads_mapping;
+    } else {
+        $device->{iothread} = $iothread_id;
+    }
+}
+
 sub get_drivedevice {
     my ($storecfg, $conf, $vmid, $drive, $bridges, $arch, $machine_type) = @_;
 
@@ -65,7 +117,7 @@ sub get_drivedevice {
         if (!min_version($machine_version, 10, 0) || $drive->{file} ne 'none') {
             $device->{drive} = "drive-$drive_id";
         }
-        $device->{iothread} = "iothread-$drive_id" if $drive->{iothread};
+        add_iothread_mapping($conf, $device, "iothread-$drive_id") if $drive->{iothread};
     } elsif ($drive->{interface} eq 'scsi') {
 
         my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $drive);
@@ -195,7 +247,7 @@ sub get_drivedevice_controller {
             && $conf->{scsihw} eq "virtio-scsi-single"
             && $drive->{iothread}
         ) {
-            $device->{iothread} = "iothread-$controllerid";
+            add_iothread_mapping($conf, $device, "iothread-$controllerid");
         }
 
         my $queues = '';
@@ -232,6 +284,9 @@ sub get_drivedevice_controller {
 sub get_drivedevice_iothread {
     my ($conf, $drive) = @_;
 
+    #we don't generate single iothread by disk if multiple iothreads are defined
+    return if $conf->{iothreads};
+
     my $drive_id = PVE::QemuServer::Drive::get_drive_id($drive);
 
     if ($drive->{interface} eq 'virtio') {
diff --git a/src/test/cfg2cmd/iothreads.conf b/src/test/cfg2cmd/iothreads.conf
new file mode 100644
index 00000000..f803499e
--- /dev/null
+++ b/src/test/cfg2cmd/iothreads.conf
@@ -0,0 +1,7 @@
+# TEST: global multiple iothreads with disk with or without iothread enabled
+iothreads: 4,affinity=2-6
+scsihw: virtio-scsi-single
+scsi0: local:8006/vm-8006-disk-0.raw,size=104858K,iothread=1
+scsi1: local:8006/vm-8006-disk-1.raw,size=104858K
+virtio0: local:8006/vm-8006-disk-3.raw,size=104858K,iothread=1
+virtio1: local:8006/vm-8006-disk-4.raw,size=104858K
diff --git a/src/test/cfg2cmd/iothreads.conf.cmd b/src/test/cfg2cmd/iothreads.conf.cmd
new file mode 100644
index 00000000..39bec041
--- /dev/null
+++ b/src/test/cfg2cmd/iothreads.conf.cmd
@@ -0,0 +1,45 @@
+/usr/bin/kvm \
+  -id 8006 \
+  -name 'vm8006,debug-threads=on' \
+  -no-shutdown \
+  -chardev 'socket,id=qmp,path=/var/run/qemu-server/8006.qmp,server=on,wait=off' \
+  -mon 'chardev=qmp,mode=control' \
+  -chardev 'socket,id=qmp-event,path=/var/run/qmeventd.sock,reconnect-ms=5000' \
+  -mon 'chardev=qmp-event,mode=control' \
+  -pidfile /var/run/qemu-server/8006.pid \
+  -daemonize \
+  -smp '1,sockets=1,cores=1,maxcpus=1' \
+  -nodefaults \
+  -boot 'menu=on,strict=on,reboot-timeout=1000,splash=/usr/share/qemu-server/bootsplash.jpg' \
+  -vnc 'unix:/var/run/qemu-server/8006.vnc,password=on' \
+  -cpu kvm64,enforce,+kvm_pv_eoi,+kvm_pv_unhalt,+lahf_lm,+sep \
+  -m 512 \
+  -object '{"id":"iothread0","qom-type":"iothread"}' \
+  -object '{"id":"iothread1","qom-type":"iothread"}' \
+  -object '{"id":"iothread2","qom-type":"iothread"}' \
+  -object '{"id":"iothread3","qom-type":"iothread"}' \
+  -object '{"id":"throttle-drive-scsi0","limits":{},"qom-type":"throttle-group"}' \
+  -object '{"id":"throttle-drive-scsi1","limits":{},"qom-type":"throttle-group"}' \
+  -object '{"id":"throttle-drive-virtio0","limits":{},"qom-type":"throttle-group"}' \
+  -object '{"id":"throttle-drive-virtio1","limits":{},"qom-type":"throttle-group"}' \
+  -global 'PIIX4_PM.disable_s3=1' \
+  -global 'PIIX4_PM.disable_s4=1' \
+  -device 'pci-bridge,id=pci.1,chassis_nr=1,bus=pci.0,addr=0x1e' \
+  -device 'pci-bridge,id=pci.2,chassis_nr=2,bus=pci.0,addr=0x1f' \
+  -device 'pci-bridge,id=pci.3,chassis_nr=3,bus=pci.0,addr=0x5' \
+  -device 'piix3-usb-uhci,id=uhci,bus=pci.0,addr=0x1.0x2' \
+  -device 'usb-tablet,id=tablet,bus=uhci.0,port=1' \
+  -device 'VGA,id=vga,bus=pci.0,addr=0x2' \
+  -device 'virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3,free-page-reporting=on' \
+  -iscsi 'initiator-name=iqn.1993-08.org.debian:01:aabbccddeeff' \
+  -device '{"addr":"0x1","bus":"pci.3","driver":"virtio-scsi-pci","id":"virtioscsi0","iothread-vq-mapping":[{"iothread":"iothread0"},{"iothread":"iothread1"},{"iothread":"iothread2"},{"iothread":"iothread3"}]}' \
+  -blockdev '{"driver":"throttle","file":{"cache":{"direct":true,"no-flush":false},"driver":"raw","file":{"aio":"io_uring","cache":{"direct":true,"no-flush":false},"detect-zeroes":"on","discard":"ignore","driver":"file","filename":"/var/lib/vz/images/8006/vm-8006-disk-0.raw","node-name":"e3b2553803d55d43b9986a0aac3e9a7","read-only":false},"node-name":"f3b2553803d55d43b9986a0aac3e9a7","read-only":false},"node-name":"drive-scsi0","throttle-group":"throttle-drive-scsi0"}' \
+  -device '{"bus":"virtioscsi0.0","channel":0,"drive":"drive-scsi0","driver":"scsi-hd","id":"scsi0","lun":0,"scsi-id":0,"write-cache":"on"}' \
+  -device '{"addr":"0x2","bus":"pci.3","driver":"virtio-scsi-pci","id":"virtioscsi1"}' \
+  -blockdev '{"driver":"throttle","file":{"cache":{"direct":true,"no-flush":false},"driver":"raw","file":{"aio":"io_uring","cache":{"direct":true,"no-flush":false},"detect-zeroes":"on","discard":"ignore","driver":"file","filename":"/var/lib/vz/images/8006/vm-8006-disk-1.raw","node-name":"e08707d013893852b3d4d42301a4298","read-only":false},"node-name":"f08707d013893852b3d4d42301a4298","read-only":false},"node-name":"drive-scsi1","throttle-group":"throttle-drive-scsi1"}' \
+  -device '{"bus":"virtioscsi1.0","channel":0,"drive":"drive-scsi1","driver":"scsi-hd","id":"scsi1","lun":1,"scsi-id":0,"write-cache":"on"}' \
+  -blockdev '{"driver":"throttle","file":{"cache":{"direct":true,"no-flush":false},"driver":"raw","file":{"aio":"io_uring","cache":{"direct":true,"no-flush":false},"detect-zeroes":"on","discard":"ignore","driver":"file","filename":"/var/lib/vz/images/8006/vm-8006-disk-3.raw","node-name":"ee025d619f851351566850c50231c52","read-only":false},"node-name":"fe025d619f851351566850c50231c52","read-only":false},"node-name":"drive-virtio0","throttle-group":"throttle-drive-virtio0"}' \
+  -device '{"addr":"0xa","bus":"pci.0","drive":"drive-virtio0","driver":"virtio-blk-pci","id":"virtio0","iothread-vq-mapping":[{"iothread":"iothread0"},{"iothread":"iothread1"},{"iothread":"iothread2"},{"iothread":"iothread3"}],"write-cache":"on"}' \
+  -blockdev '{"driver":"throttle","file":{"cache":{"direct":true,"no-flush":false},"driver":"raw","file":{"aio":"io_uring","cache":{"direct":true,"no-flush":false},"detect-zeroes":"on","discard":"ignore","driver":"file","filename":"/var/lib/vz/images/8006/vm-8006-disk-4.raw","node-name":"e3cbbe5a2921aa63c4a946b7317e87c","read-only":false},"node-name":"f3cbbe5a2921aa63c4a946b7317e87c","read-only":false},"node-name":"drive-virtio1","throttle-group":"throttle-drive-virtio1"}' \
+  -device '{"addr":"0xb","bus":"pci.0","drive":"drive-virtio1","driver":"virtio-blk-pci","id":"virtio1","write-cache":"on"}' \
+  -machine 'type=pc+pve0'
-- 
2.39.5



[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2025-07-16 20:59 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <20250716163415.1837210-1-alexandre.derumier@groupe-cyllene.com>
2025-07-16 16:34 ` [pve-devel] [PATCH v2 qemu-server 01/10] introduce DriveDevice module Alexandre Derumier via pve-devel
2025-07-16 16:34 ` [pve-devel] [PATCH v2 qemu-server 02/10] add print_drivedevice_controller && print_drivedevice_iothread Alexandre Derumier via pve-devel
2025-07-16 16:34 ` [pve-devel] [PATCH v2 qemu-server 03/10] hotplug: drive controller : use print_drivedevice_iothread && print_drivedevice_controller Alexandre Derumier via pve-devel
2025-07-16 16:34 ` [pve-devel] [PATCH v2 qemu-server 04/10] pci: add get_pci_addr Alexandre Derumier via pve-devel
2025-07-16 16:34 ` [pve-devel] [PATCH v2 qemu-server 05/10] qmphelpers: add qmp_deviceadd && qmp_devicedel Alexandre Derumier via pve-devel
2025-07-16 16:34 ` [pve-devel] [PATCH v2 qemu-server 06/10] convert drive device to json format Alexandre Derumier via pve-devel
2025-07-16 16:34 ` [pve-devel] [PATCH v2 qemu-server 07/10] convert iothread to json Alexandre Derumier via pve-devel
2025-07-16 16:34 ` [pve-devel] [PATCH v2 qemu-server 08/10] convert disk controller device to json format Alexandre Derumier via pve-devel
2025-07-16 16:34 ` [pve-devel] [PATCH v2 qemu-server 09/10] tests: cfg2cmd: convert drive devices " Alexandre Derumier via pve-devel
2025-07-16 16:34 ` [pve-devel] [PATCH v2 qemu-server 10/10] RFC: add multiple iothreads support Alexandre Derumier via pve-devel

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal