Add basic support for NVMe and NVMe Fabrics devices
Resolves: rhbz#2123337
This commit is contained in:
parent
7e17f25c75
commit
65e9f995a0
590
0010-Add-basic-support-for-NVMe-and-NVMe-Fabrics-devices.patch
Normal file
590
0010-Add-basic-support-for-NVMe-and-NVMe-Fabrics-devices.patch
Normal file
@ -0,0 +1,590 @@
|
||||
From 9383855c8a15e6d7c4033cd8d7ae8310b462d166 Mon Sep 17 00:00:00 2001
|
||||
From: Vojtech Trefny <vtrefny@redhat.com>
|
||||
Date: Tue, 18 Oct 2022 10:38:00 +0200
|
||||
Subject: [PATCH 1/3] Add a basic support for NVMe and NVMe Fabrics devices
|
||||
|
||||
This adds two new device types: NVMeNamespaceDevice and
|
||||
NVMeFabricsNamespaceDevice mostly to allow to differentiate
|
||||
between "local" and "remote" NVMe devices. The new libblockdev
|
||||
NVMe plugin is required for full functionality.
|
||||
---
|
||||
blivet/__init__.py | 6 +-
|
||||
blivet/devices/__init__.py | 2 +-
|
||||
blivet/devices/disk.py | 101 ++++++++++++++++++++++
|
||||
blivet/devices/lib.py | 1 +
|
||||
blivet/populator/helpers/__init__.py | 2 +-
|
||||
blivet/populator/helpers/disk.py | 64 ++++++++++++++
|
||||
blivet/udev.py | 33 +++++++
|
||||
blivet/util.py | 9 ++
|
||||
tests/unit_tests/populator_test.py | 124 +++++++++++++++++++++++++++
|
||||
9 files changed, 339 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/blivet/__init__.py b/blivet/__init__.py
|
||||
index bbc7ea3a..3b9e659e 100644
|
||||
--- a/blivet/__init__.py
|
||||
+++ b/blivet/__init__.py
|
||||
@@ -67,6 +67,10 @@ if arch.is_s390():
|
||||
else:
|
||||
_REQUESTED_PLUGIN_NAMES = set(("swap", "crypto", "loop", "mdraid", "mpath", "dm", "nvdimm"))
|
||||
|
||||
+# nvme plugin is not generally available
|
||||
+if hasattr(blockdev.Plugin, "NVME"):
|
||||
+ _REQUESTED_PLUGIN_NAMES.add("nvme")
|
||||
+
|
||||
_requested_plugins = blockdev.plugin_specs_from_names(_REQUESTED_PLUGIN_NAMES)
|
||||
# XXX force non-dbus LVM plugin
|
||||
lvm_plugin = blockdev.PluginSpec()
|
||||
@@ -74,7 +78,7 @@ lvm_plugin.name = blockdev.Plugin.LVM
|
||||
lvm_plugin.so_name = "libbd_lvm.so.2"
|
||||
_requested_plugins.append(lvm_plugin)
|
||||
try:
|
||||
- # do not check for dependencies during libblockdev initializtion, do runtime
|
||||
+ # do not check for dependencies during libblockdev initialization, do runtime
|
||||
# checks instead
|
||||
blockdev.switch_init_checks(False)
|
||||
succ_, avail_plugs = blockdev.try_reinit(require_plugins=_requested_plugins, reload=False, log_func=log_bd_message)
|
||||
diff --git a/blivet/devices/__init__.py b/blivet/devices/__init__.py
|
||||
index 8bb0a979..4d16466e 100644
|
||||
--- a/blivet/devices/__init__.py
|
||||
+++ b/blivet/devices/__init__.py
|
||||
@@ -22,7 +22,7 @@
|
||||
from .lib import device_path_to_name, device_name_to_disk_by_path, ParentList
|
||||
from .device import Device
|
||||
from .storage import StorageDevice
|
||||
-from .disk import DiskDevice, DiskFile, DMRaidArrayDevice, MultipathDevice, iScsiDiskDevice, FcoeDiskDevice, DASDDevice, ZFCPDiskDevice, NVDIMMNamespaceDevice
|
||||
+from .disk import DiskDevice, DiskFile, DMRaidArrayDevice, MultipathDevice, iScsiDiskDevice, FcoeDiskDevice, DASDDevice, ZFCPDiskDevice, NVDIMMNamespaceDevice, NVMeNamespaceDevice, NVMeFabricsNamespaceDevice
|
||||
from .partition import PartitionDevice
|
||||
from .dm import DMDevice, DMLinearDevice, DMCryptDevice, DMIntegrityDevice, DM_MAJORS
|
||||
from .luks import LUKSDevice, IntegrityDevice
|
||||
diff --git a/blivet/devices/disk.py b/blivet/devices/disk.py
|
||||
index bc4a1b5e..b5e25939 100644
|
||||
--- a/blivet/devices/disk.py
|
||||
+++ b/blivet/devices/disk.py
|
||||
@@ -22,10 +22,13 @@
|
||||
|
||||
import gi
|
||||
gi.require_version("BlockDev", "2.0")
|
||||
+gi.require_version("GLib", "2.0")
|
||||
|
||||
from gi.repository import BlockDev as blockdev
|
||||
+from gi.repository import GLib
|
||||
|
||||
import os
|
||||
+from collections import namedtuple
|
||||
|
||||
from .. import errors
|
||||
from .. import util
|
||||
@@ -725,3 +728,101 @@ class NVDIMMNamespaceDevice(DiskDevice):
|
||||
@property
|
||||
def sector_size(self):
|
||||
return self._sector_size
|
||||
+
|
||||
+
|
||||
+NVMeController = namedtuple("NVMeController", ["name", "serial", "nvme_ver", "id", "subsysnqn"])
|
||||
+
|
||||
+
|
||||
+class NVMeNamespaceDevice(DiskDevice):
|
||||
+
|
||||
+ """ NVMe namespace """
|
||||
+ _type = "nvme"
|
||||
+ _packages = ["nvme-cli"]
|
||||
+
|
||||
+ def __init__(self, device, **kwargs):
|
||||
+ """
|
||||
+ :param name: the device name (generally a device node's basename)
|
||||
+ :type name: str
|
||||
+ :keyword exists: does this device exist?
|
||||
+ :type exists: bool
|
||||
+ :keyword size: the device's size
|
||||
+ :type size: :class:`~.size.Size`
|
||||
+ :keyword parents: a list of parent devices
|
||||
+ :type parents: list of :class:`StorageDevice`
|
||||
+ :keyword format: this device's formatting
|
||||
+ :type format: :class:`~.formats.DeviceFormat` or a subclass of it
|
||||
+ :keyword nsid: namespace ID
|
||||
+ :type nsid: int
|
||||
+ """
|
||||
+ self.nsid = kwargs.pop("nsid", 0)
|
||||
+
|
||||
+ DiskDevice.__init__(self, device, **kwargs)
|
||||
+
|
||||
+ self._clear_local_tags()
|
||||
+ self.tags.add(Tags.local)
|
||||
+ self.tags.add(Tags.nvme)
|
||||
+
|
||||
+ self._controllers = None
|
||||
+
|
||||
+ @property
|
||||
+ def controllers(self):
|
||||
+ if self._controllers is not None:
|
||||
+ return self._controllers
|
||||
+
|
||||
+ self._controllers = []
|
||||
+ if not hasattr(blockdev.Plugin, "NVME"):
|
||||
+ # the nvme plugin is not generally available
|
||||
+ log.debug("Failed to get controllers for %s: libblockdev NVME plugin is not available", self.name)
|
||||
+ return self._controllers
|
||||
+
|
||||
+ try:
|
||||
+ controllers = blockdev.nvme_find_ctrls_for_ns(self.sysfs_path)
|
||||
+ except GLib.GError as err:
|
||||
+ log.debug("Failed to get controllers for %s: %s", self.name, str(err))
|
||||
+ return self._controllers
|
||||
+
|
||||
+ for controller in controllers:
|
||||
+ try:
|
||||
+ cpath = util.get_path_by_sysfs_path(controller, "char")
|
||||
+ except RuntimeError as err:
|
||||
+ log.debug("Failed to find controller %s: %s", controller, str(err))
|
||||
+ continue
|
||||
+ try:
|
||||
+ cinfo = blockdev.nvme_get_controller_info(cpath)
|
||||
+ except GLib.GError as err:
|
||||
+ log.debug("Failed to get controller info for %s: %s", cpath, str(err))
|
||||
+ continue
|
||||
+ self._controllers.append(NVMeController(name=os.path.basename(cpath),
|
||||
+ serial=cinfo.serial_number,
|
||||
+ nvme_ver=cinfo.nvme_ver,
|
||||
+ id=cinfo.ctrl_id,
|
||||
+ subsysnqn=cinfo.subsysnqn))
|
||||
+
|
||||
+ return self._controllers
|
||||
+
|
||||
+
|
||||
+class NVMeFabricsNamespaceDevice(NVMeNamespaceDevice, NetworkStorageDevice):
|
||||
+
|
||||
+ """ NVMe fabrics namespace """
|
||||
+ _type = "nvme-fabrics"
|
||||
+ _packages = ["nvme-cli"]
|
||||
+
|
||||
+ def __init__(self, device, **kwargs):
|
||||
+ """
|
||||
+ :param name: the device name (generally a device node's basename)
|
||||
+ :type name: str
|
||||
+ :keyword exists: does this device exist?
|
||||
+ :type exists: bool
|
||||
+ :keyword size: the device's size
|
||||
+ :type size: :class:`~.size.Size`
|
||||
+ :keyword parents: a list of parent devices
|
||||
+ :type parents: list of :class:`StorageDevice`
|
||||
+ :keyword format: this device's formatting
|
||||
+ :type format: :class:`~.formats.DeviceFormat` or a subclass of it
|
||||
+ """
|
||||
+ NVMeNamespaceDevice.__init__(self, device, **kwargs)
|
||||
+ NetworkStorageDevice.__init__(self)
|
||||
+
|
||||
+ self._clear_local_tags()
|
||||
+ self.tags.add(Tags.remote)
|
||||
+ self.tags.add(Tags.nvme)
|
||||
diff --git a/blivet/devices/lib.py b/blivet/devices/lib.py
|
||||
index 1bda0bab..b3c4c5b0 100644
|
||||
--- a/blivet/devices/lib.py
|
||||
+++ b/blivet/devices/lib.py
|
||||
@@ -32,6 +32,7 @@ class Tags(str, Enum):
|
||||
"""Tags that describe various classes of disk."""
|
||||
local = 'local'
|
||||
nvdimm = 'nvdimm'
|
||||
+ nvme = 'nvme'
|
||||
remote = 'remote'
|
||||
removable = 'removable'
|
||||
ssd = 'ssd'
|
||||
diff --git a/blivet/populator/helpers/__init__.py b/blivet/populator/helpers/__init__.py
|
||||
index c5ac412f..50ab4de8 100644
|
||||
--- a/blivet/populator/helpers/__init__.py
|
||||
+++ b/blivet/populator/helpers/__init__.py
|
||||
@@ -6,7 +6,7 @@ from .formatpopulator import FormatPopulator
|
||||
|
||||
from .btrfs import BTRFSFormatPopulator
|
||||
from .boot import AppleBootFormatPopulator, EFIFormatPopulator, MacEFIFormatPopulator
|
||||
-from .disk import DiskDevicePopulator, iScsiDevicePopulator, FCoEDevicePopulator, MDBiosRaidDevicePopulator, DASDDevicePopulator, ZFCPDevicePopulator, NVDIMMNamespaceDevicePopulator
|
||||
+from .disk import DiskDevicePopulator, iScsiDevicePopulator, FCoEDevicePopulator, MDBiosRaidDevicePopulator, DASDDevicePopulator, ZFCPDevicePopulator, NVDIMMNamespaceDevicePopulator, NVMeNamespaceDevicePopulator, NVMeFabricsNamespaceDevicePopulator
|
||||
from .disklabel import DiskLabelFormatPopulator
|
||||
from .dm import DMDevicePopulator
|
||||
from .dmraid import DMRaidFormatPopulator
|
||||
diff --git a/blivet/populator/helpers/disk.py b/blivet/populator/helpers/disk.py
|
||||
index 9db7b810..9ed1eebe 100644
|
||||
--- a/blivet/populator/helpers/disk.py
|
||||
+++ b/blivet/populator/helpers/disk.py
|
||||
@@ -22,13 +22,16 @@
|
||||
|
||||
import gi
|
||||
gi.require_version("BlockDev", "2.0")
|
||||
+gi.require_version("GLib", "2.0")
|
||||
|
||||
from gi.repository import BlockDev as blockdev
|
||||
+from gi.repository import GLib
|
||||
|
||||
from ... import udev
|
||||
from ... import util
|
||||
from ...devices import DASDDevice, DiskDevice, FcoeDiskDevice, iScsiDiskDevice
|
||||
from ...devices import MDBiosRaidArrayDevice, ZFCPDiskDevice, NVDIMMNamespaceDevice
|
||||
+from ...devices import NVMeNamespaceDevice, NVMeFabricsNamespaceDevice
|
||||
from ...devices import device_path_to_name
|
||||
from ...storage_log import log_method_call
|
||||
from .devicepopulator import DevicePopulator
|
||||
@@ -251,3 +254,64 @@ class NVDIMMNamespaceDevicePopulator(DiskDevicePopulator):
|
||||
|
||||
log.info("%s is an NVDIMM namespace device", udev.device_get_name(self.data))
|
||||
return kwargs
|
||||
+
|
||||
+
|
||||
+class NVMeNamespaceDevicePopulator(DiskDevicePopulator):
|
||||
+ priority = 20
|
||||
+
|
||||
+ _device_class = NVMeNamespaceDevice
|
||||
+
|
||||
+ @classmethod
|
||||
+ def match(cls, data):
|
||||
+ return (super(NVMeNamespaceDevicePopulator, NVMeNamespaceDevicePopulator).match(data) and
|
||||
+ udev.device_is_nvme_namespace(data) and not udev.device_is_nvme_fabrics(data))
|
||||
+
|
||||
+ def _get_kwargs(self):
|
||||
+ kwargs = super(NVMeNamespaceDevicePopulator, self)._get_kwargs()
|
||||
+
|
||||
+ log.info("%s is an NVMe local namespace device", udev.device_get_name(self.data))
|
||||
+
|
||||
+ if not hasattr(blockdev.Plugin, "NVME"):
|
||||
+ # the nvme plugin is not generally available
|
||||
+ return kwargs
|
||||
+
|
||||
+ path = udev.device_get_devname(self.data)
|
||||
+ try:
|
||||
+ ninfo = blockdev.nvme_get_namespace_info(path)
|
||||
+ except GLib.GError as err:
|
||||
+ log.debug("Failed to get namespace info for %s: %s", path, str(err))
|
||||
+ else:
|
||||
+ kwargs["nsid"] = ninfo.nsid
|
||||
+
|
||||
+ log.info("%s is an NVMe local namespace device", udev.device_get_name(self.data))
|
||||
+ return kwargs
|
||||
+
|
||||
+
|
||||
+class NVMeFabricsNamespaceDevicePopulator(DiskDevicePopulator):
|
||||
+ priority = 20
|
||||
+
|
||||
+ _device_class = NVMeFabricsNamespaceDevice
|
||||
+
|
||||
+ @classmethod
|
||||
+ def match(cls, data):
|
||||
+ return (super(NVMeFabricsNamespaceDevicePopulator, NVMeFabricsNamespaceDevicePopulator).match(data) and
|
||||
+ udev.device_is_nvme_namespace(data) and udev.device_is_nvme_fabrics(data))
|
||||
+
|
||||
+ def _get_kwargs(self):
|
||||
+ kwargs = super(NVMeFabricsNamespaceDevicePopulator, self)._get_kwargs()
|
||||
+
|
||||
+ log.info("%s is an NVMe fabrics namespace device", udev.device_get_name(self.data))
|
||||
+
|
||||
+ if not hasattr(blockdev.Plugin, "NVME"):
|
||||
+ # the nvme plugin is not generally available
|
||||
+ return kwargs
|
||||
+
|
||||
+ path = udev.device_get_devname(self.data)
|
||||
+ try:
|
||||
+ ninfo = blockdev.nvme_get_namespace_info(path)
|
||||
+ except GLib.GError as err:
|
||||
+ log.debug("Failed to get namespace info for %s: %s", path, str(err))
|
||||
+ else:
|
||||
+ kwargs["nsid"] = ninfo.nsid
|
||||
+
|
||||
+ return kwargs
|
||||
diff --git a/blivet/udev.py b/blivet/udev.py
|
||||
index efbc53d6..533a1edc 100644
|
||||
--- a/blivet/udev.py
|
||||
+++ b/blivet/udev.py
|
||||
@@ -1023,6 +1023,39 @@ def device_is_nvdimm_namespace(info):
|
||||
return ninfo is not None
|
||||
|
||||
|
||||
+def device_is_nvme_namespace(info):
|
||||
+ if info.get("DEVTYPE") != "disk":
|
||||
+ return False
|
||||
+
|
||||
+ if not info.get("SYS_PATH"):
|
||||
+ return False
|
||||
+
|
||||
+ device = pyudev.Devices.from_sys_path(global_udev, info.get("SYS_PATH"))
|
||||
+ while device:
|
||||
+ if device.subsystem and device.subsystem.startswith("nvme"):
|
||||
+ return True
|
||||
+ device = device.parent
|
||||
+
|
||||
+ return False
|
||||
+
|
||||
+
|
||||
+def device_is_nvme_fabrics(info):
|
||||
+ if not device_is_nvme_namespace(info):
|
||||
+ return False
|
||||
+
|
||||
+ if not hasattr(blockdev.Plugin, "NVME") or not blockdev.is_plugin_available(blockdev.Plugin.NVME): # pylint: disable=no-member
|
||||
+ # nvme plugin is not available -- even if this is an nvme fabrics device we
|
||||
+ # don't have tools to work with it, so we should pretend it's just a normal nvme
|
||||
+ return False
|
||||
+
|
||||
+ controllers = blockdev.nvme_find_ctrls_for_ns(info.get("SYS_PATH", ""))
|
||||
+ if not controllers:
|
||||
+ return False
|
||||
+
|
||||
+ transport = util.get_sysfs_attr(controllers[0], "transport")
|
||||
+ return transport in ("rdma", "fc", "tcp", "loop")
|
||||
+
|
||||
+
|
||||
def device_is_hidden(info):
|
||||
sysfs_path = device_get_sysfs_path(info)
|
||||
hidden = util.get_sysfs_attr(sysfs_path, "hidden")
|
||||
diff --git a/blivet/util.py b/blivet/util.py
|
||||
index 0e578aea..3040ee5a 100644
|
||||
--- a/blivet/util.py
|
||||
+++ b/blivet/util.py
|
||||
@@ -432,6 +432,15 @@ def get_sysfs_path_by_name(dev_node, class_name="block"):
|
||||
"for '%s' (it is not at '%s')" % (dev_node, dev_path))
|
||||
|
||||
|
||||
+def get_path_by_sysfs_path(sysfs_path, dev_type="block"):
|
||||
+ """ Return device path for a given device sysfs path. """
|
||||
+
|
||||
+ dev = get_sysfs_attr(sysfs_path, "dev")
|
||||
+ if not dev or not os.path.exists("/dev/%s/%s" % (dev_type, dev)):
|
||||
+ raise RuntimeError("get_path_by_sysfs_path: Could not find device for %s" % sysfs_path)
|
||||
+ return os.path.realpath("/dev/%s/%s" % (dev_type, dev))
|
||||
+
|
||||
+
|
||||
def get_cow_sysfs_path(dev_path, dev_sysfsPath):
|
||||
""" Return sysfs path of cow device for a given device.
|
||||
"""
|
||||
diff --git a/tests/unit_tests/populator_test.py b/tests/unit_tests/populator_test.py
|
||||
index 369fe878..1ee29b57 100644
|
||||
--- a/tests/unit_tests/populator_test.py
|
||||
+++ b/tests/unit_tests/populator_test.py
|
||||
@@ -13,6 +13,7 @@ from gi.repository import BlockDev as blockdev
|
||||
from blivet.devices import DiskDevice, DMDevice, FileDevice, LoopDevice
|
||||
from blivet.devices import MDRaidArrayDevice, MultipathDevice, OpticalDevice
|
||||
from blivet.devices import PartitionDevice, StorageDevice, NVDIMMNamespaceDevice
|
||||
+from blivet.devices import NVMeNamespaceDevice, NVMeFabricsNamespaceDevice
|
||||
from blivet.devicelibs import lvm
|
||||
from blivet.devicetree import DeviceTree
|
||||
from blivet.formats import get_device_format_class, get_format, DeviceFormat
|
||||
@@ -21,6 +22,7 @@ from blivet.populator.helpers import DiskDevicePopulator, DMDevicePopulator, Loo
|
||||
from blivet.populator.helpers import LVMDevicePopulator, MDDevicePopulator, MultipathDevicePopulator
|
||||
from blivet.populator.helpers import OpticalDevicePopulator, PartitionDevicePopulator
|
||||
from blivet.populator.helpers import LVMFormatPopulator, MDFormatPopulator, NVDIMMNamespaceDevicePopulator
|
||||
+from blivet.populator.helpers import NVMeNamespaceDevicePopulator, NVMeFabricsNamespaceDevicePopulator
|
||||
from blivet.populator.helpers import get_format_helper, get_device_helper
|
||||
from blivet.populator.helpers.boot import AppleBootFormatPopulator, EFIFormatPopulator, MacEFIFormatPopulator
|
||||
from blivet.populator.helpers.formatpopulator import FormatPopulator
|
||||
@@ -591,6 +593,128 @@ class NVDIMMNamespaceDevicePopulatorTestCase(PopulatorHelperTestCase):
|
||||
self.assertTrue(device in devicetree.devices)
|
||||
|
||||
|
||||
+class NVMeNamespaceDevicePopulatorTestCase(PopulatorHelperTestCase):
|
||||
+ helper_class = NVMeNamespaceDevicePopulator
|
||||
+
|
||||
+ @patch("os.path.join")
|
||||
+ @patch("blivet.udev.device_is_cdrom", return_value=False)
|
||||
+ @patch("blivet.udev.device_is_dm", return_value=False)
|
||||
+ @patch("blivet.udev.device_is_loop", return_value=False)
|
||||
+ @patch("blivet.udev.device_is_md", return_value=False)
|
||||
+ @patch("blivet.udev.device_is_partition", return_value=False)
|
||||
+ @patch("blivet.udev.device_is_disk", return_value=True)
|
||||
+ @patch("blivet.udev.device_is_nvme_fabrics", return_value=False)
|
||||
+ @patch("blivet.udev.device_is_nvme_namespace", return_value=True)
|
||||
+ def test_match(self, *args):
|
||||
+ """Test matching of NVMe namespace device populator."""
|
||||
+ device_is_nvme_namespace = args[0]
|
||||
+ self.assertTrue(self.helper_class.match(None))
|
||||
+ device_is_nvme_namespace.return_value = False
|
||||
+ self.assertFalse(self.helper_class.match(None))
|
||||
+
|
||||
+ @patch("os.path.join")
|
||||
+ @patch("blivet.udev.device_is_cdrom", return_value=False)
|
||||
+ @patch("blivet.udev.device_is_dm", return_value=False)
|
||||
+ @patch("blivet.udev.device_is_loop", return_value=False)
|
||||
+ @patch("blivet.udev.device_is_md", return_value=False)
|
||||
+ @patch("blivet.udev.device_is_partition", return_value=False)
|
||||
+ @patch("blivet.udev.device_is_disk", return_value=True)
|
||||
+ @patch("blivet.udev.device_is_nvme_fabrics", return_value=False)
|
||||
+ @patch("blivet.udev.device_is_nvme_namespace", return_value=True)
|
||||
+ def test_get_helper(self, *args):
|
||||
+ """Test get_device_helper for NVMe namespaces."""
|
||||
+ device_is_nvme_namespace = args[0]
|
||||
+ data = {}
|
||||
+ self.assertEqual(get_device_helper(data), self.helper_class)
|
||||
+
|
||||
+ # verify that setting one of the required True return values to False prevents success
|
||||
+ device_is_nvme_namespace.return_value = False
|
||||
+ self.assertNotEqual(get_device_helper(data), self.helper_class)
|
||||
+ device_is_nvme_namespace.return_value = True
|
||||
+
|
||||
+ @patch("blivet.udev.device_get_name")
|
||||
+ def test_run(self, *args):
|
||||
+ """Test disk device populator."""
|
||||
+ device_get_name = args[0]
|
||||
+
|
||||
+ devicetree = DeviceTree()
|
||||
+
|
||||
+ # set up some fake udev data to verify handling of specific entries
|
||||
+ data = {'SYS_PATH': 'dummy', 'DEVNAME': 'dummy', 'ID_PATH': 'dummy'}
|
||||
+
|
||||
+ device_name = "nop"
|
||||
+ device_get_name.return_value = device_name
|
||||
+ helper = self.helper_class(devicetree, data)
|
||||
+
|
||||
+ device = helper.run()
|
||||
+
|
||||
+ self.assertIsInstance(device, NVMeNamespaceDevice)
|
||||
+ self.assertTrue(device.exists)
|
||||
+ self.assertTrue(device.is_disk)
|
||||
+ self.assertTrue(device in devicetree.devices)
|
||||
+
|
||||
+
|
||||
+class NVMeFabricsNamespaceDevicePopulatorTestCase(PopulatorHelperTestCase):
|
||||
+ helper_class = NVMeFabricsNamespaceDevicePopulator
|
||||
+
|
||||
+ @patch("os.path.join")
|
||||
+ @patch("blivet.udev.device_is_cdrom", return_value=False)
|
||||
+ @patch("blivet.udev.device_is_dm", return_value=False)
|
||||
+ @patch("blivet.udev.device_is_loop", return_value=False)
|
||||
+ @patch("blivet.udev.device_is_md", return_value=False)
|
||||
+ @patch("blivet.udev.device_is_partition", return_value=False)
|
||||
+ @patch("blivet.udev.device_is_disk", return_value=True)
|
||||
+ @patch("blivet.udev.device_is_nvme_namespace", return_value=True)
|
||||
+ @patch("blivet.udev.device_is_nvme_fabrics", return_value=True)
|
||||
+ def test_match(self, *args):
|
||||
+ """Test matching of NVMe namespace device populator."""
|
||||
+ device_is_nvme_fabrics = args[0]
|
||||
+ self.assertTrue(self.helper_class.match(None))
|
||||
+ device_is_nvme_fabrics.return_value = False
|
||||
+ self.assertFalse(self.helper_class.match(None))
|
||||
+
|
||||
+ @patch("os.path.join")
|
||||
+ @patch("blivet.udev.device_is_cdrom", return_value=False)
|
||||
+ @patch("blivet.udev.device_is_dm", return_value=False)
|
||||
+ @patch("blivet.udev.device_is_loop", return_value=False)
|
||||
+ @patch("blivet.udev.device_is_md", return_value=False)
|
||||
+ @patch("blivet.udev.device_is_partition", return_value=False)
|
||||
+ @patch("blivet.udev.device_is_disk", return_value=True)
|
||||
+ @patch("blivet.udev.device_is_nvme_namespace", return_value=True)
|
||||
+ @patch("blivet.udev.device_is_nvme_fabrics", return_value=True)
|
||||
+ def test_get_helper(self, *args):
|
||||
+ """Test get_device_helper for NVMe namespaces."""
|
||||
+ device_is_nvme_fabrics = args[0]
|
||||
+ data = {}
|
||||
+ self.assertEqual(get_device_helper(data), self.helper_class)
|
||||
+
|
||||
+ # verify that setting one of the required True return values to False prevents success
|
||||
+ device_is_nvme_fabrics.return_value = False
|
||||
+ self.assertNotEqual(get_device_helper(data), self.helper_class)
|
||||
+ device_is_nvme_fabrics.return_value = True
|
||||
+
|
||||
+ @patch("blivet.udev.device_get_name")
|
||||
+ def test_run(self, *args):
|
||||
+ """Test disk device populator."""
|
||||
+ device_get_name = args[0]
|
||||
+
|
||||
+ devicetree = DeviceTree()
|
||||
+
|
||||
+ # set up some fake udev data to verify handling of specific entries
|
||||
+ data = {'SYS_PATH': 'dummy', 'DEVNAME': 'dummy', 'ID_PATH': 'dummy'}
|
||||
+
|
||||
+ device_name = "nop"
|
||||
+ device_get_name.return_value = device_name
|
||||
+ helper = self.helper_class(devicetree, data)
|
||||
+
|
||||
+ device = helper.run()
|
||||
+
|
||||
+ self.assertIsInstance(device, NVMeFabricsNamespaceDevice)
|
||||
+ self.assertTrue(device.exists)
|
||||
+ self.assertTrue(device.is_disk)
|
||||
+ self.assertTrue(device in devicetree.devices)
|
||||
+
|
||||
+
|
||||
class MDDevicePopulatorTestCase(PopulatorHelperTestCase):
|
||||
helper_class = MDDevicePopulator
|
||||
|
||||
--
|
||||
2.38.1
|
||||
|
||||
|
||||
From af6ad7ff2f08180672690910d453158bcd463936 Mon Sep 17 00:00:00 2001
|
||||
From: Vojtech Trefny <vtrefny@redhat.com>
|
||||
Date: Fri, 2 Dec 2022 12:20:47 +0100
|
||||
Subject: [PATCH 2/3] Add transport and address to NVMeController info
|
||||
|
||||
---
|
||||
blivet/devices/disk.py | 9 +++++++--
|
||||
1 file changed, 7 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/blivet/devices/disk.py b/blivet/devices/disk.py
|
||||
index b5e25939..796b5b03 100644
|
||||
--- a/blivet/devices/disk.py
|
||||
+++ b/blivet/devices/disk.py
|
||||
@@ -730,7 +730,8 @@ class NVDIMMNamespaceDevice(DiskDevice):
|
||||
return self._sector_size
|
||||
|
||||
|
||||
-NVMeController = namedtuple("NVMeController", ["name", "serial", "nvme_ver", "id", "subsysnqn"])
|
||||
+NVMeController = namedtuple("NVMeController", ["name", "serial", "nvme_ver", "id", "subsysnqn",
|
||||
+ "transport", "transport_address"])
|
||||
|
||||
|
||||
class NVMeNamespaceDevice(DiskDevice):
|
||||
@@ -792,11 +793,15 @@ class NVMeNamespaceDevice(DiskDevice):
|
||||
except GLib.GError as err:
|
||||
log.debug("Failed to get controller info for %s: %s", cpath, str(err))
|
||||
continue
|
||||
+ ctrans = util.get_sysfs_attr(controller, "transport")
|
||||
+ ctaddr = util.get_sysfs_attr(controller, "address")
|
||||
self._controllers.append(NVMeController(name=os.path.basename(cpath),
|
||||
serial=cinfo.serial_number,
|
||||
nvme_ver=cinfo.nvme_ver,
|
||||
id=cinfo.ctrl_id,
|
||||
- subsysnqn=cinfo.subsysnqn))
|
||||
+ subsysnqn=cinfo.subsysnqn,
|
||||
+ transport=ctrans,
|
||||
+ transport_address=ctaddr))
|
||||
|
||||
return self._controllers
|
||||
|
||||
--
|
||||
2.38.1
|
||||
|
||||
|
||||
From a04538936ff62958c272b5e2b2657d177df1ef13 Mon Sep 17 00:00:00 2001
|
||||
From: Vojtech Trefny <vtrefny@redhat.com>
|
||||
Date: Thu, 8 Dec 2022 13:15:33 +0100
|
||||
Subject: [PATCH 3/3] Add additional identifiers to NVMeNamespaceDevice
|
||||
|
||||
---
|
||||
blivet/devices/disk.py | 2 ++
|
||||
blivet/populator/helpers/disk.py | 3 +++
|
||||
2 files changed, 5 insertions(+)
|
||||
|
||||
diff --git a/blivet/devices/disk.py b/blivet/devices/disk.py
|
||||
index 796b5b03..8842b4dc 100644
|
||||
--- a/blivet/devices/disk.py
|
||||
+++ b/blivet/devices/disk.py
|
||||
@@ -756,6 +756,8 @@ class NVMeNamespaceDevice(DiskDevice):
|
||||
:type nsid: int
|
||||
"""
|
||||
self.nsid = kwargs.pop("nsid", 0)
|
||||
+ self.eui64 = kwargs.pop("eui64", "")
|
||||
+ self.nguid = kwargs.pop("nguid", "")
|
||||
|
||||
DiskDevice.__init__(self, device, **kwargs)
|
||||
|
||||
diff --git a/blivet/populator/helpers/disk.py b/blivet/populator/helpers/disk.py
|
||||
index 9ed1eebe..cf20d302 100644
|
||||
--- a/blivet/populator/helpers/disk.py
|
||||
+++ b/blivet/populator/helpers/disk.py
|
||||
@@ -282,6 +282,9 @@ class NVMeNamespaceDevicePopulator(DiskDevicePopulator):
|
||||
log.debug("Failed to get namespace info for %s: %s", path, str(err))
|
||||
else:
|
||||
kwargs["nsid"] = ninfo.nsid
|
||||
+ kwargs["uuid"] = ninfo.uuid
|
||||
+ kwargs["eui64"] = ninfo.eui64
|
||||
+ kwargs["nguid"] = ninfo.nguid
|
||||
|
||||
log.info("%s is an NVMe local namespace device", udev.device_get_name(self.data))
|
||||
return kwargs
|
||||
--
|
||||
2.38.1
|
||||
|
@ -23,7 +23,7 @@ Version: 3.6.0
|
||||
|
||||
#%%global prerelease .b2
|
||||
# prerelease, if defined, should be something like .a1, .b1, .b2.dev1, or .c2
|
||||
Release: 3%{?prerelease}%{?dist}
|
||||
Release: 4%{?prerelease}%{?dist}
|
||||
Epoch: 1
|
||||
License: LGPLv2+
|
||||
%global realname blivet
|
||||
@ -39,6 +39,7 @@ Patch5: 0006-Fix-potential-AttributeError-when-getting-stratis-bl.patch
|
||||
Patch6: 0007-tests-Skip-XFS-resize-test-on-CentOS-RHEL-9.patch
|
||||
Patch7: 0008-Revert-Adjust-to-new-XFS-min-size.patch
|
||||
Patch8: 0009-Catch-BlockDevNotImplementedError-for-btrfs-plugin-c.patch
|
||||
Patch9: 0010-Add-basic-support-for-NVMe-and-NVMe-Fabrics-devices.patch
|
||||
|
||||
# Versions of required components (done so we make sure the buildrequires
|
||||
# match the requires versions of things).
|
||||
@ -146,6 +147,7 @@ Recommends: libblockdev-lvm >= %{libblockdevver}
|
||||
Recommends: libblockdev-mdraid >= %{libblockdevver}
|
||||
Recommends: libblockdev-mpath >= %{libblockdevver}
|
||||
Recommends: libblockdev-nvdimm >= %{libblockdevver}
|
||||
Recommends: libblockdev-nvme >= %{libblockdevver}
|
||||
Recommends: libblockdev-part >= %{libblockdevver}
|
||||
Recommends: libblockdev-swap >= %{libblockdevver}
|
||||
Recommends: libblockdev-s390 >= %{libblockdevver}
|
||||
@ -201,6 +203,10 @@ configuration.
|
||||
%endif
|
||||
|
||||
%changelog
|
||||
* Tue Dec 13 2022 Vojtech Trefny <vtrefny@redhat.com> - 3.6.0-4
|
||||
- Add basic support for NVMe and NVMe Fabrics devices
|
||||
Resolves: rhbz#2123337
|
||||
|
||||
* Thu Nov 03 2022 Vojtech Trefny <vtrefny@redhat.com> - 3.6.0-3
|
||||
- Catch BlockDevNotImplementedError for btrfs plugin calls
|
||||
Resolves: rhbz#2139166
|
||||
|
Loading…
Reference in New Issue
Block a user