From 0ae0663d8cb79fa74f715901460477b0926e572e Mon Sep 17 00:00:00 2001 From: Iustin Pop <iustin@google.com> Date: Wed, 19 Jan 2011 17:52:10 +0100 Subject: [PATCH] lvmstrap: add PV-on-partition support This is a not-so-nice change, adding support for partitions to be used as PVs. The not-nice part is that partitions live in a separate place in sysfs, whereas in dev they live at the same level as disks. We workaround this via a new SysfsName function that computes the correct sysfs base path for a given disk. The other rule is that if a disk is not in use, we ignore its partitions completely, as the disk will be re-partitioned anyway. Only if the disk is busy, we consider each of its partitions for the free/busy list. Signed-off-by: Iustin Pop <iustin@google.com> Reviewed-by: Guido Trotter <ultrotter@google.com> --- tools/lvmstrap | 48 ++++++++++++++++++++++++++++++++++++------------ 1 file changed, 36 insertions(+), 12 deletions(-) diff --git a/tools/lvmstrap b/tools/lvmstrap index ad51004a4..c27e8e3fd 100755 --- a/tools/lvmstrap +++ b/tools/lvmstrap @@ -45,6 +45,7 @@ import sys import optparse import time import errno +import re from ganeti.utils import RunCmd, ReadFile from ganeti import constants @@ -78,6 +79,10 @@ EXCLUDED_FS = frozenset([ "devpts", ]) +#: A regular expression that matches partitions (must be kept in sync +# with L{SUPPORTED_TYPES} +PART_RE = re.compile("^((?:h|s|m|ub)d[a-z]{1,2})[0-9]+$") + #: Minimum partition size to be considered (1 GB) PART_MINSIZE = 1024 * 1024 * 1024 @@ -200,7 +205,7 @@ def IsPartitioned(disk): Currently only md devices are used as is. """ - return not disk.startswith('md') + return not (disk.startswith('md') or PART_RE.match(disk)) def DeviceName(disk): @@ -217,6 +222,17 @@ def DeviceName(disk): return device +def SysfsName(disk): + """Returns the sysfs name for a disk or partition. + + """ + match = PART_RE.match(disk) + if match: + # this is a partition, which resides in /sys/block under a different name + disk = "%s/%s" % (match.group(1), disk) + return "/sys/block/%s" % disk + + def ExecCommand(command): """Executes a command. @@ -453,7 +469,8 @@ def GetDiskList(opts): partsize = ReadSize(partsysfsname) if partsize >= PART_MINSIZE: CheckSysDev(partname, partdev) - partitions.append((partname, partsize, partdev)) + partinuse = InUse(partname) + partitions.append((partname, partsize, partdev, partinuse)) partitions.sort() dlist.append((name, size, dev, partitions, inuse)) dlist.sort() @@ -537,6 +554,12 @@ def ShowDiskInfo(opts): choice about which disks should be allocated to our volume group. """ + def _inuse(inuse): + if inuse: + return "yes" + else: + return "no" + mounts = GetMountInfo() dlist = GetDiskList(opts) @@ -554,13 +577,9 @@ def ShowDiskInfo(opts): flatlist = [] # Flatten the [(disk, [partition,...]), ...] list for name, size, dev, parts, inuse in dlist: - if inuse: - str_inuse = "yes" - else: - str_inuse = "no" - flatlist.append((name, size, dev, str_inuse)) - for partname, partsize, partdev in parts: - flatlist.append((partname, partsize, partdev, "")) + flatlist.append((name, size, dev, _inuse(inuse))) + for partname, partsize, partdev, partinuse in parts: + flatlist.append((partname, partsize, partdev, _inuse(partinuse))) strlist = [] for name, size, dev, in_use in flatlist: @@ -598,7 +617,7 @@ def CheckSysfsHolders(name): """ try: - contents = os.listdir("/sys/block/%s/holders/" % name) + contents = os.listdir("%s/holders/" % SysfsName(name)) except OSError, err: if err.errno == errno.ENOENT: contents = [] @@ -647,7 +666,7 @@ def CheckMounted(name): """ minfo = GetMountInfo() - dev = ReadDev("/sys/block/%s" % name) + dev = ReadDev(SysfsName(name)) return dev not in minfo @@ -786,9 +805,14 @@ def ValidateDiskList(options): " non-removable block devices).") sysd_free = [] sysd_used = [] - for name, _, _, _, used in sysdisks: + for name, _, _, parts, used in sysdisks: if used: sysd_used.append(name) + for partname, _, _, partused in parts: + if partused: + sysd_used.append(partname) + else: + sysd_free.append(partname) else: sysd_free.append(name) -- GitLab