diff --git a/configure.ac b/configure.ac
index 2a8398d738d..fc2a0d9633c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -188,6 +188,7 @@ AC_CONFIG_FILES([Makefile
pyanaconda/modules/storage/disk_selection/Makefile
pyanaconda/modules/storage/fcoe/Makefile
pyanaconda/modules/storage/iscsi/Makefile
+ pyanaconda/modules/storage/nvme/Makefile
pyanaconda/modules/storage/partitioning/Makefile
pyanaconda/modules/storage/partitioning/automatic/Makefile
pyanaconda/modules/storage/partitioning/blivet/Makefile
diff --git a/pyanaconda/modules/common/constants/objects.py b/pyanaconda/modules/common/constants/objects.py
index 6ca4fbcb0c9..2deb5890dcb 100644
--- a/pyanaconda/modules/common/constants/objects.py
+++ b/pyanaconda/modules/common/constants/objects.py
@@ -89,6 +89,11 @@
basename="iSCSI"
)
+NVME = DBusObjectIdentifier(
+ namespace=STORAGE_NAMESPACE,
+ basename="NVMe"
+)
+
SNAPSHOT = DBusObjectIdentifier(
namespace=STORAGE_NAMESPACE,
basename="Snapshot"
diff --git a/pyanaconda/modules/storage/Makefile.am b/pyanaconda/modules/storage/Makefile.am
index 554903f133a..ab4cb371a60 100644
--- a/pyanaconda/modules/storage/Makefile.am
+++ b/pyanaconda/modules/storage/Makefile.am
@@ -15,7 +15,7 @@
# along with this program. If not, see .
SUBDIRS = disk_initialization disk_selection bootloader partitioning dasd zfcp fcoe \
- snapshot devicetree checker iscsi
+ snapshot devicetree checker iscsi nvme
pkgpyexecdir = $(pyexecdir)/py$(PACKAGE_NAME)
storage_moduledir = $(pkgpyexecdir)/modules/storage
diff --git a/pyanaconda/modules/storage/installation.py b/pyanaconda/modules/storage/installation.py
index 7ca56c1d433..3e728849bd8 100644
--- a/pyanaconda/modules/storage/installation.py
+++ b/pyanaconda/modules/storage/installation.py
@@ -35,7 +35,7 @@
from pyanaconda.core.util import join_paths
from pyanaconda.core.path import make_directories
from pyanaconda.core.configuration.anaconda import conf
-from pyanaconda.modules.common.constants.objects import ISCSI, FCOE, ZFCP
+from pyanaconda.modules.common.constants.objects import ISCSI, FCOE, ZFCP, NVME
from pyanaconda.modules.common.constants.services import STORAGE
from pyanaconda.modules.common.errors.installation import StorageInstallationError
from pyanaconda.modules.common.task import Task
@@ -293,6 +293,9 @@ def _write_storage_configuration(self, storage, sysroot=None):
zfcp_proxy = STORAGE.get_proxy(ZFCP)
zfcp_proxy.WriteConfiguration()
+ nvme_proxy = STORAGE.get_proxy(NVME)
+ nvme_proxy.WriteConfiguration()
+
self._write_dasd_conf(storage, sysroot)
def _write_escrow_packets(self, storage, sysroot):
diff --git a/pyanaconda/modules/storage/nvme/Makefile.am b/pyanaconda/modules/storage/nvme/Makefile.am
new file mode 100644
index 00000000000..d496cf97af8
--- /dev/null
+++ b/pyanaconda/modules/storage/nvme/Makefile.am
@@ -0,0 +1,21 @@
+#
+# Copyright (C) 2023 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published
+# by the Free Software Foundation; either version 2.1 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this program. If not, see .
+
+pkgpyexecdir = $(pyexecdir)/py$(PACKAGE_NAME)
+nvme_moduledir = $(pkgpyexecdir)/modules/storage/nvme
+nvme_module_PYTHON = $(srcdir)/*.py
+
+MAINTAINERCLEANFILES = Makefile.in
diff --git a/pyanaconda/modules/storage/nvme/__init__.py b/pyanaconda/modules/storage/nvme/__init__.py
new file mode 100644
index 00000000000..7003a70bea2
--- /dev/null
+++ b/pyanaconda/modules/storage/nvme/__init__.py
@@ -0,0 +1,20 @@
+#
+# Copyright (C) 2023 Red Hat, Inc.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions of
+# the GNU General Public License v.2, or (at your option) any later version.
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY expressed or implied, including the implied warranties of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+# Public License for more details. You should have received a copy of the
+# GNU General Public License along with this program; if not, write to the
+# Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301, USA. Any Red Hat trademarks that are incorporated in the
+# source code or documentation are not subject to the GNU General Public
+# License and may only be used or replicated with the express permission of
+# Red Hat, Inc.
+#
+from pyanaconda.modules.storage.nvme.nvme import NVMEModule
+
+__all__ = ["NVMEModule"]
diff --git a/pyanaconda/modules/storage/nvme/nvme.py b/pyanaconda/modules/storage/nvme/nvme.py
new file mode 100644
index 00000000000..5338892193d
--- /dev/null
+++ b/pyanaconda/modules/storage/nvme/nvme.py
@@ -0,0 +1,54 @@
+#
+# The NVMe module
+#
+# Copyright (C) 2023 Red Hat, Inc.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions of
+# the GNU General Public License v.2, or (at your option) any later version.
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY expressed or implied, including the implied warranties of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+# Public License for more details. You should have received a copy of the
+# GNU General Public License along with this program; if not, write to the
+# Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301, USA. Any Red Hat trademarks that are incorporated in the
+# source code or documentation are not subject to the GNU General Public
+# License and may only be used or replicated with the express permission of
+# Red Hat, Inc.
+#
+from blivet.nvme import nvme
+
+from pyanaconda.anaconda_loggers import get_module_logger
+from pyanaconda.core.configuration.anaconda import conf
+from pyanaconda.core.signal import Signal
+from pyanaconda.core.dbus import DBus
+from pyanaconda.modules.common.base import KickstartBaseModule
+from pyanaconda.modules.common.constants.objects import NVME
+from pyanaconda.modules.storage.nvme.nvme_interface import NVMEInterface
+
+log = get_module_logger(__name__)
+
+
+class NVMEModule(KickstartBaseModule):
+ """The NVMe module."""
+
+ def __init__(self):
+ super().__init__()
+ self.reload_module()
+
+ self.initiator_changed = Signal()
+
+ def publish(self):
+ """Publish the module."""
+ DBus.publish_object(NVME.object_path, NVMEInterface(self))
+
+ def reload_module(self):
+ """Reload the NVMe module."""
+ log.debug("Start up the NVMe module.")
+ nvme.startup()
+
+ def write_configuration(self):
+ """Write the configuration to sysroot."""
+ log.debug("Write NVMe configuration.")
+ nvme.write(conf.target.system_root)
diff --git a/pyanaconda/modules/storage/nvme/nvme_interface.py b/pyanaconda/modules/storage/nvme/nvme_interface.py
new file mode 100644
index 00000000000..f64b5973819
--- /dev/null
+++ b/pyanaconda/modules/storage/nvme/nvme_interface.py
@@ -0,0 +1,35 @@
+#
+# DBus interface for the NVMe module.
+#
+# Copyright (C) 2023 Red Hat, Inc.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions of
+# the GNU General Public License v.2, or (at your option) any later version.
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY expressed or implied, including the implied warranties of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+# Public License for more details. You should have received a copy of the
+# GNU General Public License along with this program; if not, write to the
+# Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301, USA. Any Red Hat trademarks that are incorporated in the
+# source code or documentation are not subject to the GNU General Public
+# License and may only be used or replicated with the express permission of
+# Red Hat, Inc.
+#
+from dasbus.server.interface import dbus_interface
+from dasbus.typing import * # pylint: disable=wildcard-import
+from pyanaconda.modules.common.base import KickstartModuleInterfaceTemplate
+from pyanaconda.modules.common.constants.objects import NVME
+
+
+@dbus_interface(NVME.interface_name)
+class NVMEInterface(KickstartModuleInterfaceTemplate):
+ """DBus interface for the NVMe module."""
+
+ def WriteConfiguration(self):
+ """Write the configuration to sysroot.
+
+ FIXME: This is just a temporary method.
+ """
+ self.implementation.write_configuration()
diff --git a/pyanaconda/modules/storage/reset.py b/pyanaconda/modules/storage/reset.py
index c8f6e5fe962..5f56725f994 100644
--- a/pyanaconda/modules/storage/reset.py
+++ b/pyanaconda/modules/storage/reset.py
@@ -22,6 +22,7 @@
from blivet.fcoe import fcoe
from blivet.i18n import _
from blivet.iscsi import iscsi
+from blivet.nvme import nvme
from blivet.zfcp import zfcp
from pyanaconda.anaconda_loggers import get_module_logger
@@ -73,6 +74,7 @@ def _reload_modules(self):
iscsi.startup()
fcoe.startup()
+ nvme.startup()
if arch.is_s390():
zfcp.startup()
diff --git a/pyanaconda/modules/storage/storage.py b/pyanaconda/modules/storage/storage.py
index f214dba70a0..43d17f85698 100644
--- a/pyanaconda/modules/storage/storage.py
+++ b/pyanaconda/modules/storage/storage.py
@@ -37,6 +37,7 @@
WriteConfigurationTask
from pyanaconda.modules.storage.iscsi import ISCSIModule
from pyanaconda.modules.storage.kickstart import StorageKickstartSpecification
+from pyanaconda.modules.storage.nvme import NVMEModule
from pyanaconda.modules.storage.partitioning.constants import PartitioningMethod
from pyanaconda.modules.storage.partitioning.factory import PartitioningFactory
from pyanaconda.modules.storage.partitioning.validate import StorageValidateTask
@@ -98,6 +99,9 @@ def __init__(self):
self._iscsi_module = ISCSIModule()
self._modules.add_module(self._iscsi_module)
+ self._nvme_module = NVMEModule()
+ self._modules.add_module(self._nvme_module)
+
self._dasd_module = DASDModule()
self._modules.add_module(self._dasd_module)
diff --git a/tests/unit_tests/pyanaconda_tests/modules/storage/test_module_nvme.py b/tests/unit_tests/pyanaconda_tests/modules/storage/test_module_nvme.py
new file mode 100644
index 00000000000..88468c6ead6
--- /dev/null
+++ b/tests/unit_tests/pyanaconda_tests/modules/storage/test_module_nvme.py
@@ -0,0 +1,41 @@
+#
+# Copyright (C) 2023 Red Hat, Inc.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions of
+# the GNU General Public License v.2, or (at your option) any later version.
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY expressed or implied, including the implied warranties of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+# Public License for more details. You should have received a copy of the
+# GNU General Public License along with this program; if not, write to the
+# Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301, USA. Any Red Hat trademarks that are incorporated in the
+# source code or documentation are not subject to the GNU General Public
+# License and may only be used or replicated with the express permission of
+# Red Hat, Inc.
+#
+# Red Hat Author(s): Vojtech Trefny
+#
+import unittest
+
+from unittest.mock import patch
+
+from pyanaconda.core.configuration.anaconda import conf
+from pyanaconda.modules.storage.nvme import NVMEModule
+from pyanaconda.modules.storage.nvme.nvme_interface import NVMEInterface
+
+
+class NVMEInterfaceTestCase(unittest.TestCase):
+ """Test DBus interface of the NVMe module."""
+
+ def setUp(self):
+ """Set up the module."""
+ self.nvme_module = NVMEModule()
+ self.nvme_interface = NVMEInterface(self.nvme_module)
+
+ @patch('pyanaconda.modules.storage.nvme.nvme.nvme')
+ def test_write_configuration(self, nvme):
+ """Test WriteConfiguration."""
+ self.nvme_interface.WriteConfiguration()
+ nvme.write.assert_called_once_with(conf.target.system_root)