051-addhardware-Add-usb-as-a-recommended-sound-device.patch 055-virtinst-Add-serial-controller-option-to-cli.patch 056-virtinst-Add-NVMe-Controller.patch 057-virtinst-implement-NVMe-disk-target-generation.patch 057-virtinst-implement-NVMe-disk-target-generation.patch~ 058-virtManager-Add-NVMe-disk-type.patch 058-virtManager-Add-NVMe-disk-type.patch~ 059-ui-Show-NVMe-Controller-details.patch 060-virtinst-fix-locale-when-running-in-flatpak.patch 061-virtinst-add-support-for-iommufd.patch OBS-URL: https://build.opensuse.org/package/show/Virtualization/virt-manager?expand=0&rev=744
148 lines
4.9 KiB
Diff
148 lines
4.9 KiB
Diff
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":
|