[master 3/7] Add support for LVM cache creation to LVM device classes

vpodzime installerbot-noreply at redhat.com
Fri Jul 31 11:45:05 UTC 2015


From: Vratislav Podzimek <vpodzime at redhat.com>

These are the basic building blocks for LVM cache creation as all high-level
calls end up doing these things.
---
 blivet/devices/lvm.py | 78 ++++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 74 insertions(+), 4 deletions(-)

diff --git a/blivet/devices/lvm.py b/blivet/devices/lvm.py
index f4e5a7b..5d72b1a 100644
--- a/blivet/devices/lvm.py
+++ b/blivet/devices/lvm.py
@@ -51,7 +51,7 @@
 from .container import ContainerDevice
 from .dm import DMDevice
 from .md import MDRaidArrayDevice
-from .cache import Cache, CacheStats
+from .cache import Cache, CacheStats, CacheRequest
 
 _INTERNAL_LV_CLASSES = []
 
@@ -473,7 +473,7 @@ class LVMLogicalVolumeDevice(DMDevice):
 
     def __init__(self, name, parents=None, size=None, uuid=None, segType=None,
                  fmt=None, exists=False, sysfsPath='', grow=None, maxsize=None,
-                 percent=None):
+                 percent=None, cacheRequest=None):
         """
             :param name: the device name (generally a device node's basename)
             :type name: str
@@ -503,6 +503,8 @@ def __init__(self, name, parents=None, size=None, uuid=None, segType=None,
             :type maxsize: :class:`~.size.Size`
             :keyword percent: percent of VG space to take
             :type percent: int
+            :keyword cacheRequest: parameters of requested cache (if any)
+            :type cacheRequest: :class:`~.devices.lvm.LVMCacheRequest`
 
         """
 
@@ -536,6 +538,10 @@ def __init__(self, name, parents=None, size=None, uuid=None, segType=None,
         self._internal_lvs = []
         self._cache = None
 
+        if cacheRequest and not self.exists:
+            self._cache = LVMCache(self, size=cacheRequest.size, exists=False,
+                                   fast_pv_names=cacheRequest.fast_devs_names, mode=cacheRequest.mode)
+
     def _check_parents(self):
         """Check that this device has parents as expected"""
 
@@ -735,7 +741,36 @@ def _create(self):
         """ Create the device. """
         log_method_call(self, self.name, status=self.status)
         # should we use --zero for safety's sake?
-        blockdev.lvm.lvcreate(self.vg.name, self._name, self.size)
+        if not self.cache:
+            # just a plain LV
+            blockdev.lvm.lvcreate(self.vg.name, self._name, self.size)
+        else:
+            mode = blockdev.lvm.cache_get_mode_from_str(self.cache.mode)
+            # prepare the list of fast PV devices
+            fast_pvs = []
+            for pv in self.cache.fast_pv_names:
+                # make sure we have the full device paths
+                if not pv.startswith("/dev/"):
+                    fast_pvs.append("/dev/%s" % pv)
+                else:
+                    fast_pvs.append(pv)
+
+            # get the list of all fast PV devices used in the VG so that we can
+            # consider the rest to be slow PVs and generate a list of them
+            all_fast_pvs_names = set()
+            for lv in self.vg.lvs:
+                if lv.cached and lv.cache.fast_pv_names:
+                    all_fast_pvs_names |= set(lv.cache.fast_pv_names)
+            slow_pvs = [pv.path for pv in self.vg.pvs if pv.name not in all_fast_pvs_names]
+
+            # TODO: allow specification of metadata size
+            # for now, we just make the metadata+data parts take the requested cache space together
+            md_size = blockdev.lvm.cache_get_default_md_size(self.cache.size)
+            data_size = self.cache.size - md_size
+
+            # VG name, LV name, data size, cache size, metadata size, mode, flags, slow PVs, fast PVs
+            blockdev.lvm.cache_create_cached_lv(self.vg.name, self._name, self.size, data_size, md_size,
+                                                mode, 0, slow_pvs, fast_pvs)
 
     def _preDestroy(self):
         StorageDevice._preDestroy(self)
@@ -1615,7 +1650,7 @@ def dependsOn(self, dep):
 class LVMCache(Cache):
     """Class providing the cache-related functionality of a cached LV"""
 
-    def __init__(self, cached_lv, size=None, exists=False, mode=None):
+    def __init__(self, cached_lv, size=None, exists=False, fast_pv_names=None, mode=None):
         """
         :param cached_lv: the LV the cache functionality of which to provide
         :type cached_lv: :class:`LVMLogicalVolumeDevice`
@@ -1623,6 +1658,8 @@ def __init__(self, cached_lv, size=None, exists=False, mode=None):
                      that cannot determine their size dynamically)
         :type size: :class:`~.size.Size`
         :param bool exists: whether the cache exists or not
+        :param fast_pv_names: PVs to allocate the cache on/from (ignored for existing)
+        :type fast_pv_names: list of str
         :param str mode: desired mode for non-existing cache (ignored for existing)
 
         """
@@ -1631,8 +1668,10 @@ def __init__(self, cached_lv, size=None, exists=False, mode=None):
         self._exists = exists
         if not exists:
             self._mode = mode or "writethrough"
+            self._fast_pvs = fast_pv_names
         else:
             self._mode = None
+            self._fast_pvs = None
 
     @property
     def size(self):
@@ -1674,6 +1713,10 @@ def cache_device_name(self):
         else:
             return None
 
+    @property
+    def fast_pv_names(self):
+        return self._fast_pvs
+
     def detach(self):
         vg_name = self._cached_lv.vg.name
         ret = blockdev.lvm.cache_pool_name(vg_name, self._cached_lv.lvname)
@@ -1747,3 +1790,30 @@ def write_hits(self):
     @property
     def write_misses(self):
         return self._write_misses
+
+class LVMCacheRequest(CacheRequest):
+    """Class representing the LVM cache creation request"""
+    def __init__(self, size, fast_pv_names, mode=None):
+        """
+        :param size: requested size of the cache
+        :type size: :class:`~.size.Size`
+        :param fast_pv_names: PVs to allocate the cache on/from
+        :type fast_pv_names: list of str
+        :param str mode: requested mode for the cache (``None`` means the default is used)
+
+        """
+        self._size = size
+        self._fast_pvs = fast_pv_names
+        self._mode = mode or "writethrough"
+
+    @property
+    def size(self):
+        return self._size
+
+    @property
+    def fast_devs_names(self):
+        return self._fast_pvs
+
+    @property
+    def mode(self):
+        return self._mode


-- 
To view this commit on github, visit https://github.com/rhinstaller/blivet/commit/c8645fe94df2ff7ff7e655385be7d141e1b1eee9


More information about the anaconda-patches mailing list