diff options
-rw-r--r-- | ChangeLog | 10 | ||||
-rw-r--r-- | fsset.py | 57 | ||||
-rw-r--r-- | lvm.py | 189 | ||||
-rw-r--r-- | lvmErrors.py | 101 |
4 files changed, 256 insertions, 101 deletions
@@ -1,3 +1,13 @@ +2007-02-07 Peter Jones <pjones@redhat.com> + + * lvmErrors.py: add some exception classes + + * lvm.py: add lvmExec and lvmCapture wrappers to iutil.exec*. + make lots of lvm commands use lvmExec and lvmCapture. + When exceptions happen, raise the exceptions defined in lvmErrors.py + + * fsset.py: use lvm commands in lvm.py + 2007-02-07 Jeremy Katz <katzj@redhat.com> * isys/isys.py (fbconProbe): Remove obsolete crap. @@ -1808,11 +1808,7 @@ MAILADDR root if isinstance(root.device, LogicalVolumeDevice) or rootlvm1: # now make sure all of the device nodes exist. *sigh* - rc = iutil.execWithRedirect("lvm", - ["vgmknodes", "-v"], - stdout = "/tmp/lvmout", - stderr = "/tmp/lvmout", - searchPath = 1) + rc = lvm.vgmknodes() rootDev = "/dev/%s" % (root.device.getDevice(),) rootdir = instPath + rootDev[:string.rfind(rootDev, "/")] @@ -2263,42 +2259,11 @@ class VolumeGroupDevice(Device): # XXX I should check if the pv is set up somehow so that we # can have preexisting vgs and add new pvs to them. if not self.isSetup: - # now make the device into a real physical volume - # XXX I don't really belong here. should - # there be a PhysicalVolumeDevice(PartitionDevice) ? - lvm.writeForceConf() - rc = iutil.execWithRedirect("lvm", - ["pvcreate", "-ff", "-y", - "-v", node], - stdout = "/tmp/lvmout", - stderr = "/tmp/lvmout", - searchPath = 1) - if rc: - raise SystemError, "pvcreate failed for %s" % (volume,) - lvm.unlinkConf() - - lvm.wipeOtherMetadataFromPV(node) - + lvm.pvcreate(node) nodes.append(node) if not self.isSetup: - # rescan now that we've recreated pvs. ugh. - lvm.writeForceConf() - lvm.vgscan() - - args = [ "vgcreate", "-v", "-An", - "-s", "%sk" %(self.physicalextentsize,), - self.name ] - args.extend(nodes) - rc = iutil.execWithRedirect("lvm", args, - stdout = "/tmp/lvmout", - stderr = "/tmp/lvmout", - searchPath = 1) - - if rc: - raise SystemError, "vgcreate failed for %s" %(self.name,) - - lvm.unlinkConf() + lvm.vgcreate(self.name, self.physicalextentsize, nodes) self.isSetup = 1 else: lvm.vgscan() @@ -2330,21 +2295,11 @@ class LogicalVolumeDevice(Device): def setupDevice(self, chroot="/", devPrefix='/tmp', vgdevice = None): if not self.isSetup: - lvm.writeForceConf() - rc = iutil.execWithRedirect("lvm", - ["lvcreate", "-L", - "%dM" % (self.size,), - "-n", self.name, "-An", - self.vgname], - stdout = "/tmp/lvmout", - stderr = "/tmp/lvmout", - searchPath = 1) - if rc: - raise SystemError, "lvcreate failed for %s" %(self.name,) - lvm.unlinkConf() + lvm.lvcreate(self.name, self.vgname, self.size) self.isSetup = 1 - if vgdevice and vgdevice.isNetdev(): self.setAsNetdev() + if vgdevice and vgdevice.isNetdev(): + self.setAsNetdev() return "/dev/%s" % (self.getDevice(),) @@ -30,6 +30,8 @@ output = "/tmp/lvmout" lvmDevicePresent = 0 +from lvmErrors import * + def has_lvm(): global lvmDevicePresent @@ -53,6 +55,22 @@ def has_lvm(): # now check to see if lvm is available has_lvm() +def lvmExec(*args): + try: + return iutil.execWithRedirect("lvm", args, stdout = output, + stderr = output, searchPath = 1) + except: + raise LvmError, args[0] + +def lvmCapture(*args): + try: + lvmout = iutil.execWithCapture("lvm", args, stderr = output) + lines = [] + for line in lvmout.split("\n"): + lines.append(line.strip().split(':')) + return lines + except: + raise LvmError, args[0] def vgscan(): """Runs vgscan.""" @@ -61,13 +79,21 @@ def vgscan(): if flags.test or lvmDevicePresent == 0: return - rc = iutil.execWithRedirect("lvm", ["vgscan", "-v"], - stdout = output, stderr = output, - searchPath = 1) + rc = lvmExec("vgscan", "-v") if rc: log.error("running vgscan failed: %s" %(rc,)) # lvmDevicePresent = 0 +def vgmknodes(volgroup=None): + # now make the device nodes + args = ["vgmknodes", "-v"] + if volgroup: + args.append(volgroup) + rc = lvmExec(*args) + if rc: + log.error("running vgmknodes failed: %s" %(rc,)) +# lvmDevicePresent = 0 + def vgactivate(volgroup = None): """Activate volume groups by running vgchange -ay. @@ -77,24 +103,14 @@ def vgactivate(volgroup = None): if flags.test or lvmDevicePresent == 0: return - args = ["vgchange", "-ay"] + args = ["vgchange", "-ay", "-v"] if volgroup: args.append(volgroup) - rc = iutil.execWithRedirect("lvm", args, stdout = output, - stderr = output, searchPath = 1) + rc = lvmExec(*args) if rc: log.error("running vgchange failed: %s" %(rc,)) # lvmDevicePresent = 0 - - # now make the device nodes - args = ["vgmknodes"] - if volgroup: - args.append(volgroup) - rc = iutil.execWithRedirect("lvm", args, stdout = output, - stderr = output, searchPath = 1) - if rc: - log.error("running vgmknodes failed: %s" %(rc,)) -# lvmDevicePresent = 0 + vgmknodes(volgroup) def vgdeactivate(volgroup = None): """Deactivate volume groups by running vgchange -an. @@ -105,16 +121,36 @@ def vgdeactivate(volgroup = None): if flags.test or lvmDevicePresent == 0: return - args = ["vgchange", "-an"] + args = ["vgchange", "-an", "-v"] if volgroup: args.append(volgroup) - rc = iutil.execWithRedirect("lvm", args, stdout = output, - stderr = output, searchPath = 1) + rc = lvmExec(*args) if rc: log.error("running vgchange failed: %s" %(rc,)) # lvmDevicePresent = 0 - - + +def lvcreate(lvname, vgname, size): + """Creates a new logical volume. + + lvname - name of logical volume to create. + vgname - name of volume group lv will be in. + size - size of lv, in megabytes. + """ + global lvmDevicePresent + if flags.test or lvmDevicePresent == 0: + return + writeForceConf() + vgscan() + + args = ["lvcreate", "-v", "-L", "%dM" %(size,), "-n", lvname, "-An", vgname] + try: + rc = lvmExec(*args) + except: + rc = 1 + if rc: + raise LVCreateError(vgname, lvname, size) + unlinkConf() + def lvremove(lvname, vgname): """Removes a logical volume. @@ -125,15 +161,42 @@ def lvremove(lvname, vgname): if flags.test or lvmDevicePresent == 0: return - args = ["lvremove", "-f"] + args = ["lvremove", "-f", "-v"] dev = "/dev/%s/%s" %(vgname, lvname) args.append(dev) - rc = iutil.execWithRedirect("lvm", args, stdout = output, - stderr = output, searchPath = 1) + try: + rc = lvmExec(*args) + except: + rc = 1 if rc: - raise SystemError, "lvremove failed" + raise LVRemoveError(vgname, lvname) +def vgcreate(vgname, PESize, nodes): + """Creates a new volume group." + + vgname - name of volume group to create. + PESize - Physical Extent size, in kilobytes. + nodes - LVM Physical Volumes on which to put the new VG. + """ + global lvmDevicePresent + if flags.test or lvmDevicePresent == 0: + return + + # rescan now that we've recreated pvs. ugh. + writeForceConf() + vgscan() + + args = ["vgcreate", "-v", "-An", "-s", "%sk" % (PESize,), vgname ] + args.extend(nodes) + + try: + rc = lvmExec(*args) + except: + rc = 1 + if rc: + raise VGCreateError(vgname, PESize, nodes) + unlinkConf() def vgremove(vgname): """Removes a volume group. Deactivates the volume group first @@ -158,34 +221,62 @@ def vgremove(vgname): except: pass - args = ["vgremove", vgname] + args = ["vgremove", "-v", vgname] log.info(string.join(args, ' ')) - rc = iutil.execWithRedirect("lvm", args, stdout = output, - stderr = output, searchPath = 1) + try: + rc = lvmExec(*args) + except: + rc = 1 if rc: - raise SystemError, "vgremove failed" + raise VGRemoveError, vgname # now iterate all the PVs we've just freed up, so we reclaim the metadata # space. This is an LVM bug, AFAICS. for pvname in pvs: - args = ["pvremove", "-ff", "-y", pvname] + args = ["pvremove", "-ff", "-y", "-v", pvname] log.info(string.join(args, ' ')) - rc = iutil.execWithRedirect("lvm", args, stdout = output, - stderr = output, searchPath = 1) - + try: + rc = lvmExec(*args) + except: + rc = 1 if rc: - raise SystemError, "pvremove failed" + raise PVRemoveError, pvname args = ["pvcreate", "-ff", "-y", "-v", pvname] log.info(string.join(args, ' ')) - rc = iutil.execWithRedirect("lvm", args, stdout = output, - stderr = output, searchPath = 1) - + try: + rc = lvmExec(*args) + except: + rc = 1 if rc: - raise SystemError, "pvcreate failed for %s" % (pvname,) + raise PVCreateError, pvname + wipeOtherMetadataFromPV(pvname) + +def pvcreate(node): + """Initializes a new Physical Volume." + + node - path to device node on which to create the new PV." + """ + global lvmDevicePresent + if flags.test or lvmDevicePresent == 0: + return + + # rescan now that we've recreated pvs. ugh. + writeForceConf() + + args = ["pvcreate", "-ff", "-y", "-v", node ] + + try: + rc = lvmExec(*args) + except: + rc = 1 + if rc: + raise PVCreateError(node) + unlinkConf() + wipeOtherMetadataFromPV(node) def lvlist(): global lvmDevicePresent @@ -199,9 +290,9 @@ def lvlist(): "vg_name,lv_name,lv_size,origin" ] lvscanout = iutil.execWithCapture("lvm", args, stderr = "/dev/tty6") - for line in lvscanout.split("\n"): + for line in lvmCapture(*args): try: - (vg, lv, size, origin) = line.strip().split(':') + (vg, lv, size, origin) = line size = long(math.floor(long(size) / (1024 * 1024))) if origin == '': origin = None @@ -226,10 +317,9 @@ def pvlist(): "--nosuffix", "--separator", ":", "--options", "pv_name,vg_name,dev_size" ] - scanout = iutil.execWithCapture("lvm", args, stderr = "/dev/tty6") - for line in scanout.split("\n"): + for line in lvmCapture(*args): try: - (dev, vg, size) = line.strip().split(':') + (dev, vg, size) = line size = long(math.floor(long(size) / (1024 * 1024))) except: continue @@ -248,10 +338,9 @@ def vglist(): "--nosuffix", "--separator", ":", "--options", "vg_name,vg_size,vg_extent_size" ] - scanout = iutil.execWithCapture("lvm", args, stderr = "/dev/tty6") - for line in scanout.split("\n"): + for line in lvmCapture(*args): try: - (vg, size, pesize) = line.strip().split(':') + (vg, size, pesize) = line size = long(math.floor(long(size) / (1024 * 1024))) pesize = long(pesize)/1024 except: @@ -267,11 +356,11 @@ def partialvgs(): return [] vgs = [] - args = ["vgdisplay", "-C", "-P", "--noheadings", "--units", "b"] - scanout = iutil.execWithCapture("lvm", args, stderr = "/dev/tty6") - for line in scanout.split("\n"): + args = ["vgdisplay", "-C", "-P", "--noheadings", "--units", "b", + "--nosuffix", "--separator", ":"] + for line in lvmCapture(*args): try: - (vg, numpv, numlv, numsn, attr, size, free) = line.strip()[:-1].split() + (vg, numpv, numlv, numsn, attr, size, free) = line except: continue if attr.find("p") != -1: diff --git a/lvmErrors.py b/lvmErrors.py new file mode 100644 index 000000000..3371c05a4 --- /dev/null +++ b/lvmErrors.py @@ -0,0 +1,101 @@ +# +# lvmErrors.py: lvm error exceptions +# +# Peter Jones <pjones@redhat.com> +# +# Copyright 2007 Red Hat, Inc. +# +# This software may be freely redistributed under the terms of the GNU +# library public license. +# +# You should have received a copy of the GNU Library Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +"""Exceptions for use in lvm operations.""" + +import string +from lvm import output + +class LvmError(Exception): + """An error occurred with lvm.""" + def __init__(self, command, name=None): + self.command = command + self.name = name + self.log = self.getLvmOutput() + + def getLvmOutput(self): + f = open(output, "r") + lines = reduce(lambda x,y: x + [string.strip(y),], f.readlines(), []) + lines = string.join(reduce(lambda x,y: x + [" %s" % (y,)], \ + lines, []), "\n") + return lines + + def __str__(self): + s = "" + if not self.name is None: + s = " for device %s" % (self.name,) + return "%s failed%s\nLog:\n%s" % (self.command, s, self.log) + +class LVCreateError(LvmError): + def __init__(self, vgname, lvname, size): + self.vgname = vgname + self.lvname = lvname + self.size = size + self.log = self.getLvmOutput() + + def __str__(self): + return "lvcreate of %d Megabyte lv \"%s\" on vg \"%s\" failed\n" \ + "Log:\n%s" % ( \ + self.size, self.lvname, self.vgname, self.log) + +class LVRemoveError(LvmError): + def __init__(self, vgname, lvname): + self.vgname = vgname + self.lvname = lvname + self.log = self.getLvmOutput() + + def __str__(self): + return "lvremove of lv \"%s\" from vg \"%s\" failed\nLog:\n%s" % ( \ + self.lvname, self.vgname, self.log) + +class VGCreateError(LvmError): + def __init__(self, vgname, PESize, nodes): + self.vgname = vgname + self.PESize = PESize + self.nodes = nodes + self.log = self.getLvmOutput() + + def __str__(self): + nodes = string.join(self.nodes, ' ') + return "vgcreate failed creating vg \"%s\" (PESize=%dkB) on PVs: %s\n" \ + "Log:\n%s" % ( \ + self.vgname, self.PESize, nodes, self.log) + +class VGRemoveError(LvmError): + def __init__(self, vgname): + self.vgname = vgname + self.log = self.getLvmOutput() + + def __str__(self): + return "vgremove of vg \"%s\" failed\nLog:\n%s" % ( \ + self.vgname, self.log) + +class PVRemoveError(LvmError): + def __init__(self, pvname): + self.pvname = pvname + self.log = self.getLvmOutput() + + def __str__(self): + return "pvremove of pv \"%s\" failed\nLog:\n%s" % ( \ + self.pvname, self.log) + +class PVCreateError(LvmError): + def __init__(self, pvname): + self.pvname = pvname + self.log = self.getLvmOutput() + + def __str__(self): + return "pvcreate of pv \"%s\" failed\nLog:\n%s" % ( \ + self.pvname, self.log) + |