184 lines
6.4 KiB
Diff
184 lines
6.4 KiB
Diff
|
From 037d12cf3d137e08cbb8fa698a1a9c50d20228ea Mon Sep 17 00:00:00 2001
|
||
|
From: Vojtech Trefny <vtrefny@redhat.com>
|
||
|
Date: Wed, 7 Feb 2018 14:54:40 +0100
|
||
|
Subject: [PATCH 2/7] Add a singleton for NVDIMM namespaces management
|
||
|
|
||
|
This currently allows changing mode of the namespace and getting
|
||
|
information about available namespaces.
|
||
|
---
|
||
|
blivet/static_data/__init__.py | 1 +
|
||
|
blivet/static_data/nvdimm.py | 152 +++++++++++++++++++++++++++++++++++++++++
|
||
|
2 files changed, 153 insertions(+)
|
||
|
create mode 100644 blivet/static_data/nvdimm.py
|
||
|
|
||
|
diff --git a/blivet/static_data/__init__.py b/blivet/static_data/__init__.py
|
||
|
index 2c720af3..c5928ab4 100644
|
||
|
--- a/blivet/static_data/__init__.py
|
||
|
+++ b/blivet/static_data/__init__.py
|
||
|
@@ -1,3 +1,4 @@
|
||
|
from .lvm_info import lvs_info, pvs_info
|
||
|
from .luks_data import luks_data
|
||
|
from .mpath_info import mpath_members
|
||
|
+from .nvdimm import nvdimm
|
||
|
diff --git a/blivet/static_data/nvdimm.py b/blivet/static_data/nvdimm.py
|
||
|
new file mode 100644
|
||
|
index 00000000..0644c9f6
|
||
|
--- /dev/null
|
||
|
+++ b/blivet/static_data/nvdimm.py
|
||
|
@@ -0,0 +1,152 @@
|
||
|
+#
|
||
|
+# nvdimm.py - nvdimm class
|
||
|
+#
|
||
|
+# Copyright (C) 2018 Red Hat, Inc. All rights reserved.
|
||
|
+#
|
||
|
+# This program is free software; you can redistribute it and/or modify
|
||
|
+# it under the terms of the GNU General Public License as published by
|
||
|
+# the Free Software Foundation; either version 2 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 General Public License for more details.
|
||
|
+#
|
||
|
+# You should have received a copy of the GNU General Public License
|
||
|
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||
|
+#
|
||
|
+
|
||
|
+import gi
|
||
|
+gi.require_version("BlockDev", "2.0")
|
||
|
+gi.require_version("GLib", "2.0")
|
||
|
+from gi.repository import BlockDev
|
||
|
+from gi.repository import GLib
|
||
|
+
|
||
|
+from .. import util
|
||
|
+
|
||
|
+import logging
|
||
|
+log = logging.getLogger("blivet")
|
||
|
+
|
||
|
+
|
||
|
+class NVDIMMDependencyGuard(util.DependencyGuard):
|
||
|
+ error_msg = "libblockdev NVDIMM functionality not available"
|
||
|
+
|
||
|
+ def _check_avail(self):
|
||
|
+ try:
|
||
|
+ BlockDev.nvdimm_is_tech_avail(BlockDev.NVDIMMTech.NVDIMM_TECH_NAMESPACE,
|
||
|
+ BlockDev.NVDIMMTechMode.RECONFIGURE |
|
||
|
+ BlockDev.NVDIMMTechMode.QUERY |
|
||
|
+ BlockDev.NVDIMMTechMode.ACTIVATE_DEACTIVATE)
|
||
|
+ except GLib.GError:
|
||
|
+ return False
|
||
|
+ return True
|
||
|
+
|
||
|
+blockdev_nvdimm_required = NVDIMMDependencyGuard()
|
||
|
+
|
||
|
+
|
||
|
+class NVDIMM(object):
|
||
|
+ """ NVDIMM utility class.
|
||
|
+
|
||
|
+ .. warning::
|
||
|
+ Since this is a singleton class, calling deepcopy() on the instance
|
||
|
+ just returns ``self`` with no copy being created.
|
||
|
+ """
|
||
|
+
|
||
|
+ def __init__(self):
|
||
|
+ self._namespaces = None
|
||
|
+
|
||
|
+ # So that users can write nvdimm() to get the singleton instance
|
||
|
+ def __call__(self):
|
||
|
+ return self
|
||
|
+
|
||
|
+ def __deepcopy__(self, memo_dict):
|
||
|
+ # pylint: disable=unused-argument
|
||
|
+ return self
|
||
|
+
|
||
|
+ @property
|
||
|
+ def namespaces(self):
|
||
|
+ """ Dict of all NVDIMM namespaces, including dax and disabled namespaces
|
||
|
+ """
|
||
|
+ if not self._namespaces:
|
||
|
+ self.update_namespaces_info()
|
||
|
+
|
||
|
+ return self._namespaces
|
||
|
+
|
||
|
+ @blockdev_nvdimm_required(critical=True, eval_mode=util.EvalMode.onetime)
|
||
|
+ def update_namespaces_info(self):
|
||
|
+ """ Update information about the namespaces
|
||
|
+ """
|
||
|
+ namespaces = BlockDev.nvdimm_list_namespaces(idle=True)
|
||
|
+
|
||
|
+ self._namespaces = dict((namespace.dev, namespace) for namespace in namespaces)
|
||
|
+
|
||
|
+ def get_namespace_info(self, device):
|
||
|
+ """ Get namespace information for a device
|
||
|
+ :param str device: device name (e.g. 'pmem0') or path
|
||
|
+ """
|
||
|
+ for info in self.namespaces.values():
|
||
|
+ if info.blockdev == device or \
|
||
|
+ (device.startswith("/dev/") and info.blockdev == device[5:]):
|
||
|
+ return info
|
||
|
+
|
||
|
+ @blockdev_nvdimm_required(critical=True, eval_mode=util.EvalMode.onetime)
|
||
|
+ def enable_namespace(self, namespace):
|
||
|
+ """ Enable a namespace
|
||
|
+ :param str namespace: devname of the namespace (e.g. 'namespace0.0')
|
||
|
+ """
|
||
|
+
|
||
|
+ if namespace not in self.namespaces.keys():
|
||
|
+ raise ValueError("Namespace '%s' doesn't exist." % namespace)
|
||
|
+
|
||
|
+ BlockDev.nvdimm_namespace_enable(namespace)
|
||
|
+
|
||
|
+ # and update our namespaces info "cache"
|
||
|
+ self.update_namespaces_info()
|
||
|
+
|
||
|
+ @blockdev_nvdimm_required(critical=True, eval_mode=util.EvalMode.onetime)
|
||
|
+ def reconfigure_namespace(self, namespace, mode, **kwargs):
|
||
|
+ """ Change mode of the namespace
|
||
|
+ :param str namespace: devname of the namespace (e.g. 'namespace0.0')
|
||
|
+ :param str mode: new mode of the namespace (one of 'sector', 'memory', 'dax')
|
||
|
+ :keyword int sector_size: sector size when reconfiguring to the 'sector' mode
|
||
|
+ :keyword str map_location: map location when reconfiguring to the 'memory'
|
||
|
+ mode (one of 'mem', 'dev')
|
||
|
+
|
||
|
+ .. note::
|
||
|
+ This doesn't change state of the devicetree. It is necessary to
|
||
|
+ run reset() or populate() to make these changes visible.
|
||
|
+ """
|
||
|
+
|
||
|
+ if namespace not in self.namespaces.keys():
|
||
|
+ raise ValueError("Namespace '%s' doesn't exist." % namespace)
|
||
|
+
|
||
|
+ info = self.namespaces[namespace]
|
||
|
+
|
||
|
+ sector_size = kwargs.get("sector_size", None)
|
||
|
+ map_location = kwargs.get("map_location", None)
|
||
|
+
|
||
|
+ if sector_size and mode != "sector":
|
||
|
+ raise ValueError("Sector size cannot be set for selected mode '%s'." % mode)
|
||
|
+
|
||
|
+ if map_location and mode != "memory":
|
||
|
+ raise ValueError("Map location cannot be set for selected mode '%s'." % mode)
|
||
|
+
|
||
|
+ mode_t = BlockDev.nvdimm_namespace_get_mode_from_str(mode)
|
||
|
+
|
||
|
+ if sector_size:
|
||
|
+ extra = {"-l": str(sector_size)}
|
||
|
+ elif map_location:
|
||
|
+ extra = {"-M": map_location}
|
||
|
+ else:
|
||
|
+ extra = None
|
||
|
+
|
||
|
+ BlockDev.nvdimm_namespace_reconfigure(namespace, mode_t, info.enabled, extra)
|
||
|
+
|
||
|
+ # and update our namespaces info "cache"
|
||
|
+ self.update_namespaces_info()
|
||
|
+
|
||
|
+
|
||
|
+# Create nvdimm singleton
|
||
|
+nvdimm = NVDIMM()
|
||
|
+""" An instance of :class:`NVDIMM` """
|
||
|
--
|
||
|
2.14.3
|
||
|
|