File 057-virtinst-implement-NVMe-disk-target-generation.patch of Package virt-manager
Subject: virtinst: implement NVMe disk target generation
From: Pavel Hrdina phrdina@redhat.com Fri Jan 9 08:51:29 2026 +0100
Date: Sun Jan 11 18:36:09 2026 +0100:
Git: 97505a9feab1ecfd23d88dad0f90444108496f83
In libvirt NVMe disk targets are based on what linux uses for device
names.
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
--- a/tests/test_disk.py
+++ b/tests/test_disk.py
@@ -40,13 +40,30 @@ def test_disk_numtotarget():
assert DeviceDisk.target_to_num("xvdaaa") == 26 * 26 * 1 + 26 * 1 + 0
conn = utils.URIs.open_testdefault_cached()
+ guest = virtinst.Guest(conn)
disk = virtinst.DeviceDisk(conn)
disk.bus = "ide"
- assert disk.generate_target([]) == "hda"
- assert disk.generate_target(["hda"]) == "hdb"
- assert disk.generate_target(["hdb", "sda"]) == "hdc"
- assert disk.generate_target(["hda", "hdd"]) == "hdb"
+ assert disk.generate_target([], guest) == "hda"
+ assert disk.generate_target(["hda"], guest) == "hdb"
+ assert disk.generate_target(["hdb", "sda"], guest) == "hdc"
+ assert disk.generate_target(["hda", "hdd"], guest) == "hdb"
+
+ disk.bus = "nvme"
+ disk.serial = "0"
+
+ assert disk.generate_target([], guest) == "nvme0n1"
+
+ controller = virtinst.DeviceController(conn)
+ controller.type = "nvme"
+ controller.serial = "0"
+ controller.index = 0
+ guest.add_device(controller)
+
+ assert disk.generate_target([], guest) == "nvme0n1"
+
+ controller.index = 1
+ assert disk.generate_target(["nvme1n1"], guest) == "nvme1n2"
def test_disk_dir_searchable(monkeypatch):
--- a/virtManager/addhardware.py
+++ b/virtManager/addhardware.py
@@ -1453,7 +1453,7 @@ class vmmAddHardware(vmmGObjectUI):
used.append(d.target)
self._set_disk_controller(disk)
- disk.generate_target(used)
+ disk.generate_target(used, self.vm.xmlobj)
return disk
def _build_network(self):
--- a/virtinst/devices/disk.py
+++ b/virtinst/devices/disk.py
@@ -914,6 +914,19 @@ class DeviceDisk(Device):
if path:
self._set_xmlpath(path)
+ def get_nvme_namespace(self, guest):
+ """
+ Returns the NVMe namespace for disk based on it's bus and serial.
+
+ If no NVMe controller is defined return 0 as that is default used by
+ libvirt and virt-manager.
+ """
+ for c in guest.devices.controller:
+ if c.type == "nvme" and c.serial == self.serial:
+ return c.index
+
+ return 0
+
def get_target_prefix(self):
"""
Returns the suggested disk target prefix (hd, xvd, sd ...) for the
@@ -930,6 +943,7 @@ class DeviceDisk(Device):
"fd": 2,
"hd": 4,
"sd": 1024,
+ "nvme": 1024,
}
return prefix, nummap[prefix]
@@ -941,10 +955,12 @@ class DeviceDisk(Device):
return _return("fd")
elif self.bus == "ide":
return _return("hd")
+ elif self.bus == "nvme":
+ return _return("nvme")
# sata, scsi, usb, sd
return _return("sd")
- def generate_target(self, skip_targets):
+ def generate_target(self, skip_targets, guest):
"""
Generate target device ('hda', 'sdb', etc..) for disk, excluding
any targets in 'skip_targets'.
@@ -957,11 +973,17 @@ class DeviceDisk(Device):
skip_targets = [t for t in skip_targets if t and t.startswith(prefix)]
skip_targets.sort()
+ if self.bus == "nvme":
+ nvmen = self.get_nvme_namespace(guest)
+
def get_target():
first_found = None
for i in range(maxnode):
- gen_t = prefix + self.num_to_target(i + 1)
+ if self.bus == "nvme":
+ gen_t = f"{prefix}{nvmen}n{i + 1}"
+ else:
+ gen_t = prefix + self.num_to_target(i + 1)
if gen_t in skip_targets:
skip_targets.remove(gen_t)
continue
@@ -1008,7 +1030,7 @@ class DeviceDisk(Device):
used.remove(self.target)
self.target = None
- self.generate_target(used)
+ self.generate_target(used, guest)
#########################
# set_defaults handling #
@@ -1078,4 +1100,4 @@ class DeviceDisk(Device):
if not self.target:
used_targets = [d.target for d in guest.devices.disk if d.target]
- self.generate_target(used_targets)
+ self.generate_target(used_targets, guest)
--- a/virtinst/guest.py
+++ b/virtinst/guest.py
@@ -877,7 +877,7 @@ class Guest(XMLBuilder):
if dev.DEVICE_TYPE == "disk" and dev.bus == "ide":
dev.bus = "sata"
used_targets = [d.target for d in self.devices.disk if d.target]
- dev.generate_target(used_targets)
+ dev.generate_target(used_targets, self)
dev.address.clear()
if dev.address.type == "pci":