---
blivet/devicelibs/lvm.py | 83 ++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 83 insertions(+)
diff --git a/blivet/devicelibs/lvm.py b/blivet/devicelibs/lvm.py
index 7ac0cac..24e19c0 100644
--- a/blivet/devicelibs/lvm.py
+++ b/blivet/devicelibs/lvm.py
@@ -40,6 +40,12 @@ MAX_LV_SLOTS = 256
LVM_PE_START = 1.0 # MB
LVM_PE_SIZE = 4.0 # MB
+# thinp constants
+LVM_THINP_MIN_METADATA_SIZE = 2 # 2 MiB
+LVM_THINP_MAX_METADATA_SIZE = 16384 # 16 GiB
+LVM_THINP_MIN_CHUNK_SIZE = 0.0625 # 64 KiB
+LVM_THINP_MAX_CHUNK_SIZE = 1024 # 1 GiB
+
def has_lvm():
if util.find_program_in_path("lvm"):
for line in open("/proc/devices").readlines():
@@ -156,6 +162,41 @@ def get_pv_space(size, disks, pesize=LVM_PE_SIZE,
pesize
return space
+def get_pool_padding(size, pesize=LVM_PE_SIZE, reverse=False):
+ """ Return the size of the pad required for a pool with the given
specs.
+
+ reverse means the pad is already included in the specified size and we
+ should calculate how much of the total is the pad
+ """
+ if not reverse:
+ multiplier = 0.2
+ else:
+ multiplier = 1.0 / 6
+
+ pad = min(clampSize(size * multiplier, pesize, roundup=True),
+ clampSize(LVM_THINP_MAX_METADATA_SIZE, pesize, roundup=True))
+
+ return pad
+
+def is_valid_thin_pool_metadata_size(size):
+ """ Return True if size (in MiB) is a valid thin pool metadata vol
size. """
+ return (LVM_THINP_MIN_METADATA_SIZE <= size <= LVM_THINP_MAX_METADATA_SIZE)
+
+# To support discard, chunk size must be a power of two. Otherwise it must be a
+# multiple of 64 KiB.
+def is_valid_thin_pool_chunk_size(size, discard=False):
+ """ Return True if size (in MiB) is a valid thin pool chunk size.
+
+ discard (boolean) indicates whether discard support is required
+ """
+ if not LVM_THINP_MIN_CHUNK_SIZE <= size <= LVM_THINP_MAX_CHUNK_SIZE:
+ return False
+
+ if discard:
+ return (math.log(size, 2) % 1.0 == 0)
+ else:
+ return (size % LVM_THINP_MIN_CHUNK_SIZE == 0)
+
def lvm(args):
ret = util.run_program(["lvm"] + args)
if ret:
@@ -407,3 +448,45 @@ def lvdeactivate(vg_name, lv_name):
except LVMError as msg:
raise LVMError("lvdeactivate failed for %s: %s" % (lv_name, msg))
+def thinpoolcreate(vg_name, lv_name, size, metadatasize=None, chunksize=None):
+ args = ["lvcreate", "--thinpool", "%s/%s" % (vg_name,
lv_name),
+ "--size", "%dm" % size]
+
+ if metadatasize:
+ # default unit is MiB
+ args += ["--poolmetadatasize", "%d" % metadatasize]
+
+ if chunksize:
+ # default unit is KiB
+ args += ["--chunksize", "%d" % (chunksize * 1024,)]
+
+ args += _getConfigArgs()
+
+ try:
+ lvm(args)
+ except LVMError as msg:
+ raise LVMError("lvcreate failed for %s/%s: %s" % (vg_name, lv_name,
msg))
+
+def thinlvcreate(vg_name, pool_name, lv_name, size):
+ args = ["lvcreate", "--thinpool", "%s/%s" % (vg_name,
pool_name),
+ "--virtualsize", "%dm" % size, "-n", lv_name] +
\
+ _getConfigArgs()
+
+ try:
+ lvm(args)
+ except LVMError as msg:
+ raise LVMError("lvcreate failed for %s/%s: %s" % (vg_name, lv_name,
msg))
+
+def thinlvpoolname(vg_name, lv_name):
+ args = ["lvs", "--noheadings", "-o",
"pool_lv"] + \
+ _getConfigArgs(read_only_locking=True) + \
+ ["%s/%s" % (vg_name, lv_name)]
+
+ buf = util.capture_output(["lvm"] + args)
+
+ try:
+ pool = buf.splitlines()[0].strip()
+ except IndexError:
+ pool = ''
+
+ return pool
--
1.8.1.4