From weiyj.lk at gmail.com Fri Dec 16 09:52:01 2011 From: weiyj.lk at gmail.com (Yongjun Wei) Date: Fri, 16 Dec 2011 17:52:01 +0800 Subject: [Thincrust-devel] [PATCH 0/4] Add Base Logical Volume Management support Message-ID: This patchset try to add base Logical Volume Management support to appliance-tools. [PATCH 1/4] Add LVM physical volume partition type support [PATCH 2/4] Add Logical Volume Management(LVM) group interface to partitionedfs [PATCH 3/4] Add Logical Volume interface to partitionedfs [PATCH 4/4] Add Logical Volume Management to ApplianceImageCreator TODO list: - support for grub2 - calc lvm size to fit the size of pv., maybe --grow support for logvol options From weiyj.lk at gmail.com Fri Dec 16 09:55:20 2011 From: weiyj.lk at gmail.com (Yongjun Wei) Date: Fri, 16 Dec 2011 17:55:20 +0800 Subject: [Thincrust-devel] [PATCH 1/4] Add LVM physical volume partition type support Message-ID: partition using by LVM physical volume is defined in ks.conf with mntpoint pv., this patch will allowed partitionedfs to format LVM physical volumes, and also we should skip mount of them when mount all the partitions before install os. Signed-off-by: Wei Yongjun diff --git a/appcreate/partitionedfs.py b/appcreate/partitionedfs.py index 675ac71..3c6795f 100644 --- a/appcreate/partitionedfs.py +++ b/appcreate/partitionedfs.py @@ -108,6 +108,27 @@ class PartitionedMount(Mount): #if rc != 0 and 1 == 0: # raise MountError("Error creating partition on %s" % d['disk'].device) + def __create_physical_volumes(self): + logging.debug("Creating physical volumes") + for p in self.partitions: + d = self.disks[p['disk']] + if p['mountpoint'].startswith("pv."): + logging.debug("Set LVM flag on partition %s%d" % (p['disk'], p['num'])) + rc = subprocess.call(["/sbin/parted", "-s", d['disk'].device, "set", + str(p['num']), "lvm", "on"]) + if rc != 0: + raise MountError("Error set LVM flag on partition %s%d" % + (p['disk'], p['num'])) + + logging.debug("Initialize physical volume %s" % p['device']) + rc = subprocess.call(["/sbin/lvm", "pvcreate", p['device']]) + if rc != 0: + raise MountError("Error initialize physical volume %s" % p['device']) + + def __format_volumes(self): + logging.debug("Formatting volumes") + self.__create_physical_volumes() + def __map_partitions(self): for dev in self.disks.keys(): d = self.disks[dev] @@ -180,6 +201,9 @@ class PartitionedMount(Mount): def __calculate_mountorder(self): for p in self.partitions: + if p['mountpoint'].startswith("pv."): + continue + self.mountOrder.append(p['mountpoint']) self.unmountOrder.append(p['mountpoint']) @@ -222,6 +246,7 @@ class PartitionedMount(Mount): self.__format_disks() self.__map_partitions() + self.__format_volumes() self.__calculate_mountorder() for mp in self.mountOrder: -- 1.7.7.4 From weiyj.lk at gmail.com Fri Dec 16 09:59:34 2011 From: weiyj.lk at gmail.com (Yongjun Wei) Date: Fri, 16 Dec 2011 17:59:34 +0800 Subject: [Thincrust-devel] [PATCH 2/4] Add Logical Volume Management(LVM) group interface to partitionedfs Message-ID: Kickstart has an option 'volgroup' to support create a Logical Volume Management (LVM) group. But partitionedfs does not have an interface to apply this option. We added LVM volume group interface to partitionedfs in this patch. Signed-off-by: Wei Yongjun diff --git a/appcreate/partitionedfs.py b/appcreate/partitionedfs.py index 3c6795f..8b444ad 100644 --- a/appcreate/partitionedfs.py +++ b/appcreate/partitionedfs.py @@ -42,6 +42,7 @@ class PartitionedMount(Mount): 'offset': 0 } # Offset of next partition self.partitions = [] + self.groups = [] self.mapped = False self.mountOrder = [] self.unmountOrder = [] @@ -56,6 +57,12 @@ class PartitionedMount(Mount): 'mount': None, # Mount object 'num': None}) # Partition number + def add_volume_groups(self, name, pesize, physvols): + self.groups.append({'name': name, + 'mapped': False, # True if volume group mapping exists + 'pesize': pesize, + 'physvols': physvols}) + def __format_disks(self): logging.debug("Formatting disks") for dev in self.disks.keys(): @@ -125,9 +132,28 @@ class PartitionedMount(Mount): if rc != 0: raise MountError("Error initialize physical volume %s" % p['device']) + def __create_volume_groups(self): + logging.debug("Create volume groups") + for g in self.groups: + logging.debug("Create volume group %s using %s" % (g['name'], g['physvols'])) + parts = [] + for p in self.partitions: + if g['physvols'].count(p['mountpoint']) > 0: + parts.append(p['device']) + + if len(parts) == 0: + raise MountError("Failed to query Physical Volume %s for volume group %s" % (g['physvols'], g['name'])) + + rc = subprocess.call(["/sbin/lvm", "vgcreate", g['name'], + ' '.join(parts)]) + if rc != 0: + raise MountError("Error create volume group %s using %s" % + (g['name'], g['physvols'])) + def __format_volumes(self): logging.debug("Formatting volumes") self.__create_physical_volumes() + self.__create_volume_groups() def __map_partitions(self): for dev in self.disks.keys(): @@ -198,6 +224,27 @@ class PartitionedMount(Mount): d['mapped'] = False + def __map_volumes(self): + for g in self.groups: + if g['mapped']: + continue + + rc = subprocess.call(["/sbin/lvm", "vgchange", "-ay", g['name']]) + if rc != 0: + raise MountError("Failed to map volume group %s" % g['name']) + + g['mapped'] = True + + def __unmap_volumes(self): + for g in self.groups: + if not g['mapped']: + continue + + rc = subprocess.call(["/sbin/lvm", "vgchange", "-an", g['name']]) + if rc != 0: + raise MountError("Failed to unmap volume group %s" % g['name']) + + g['mapped'] = False def __calculate_mountorder(self): for p in self.partitions: @@ -214,6 +261,7 @@ class PartitionedMount(Mount): def cleanup(self): Mount.cleanup(self) + self.__unmap_volumes() self.__unmap_partitions() for dev in self.disks.keys(): d = self.disks[dev] @@ -247,6 +295,7 @@ class PartitionedMount(Mount): self.__format_disks() self.__map_partitions() self.__format_volumes() + self.__map_volumes() self.__calculate_mountorder() for mp in self.mountOrder: -- 1.7.7.4 From weiyj.lk at gmail.com Fri Dec 16 10:01:02 2011 From: weiyj.lk at gmail.com (Yongjun Wei) Date: Fri, 16 Dec 2011 18:01:02 +0800 Subject: [Thincrust-devel] [PATCH 3/4] Add Logical Volume interface to partitionedfs Message-ID: Kickstart has an option 'logvol' to support create a Logical Volume. But partitionedfs does not have the interface to apply this option. We added Logical Volume interface to partitionedfs in this patch. Signed-off-by: Wei Yongjun diff --git a/appcreate/partitionedfs.py b/appcreate/partitionedfs.py index 8b444ad..12ff818 100644 --- a/appcreate/partitionedfs.py +++ b/appcreate/partitionedfs.py @@ -43,6 +43,7 @@ class PartitionedMount(Mount): self.partitions = [] self.groups = [] + self.volumes = [] self.mapped = False self.mountOrder = [] self.unmountOrder = [] @@ -63,6 +64,16 @@ class PartitionedMount(Mount): 'pesize': pesize, 'physvols': physvols}) + def add_logical_volume(self, name, size, vgname, mountpoint, fstype = None): + self.volumes.append({'name': name, + 'size': size, + 'vgname': vgname, + 'mountpoint': mountpoint, # Mount relative to chroot + 'fstype': fstype, + 'device': None, + 'devicemapper': None, + 'mount': None}) + def __format_disks(self): logging.debug("Formatting disks") for dev in self.disks.keys(): @@ -150,10 +161,21 @@ class PartitionedMount(Mount): raise MountError("Error create volume group %s using %s" % (g['name'], g['physvols'])) + def __create_logical_volumes(self): + logging.debug("Create logical volumes") + for v in self.volumes: + logging.debug("Create logical volume %s in volume group %s" % + (v['name'], v['vgname'])) + rc = subprocess.call(["/sbin/lvm", "lvcreate", "--name", v['name'], + "--size", str(v['size']), v['vgname']]) + if rc != 0: + raise MountError("Error create logical volume %s" % v['name']) + def __format_volumes(self): logging.debug("Formatting volumes") self.__create_physical_volumes() self.__create_volume_groups() + self.__create_logical_volumes() def __map_partitions(self): for dev in self.disks.keys(): @@ -225,7 +247,10 @@ class PartitionedMount(Mount): d['mapped'] = False def __map_volumes(self): + vgnames = [] for g in self.groups: + vgnames.append(g['name']) + if g['mapped']: continue @@ -235,6 +260,32 @@ class PartitionedMount(Mount): g['mapped'] = True + lvs = subprocess.Popen(["/sbin/lvm", "lvs", "--all","--noheadings", + "-o", "vg_name,lv_name,lv_path", + ' '.join(vgnames)], + stdout=subprocess.PIPE) + + lvsOutput = lvs.communicate()[0].split("\n") + # Strip trailing blank + lvsOutput = lvsOutput[0:len(lvsOutput)-1] + if len(lvsOutput) != len(self.volumes): + raise MountError("Unexpected number of logical volumes from lvs %d != %d" % (len(lvsOutput), len(self.volumes))) + + for i in range(len(lvsOutput)): + lvinfo = lvsOutput[i].strip().split() + vgname = lvinfo[0] + lvname = lvinfo[1] + device = lvinfo[2] + mapperdev = "/dev/mapper/%s-%s" %(vgname, lvname) + + for v in self.volumes: + if v['name'] == lvname and v['vgname'] == vgname: + logging.debug("LogVol %s: %s -> %s -> %s" % + (vgname, lvname, device, mapperdev)) + v['device'] = device + v['devicemapper'] = mapperdev + break + def __unmap_volumes(self): for g in self.groups: if not g['mapped']: @@ -254,6 +305,10 @@ class PartitionedMount(Mount): self.mountOrder.append(p['mountpoint']) self.unmountOrder.append(p['mountpoint']) + for v in self.volumes: + self.mountOrder.append(v['mountpoint']) + self.unmountOrder.append(v['mountpoint']) + self.mountOrder.sort() self.unmountOrder.sort() self.unmountOrder.reverse() @@ -280,6 +335,11 @@ class PartitionedMount(Mount): p = p1 break + for v in self.volumes: + if v['mountpoint'] == mp: + p = v + break + if p['mount'] != None: try: p['mount'].cleanup() @@ -305,6 +365,11 @@ class PartitionedMount(Mount): p = p1 break + for v in self.volumes: + if v['mountpoint'] == mp: + p = v + break + if mp == 'biosboot': subprocess.call(["/sbin/parted", "-s", self.disks[p['disk']]['disk'].device, "set", "1", "bios_grub", "on"]) continue -- 1.7.7.4 From weiyj.lk at gmail.com Fri Dec 16 10:03:05 2011 From: weiyj.lk at gmail.com (Yongjun Wei) Date: Fri, 16 Dec 2011 18:03:05 +0800 Subject: [Thincrust-devel] [PATCH 4/4] Add Logical Volume Management to ApplianceImageCreator Message-ID: This patch add Logical Volume Management to ApplianceImageCreator. Only grub is support now. grub2 support will be added later. Signed-off-by: Wei Yongjun diff --git a/appcreate/appliance.py b/appcreate/appliance.py index f9fc784..2f1854c 100644 --- a/appcreate/appliance.py +++ b/appcreate/appliance.py @@ -74,13 +74,21 @@ class ApplianceImageCreator(ImageCreator): s = "" for mp in self.__instloop.mountOrder: p = None + device = None for p1 in self.__instloop.partitions: if p1['mountpoint'] == mp: + device = "/dev/%s%-d" % (p1['disk'], p1['num']) p = p1 break + for v in self.__instloop.volumes: + if v['mountpoint'] == mp: + device = "/dev/mapper/%s-%s" % (v['vgname'], v['name']) + p = v + break + s += "%(device)s %(mountpoint)s %(fstype)s defaults,noatime 0 0\n" % { - 'device': "/dev/%s%-d" % (p['disk'], p['num']), + 'device': device, 'mountpoint': p['mountpoint'], 'fstype': p['fstype'] } @@ -120,6 +128,8 @@ class ApplianceImageCreator(ImageCreator): #list of partitions from kickstart file parts = kickstart.get_partitions(self.ks) + groups = self.ks.handler.volgroup.vgList + volumes = self.ks.handler.logvol.lvList #list of disks where a disk is an dict with name: and size disks = [] @@ -173,6 +183,13 @@ class ApplianceImageCreator(ImageCreator): for p in parts: self.__instloop.add_partition(int(p.size), p.disk, p.mountpoint, p.fstype) + for g in groups: + self.__instloop.add_volume_groups(g.vgname, g.pesize, g.physvols) + + for v in volumes: + self.__instloop.add_logical_volume(v.name, v.size, v.vgname, + v.mountpoint, v.fstype) + try: self.__instloop.mount() except MountError, e: @@ -220,6 +237,10 @@ class ApplianceImageCreator(ImageCreator): rootdevnum = p['num'] - 1 rootdev = "/dev/%s%-d" % (p['disk'], p['num']) + for v in self.__instloop.volumes: + if v['mountpoint'] == "/": + rootdev = "/dev/mapper/%s-%s" % (v['vgname'], v['name']) + prefix = "" if bootdevnum == rootdevnum: prefix = "/boot" -- 1.7.7.4