Joel Andres Granados wrote:
Hi list:
Anybody interested in testing my take on mirroring for anaconda
installer is more than
welcome to take a big wack at this path. I will attach the updates
images Im using for testing
is at http://jgranado.fedorapeople.org/updates.img. I tested against
f8t1.
comments greatly appreciated :)
Regards.
------------------------------------------------------------------------
_______________________________________________
Anaconda-devel-list mailing list
Anaconda-devel-list@xxxxxxxxxx
https://www.redhat.com/mailman/listinfo/anaconda-devel-list
Here is the new stuff :)
I'm specially worried about the following piece of code :
<snip>
self.mirrors = mirrors
self.corelog = corelog
self.devs = devs
#This is the size of each side. All sides have the same size.
self.mirroredSize = size
self.mirroredRequestSize = size
#This is what the rest of the code has to consider as size.
#This is done so other lvs can be installed with the mirrored lv.
#FIXME: We don't consider the space that the log ocupies, it
might be a problem!
#Be aware that the requestSize will also be the "totalSize".
#self.totalMirroredLVSize = self.mirroredSize * (self.mirrors + 1)
LogicalVolumeRequestSpec.__init__(self, fstype, format=format,
mountpoint=mountpoint,
size=self.mirroredSize * (self.mirrors + 1),
volgroup=volgroup, lvname=lvname, preexist=preexist,
percent=percent, grow=grow, maxSizeMB=maxSizeMB,
bytesPerInode=bytesPerInode, fslabel=fslabel)
self.requestSize = self.mirroredSize
</snip>
The way that the size is handled here is somewhat hacky, to say the
least :). What I want to accomplish with
this way of handling things is to inform the rest of the LVM stuff that
this mirrored LVM will take N*(size)
of space in the LVM system. N being the number of areas in the mirror.
Comments greatly appreciated. :)
--
Joel Andres Granados
Index: fsset.py
===================================================================
RCS file: /usr/local/CVS/anaconda/fsset.py,v
retrieving revision 1.334
diff -u -r1.334 fsset.py
--- fsset.py 17 Aug 2007 14:20:44 -0000 1.334
+++ fsset.py 31 Aug 2007 13:17:17 -0000
@@ -1505,7 +1505,17 @@
vgs[entry.device.name] = entry.device
# then set up the logical volumes
+ nonLVMirrors = []
for entry in self.entries:
+ #We should do the mirrored stuff first :)
+ if isinstance(entry.device, MirroredLogicalVolumeDevice):
+ vg = None
+ if vgs.has_key(entry.device.vgname):
+ vg = vgs[entry.device.vgname]
+ entry.device.setupDevice(chroot, vgdevice = vg)
+ else:
+ nonLVMirrors.append(entry)
+ for nonMirrors in nonLVMirrors:
if isinstance(entry.device, LogicalVolumeDevice):
vg = None
if vgs.has_key(entry.device.vgname):
@@ -2194,6 +2204,28 @@
return
+class MirroredLogicalVolumeDevice(LogicalVolumeDevice):
+ def __init__(self, vgname, size, lvname, vg, existing = 0, mirrors = 0, devs = [], corelog = True):
+ """
+ mirrors - The number of mirrors.
+ devs - Specific devices to use for mirrors.
+ corelog - Wether to use corelog or not.
+ """
+ LogicalVolumeDevice.__init__(self,vgname, size, lvname, vg, existing=existing)
+ self.mirrors = mirrors #If mirrors is set to 0 mirroring is ignored.
+ self.devs = devs
+ self.corelog = corelog
+
+ def setupDevice(self, chroot="/", devPrefix='/tmp', vgdevice = None):
+ if not self.isSetup:
+ lvm.mirroredlvcreate(self.name, self.vgname, self.size, mirrors=self.mirrors, corelog=self.corelog, devs=self.devs)
+ self.isSetup = 1
+
+ if vgdevice and vgdevice.isNetdev():
+ self.setAsNetdev()
+
+ return "/dev/%s" % (self.getDevice(),)
+
class PartitionDevice(Device):
def __init__(self, partition):
Device.__init__(self)
Index: kickstart.py
===================================================================
RCS file: /usr/local/CVS/anaconda/kickstart.py,v
retrieving revision 1.386
diff -u -r1.386 kickstart.py
--- kickstart.py 27 Aug 2007 20:15:55 -0000 1.386
+++ kickstart.py 31 Aug 2007 13:17:17 -0000
@@ -217,9 +217,9 @@
self.handler.id.instClass.setLanguage(self.handler.id, self.lang)
self.handler.skipSteps.append("language")
-class LogVol(commands.logvol.FC4_LogVol):
+class LogVol(commands.logvol.F8_LogVol):
def parse(self, args):
- commands.logvol.FC4_LogVol.parse(self, args)
+ commands.logvol.F8_LogVol.parse(self, args)
lvd = self.lvList[-1]
@@ -264,7 +264,46 @@
elif (lvd.percent <= 0 or lvd.percent > 100) and not lvd.preexist:
raise KickstartValueError, formatErrorMsg(self.lineno, msg="Percentage must be between 0 and 100")
- request = partRequests.LogicalVolumeRequestSpec(filesystem,
+ if lvd.mirrors > 0:# sanity checks for the mirror stuff.
+ if lvd.devs == []:
+ raise KickstartValueError, formatErrorMsg(self.lineno, \
+ msg="When specifying a mirrored logical volume you must provide a list of devices.")
+ # For now we will ask the user to use only the minimum number of devices.
+ if lvd.corelog and len(lvd.devs) != lvd.mirrors+1:
+ raise KickstartValueError, formatErrorMsg(self.lineno, \
+ msg="When mirroring with corelog the number of devices must be equal to the number of mirrors plus one. (devs=mirrors+1)")
+ if not lvd.corelog and len(lvd.devs) != lvd.mirrors+2:
+ raise KickstartValueError, formatErrorMsg(self.lineno, \
+ msg="When mirroring without corelog the number of devices must be equal to the number of mirrors plus two. (devs=mirrors+2)")
+ #The calculations based on percentages will not apply to mirrored logical volumes for now.
+ if lvd.percent:
+ raise KickstartValueError, formatErrorMsg(self.lineno, \
+ msg="When creating a logical volume use the --size option instead of the --percent.")
+ # get the unique ids of each of the physical volumes
+ pvs=[]
+ for pv in lvd.devs:
+ if pv not in self.handler.ksPVMapping.keys():
+ raise KickstartValueError, formatErrorMsg(self.lineno, \
+ msg="Tried to use undefined partition %s in Volume Group specification" % pv)
+ pvs.append(self.handler.ksPVMapping[pv])
+
+ request = partRequests.MirroredLogicalVolumeRequestSpec(filesystem,
+ format = lvd.format,
+ mountpoint = lvd.mountpoint,
+ size = lvd.size,
+ percent = lvd.percent,
+ volgroup = vgid,
+ lvname = lvd.name,
+ grow = lvd.grow,
+ maxSizeMB = lvd.maxSizeMB,
+ preexist = lvd.preexist,
+ bytesPerInode = lvd.bytesPerInode,
+ mirrors = lvd.mirrors,
+ corelog = lvd.corelog,
+ devs = pvs)
+
+ else:
+ request = partRequests.LogicalVolumeRequestSpec(filesystem,
format = lvd.format,
mountpoint = lvd.mountpoint,
size = lvd.size,
@@ -695,7 +734,7 @@
"poweroff": Reboot,
"raid": Raid,
"reboot": Reboot,
- "repo": commands.repo.F8_Repo,
+ "repo": commands.repo.FC6_Repo,
"rootpw": RootPw,
"selinux": SELinux,
"services": commands.services.FC6_Services,
Index: lvm.py
===================================================================
RCS file: /usr/local/CVS/anaconda/lvm.py,v
retrieving revision 1.48
diff -u -r1.48 lvm.py
--- lvm.py 21 May 2007 14:30:19 -0000 1.48
+++ lvm.py 31 Aug 2007 13:17:17 -0000
@@ -179,6 +179,31 @@
raise LVCreateError(vgname, lvname, size)
unlinkConf()
+def mirroredlvcreate(lvname, vgname, size, mirrors=0, corelog=True, devs=[]):
+ """Creates mirrored logical volume.
+ lvname - name of logical volume to create.
+ vgname - name of volume group lv will be in.
+ size - size of lv, in megabytes.
+ mirrors - the amount of mirrors to create
+ devs - a list of string representing valid devices of the form "/dev/deviceName
+ corelog - whether or not to use corelog.
+ """
+ global lvmDevicePresent
+ if flags.test or lvmDevicePresent == 0:
+ return
+ writeForceConf()
+ vgscan()
+
+ args = ["lvcreate", "-v", "-L", "%dM" %(size,), "-m", "%s"%mirrors]+\
+ (corelog and ["--corelog"] or [])+["-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.
Index: partRequests.py
===================================================================
RCS file: /usr/local/CVS/anaconda/partRequests.py,v
retrieving revision 1.74
diff -u -r1.74 partRequests.py
--- partRequests.py 3 Aug 2007 19:32:24 -0000 1.74
+++ partRequests.py 31 Aug 2007 13:17:17 -0000
@@ -930,3 +930,84 @@
"group's physical extent size.")
return RequestSpec.sanityCheckRequest(self, partitions, skipMntPtExistCheck)
+
+class MirroredLogicalVolumeRequestSpec(LogicalVolumeRequestSpec):
+ def __init__(self,fstype, format = None, mountpoint = None, size = None, volgroup = None,
+ lvname = None, preexist = 0, percent = None, grow=0, maxSizeMB=0, bytesPerInode = 4096,
+ fslabel = None, mirrors=1, corelog=True, devs=[]):
+ """
+ mirrors - This is the total amount of mirrors. Not counting the main device.
+ corelog - If corelog was chosen or not.
+ devs - The list of devices that hold the mirrors and the main device
+
+ The lvm2 cml does not make the relation of each device with each logical volume, we are not
+ going to handle that relation either.
+ """
+ self.mirrors = mirrors
+ self.corelog = corelog
+ self.devs = devs
+ #This is the size of each side. All sides have the same size.
+ self.mirroredSize = size
+ self.mirroredRequestSize = size
+ #This is what the rest of the code has to consider as size.
+ #This is done so other lvs can be installed with the mirrored lv.
+ #FIXME: We don't consider the space that the log ocupies, it might be a problem!
+ #Be aware that the requestSize will also be the "totalSize".
+ #self.totalMirroredLVSize = self.mirroredSize * (self.mirrors + 1)
+
+ LogicalVolumeRequestSpec.__init__(self, fstype, format=format, mountpoint=mountpoint,
+ size=self.mirroredSize * (self.mirrors + 1), volgroup=volgroup, lvname=lvname, preexist=preexist,
+ percent=percent, grow=grow, maxSizeMB=maxSizeMB, bytesPerInode=bytesPerInode, fslabel=fslabel)
+
+ self.requestSize = self.mirroredSize
+
+ def __str__(self):
+ devices = ""
+ for dev in self.devs:
+ devices = "%s,%s"%(devices, dev)
+ devices = devices.strip(",")
+ str = (" %(lvstr)s \n"
+ " mirrors: %(mirrors) devices: %(devices)s corelog: %(corelog)s" %
+ { "lvstr": LogicalVolumeRequestSpec.__str__(self), "mirrors":self.mirrors,
+ "devices":devices, "corelog":self.corelog})
+ return str
+
+ def setSize(self, size):
+ # We will not allow size change for now.
+ raise RuntimeError, "The size of the mirrored lv was going to be changed. This is not possible for now."
+
+
+ def getDevice(self, partitions):
+ """Return a device which can be solidified."""
+ devices = []
+ for dev in self.devs:
+ devices.append("/dev/%s"%partitions.getRequestByID(dev).device)
+ vg = partitions.getRequestByID(self.volumeGroup)
+ vgname = vg.volumeGroupName
+ self.dev = fsset.MirroredLogicalVolumeDevice(vgname, self.mirroredSize,
+ self.logicalVolumeName,
+ vg = vg,
+ existing = self.preexist,
+ mirrors=self.mirrors,
+ corelog=self.corelog,
+ devs=devices)
+ return self.dev
+
+ def sanityCheckMirroredRequest(self, partitions, diskset):
+ peSize = partitions.getRequestByID(self.volumeGroup).pesize
+ #We mainly check that the size stuff is ok.
+ for dev in self.devs:
+ devReq = partitions.getRequestByID(dev)
+ actualSize = devReq.getActualSize(partitions, diskset)
+ if devReq.grow and actualSize < self.mirroredSize:
+ # After the devices grew, it was still insuficient space to hold the lv.
+ return _("After growing one of the Physical Volumes it was still insuficient "
+ "to hold %s Mirrored Logical Volume." % self.logicalVolumeName)
+ if not devReq.grow and devReq.requestSize < self.mirroredRequestSize:
+ # Must be a mistake in the ksfile
+ return _("All Physical Volumes must be greater than or equal to the size of "
+ "the mirrored Logical Volume that will contain them.")
+ if not devReq.grow and lvm.clampPVSize(actualSize,peSize) < self.mirroredSize and devReq.requestSize >= actualSize:
+ #This basically means that the actual size of the pv was rounded up.
+ #Change the self.mirroredSize and continue
+ self.mirroredSize = lvm.clampPVSize(actualSize,peSize)
Index: partitions.py
===================================================================
RCS file: /usr/local/CVS/anaconda/partitions.py,v
retrieving revision 1.108
diff -u -r1.108 partitions.py
--- partitions.py 23 Aug 2007 14:58:15 -0000 1.108
+++ partitions.py 31 Aug 2007 13:17:17 -0000
@@ -957,6 +957,10 @@
rc = request.sanityCheckRaid(self)
if rc:
errors.append(rc)
+ if isinstance(request, partRequests.MirroredLogicalVolumeRequestSpec):
+ rc = request.sanityCheckMirroredRequest(self, diskset)
+ if rc:
+ errors.append(rc)
if not hasattr(request,'drive'):
continue
for x in request.drive or []:
diff -ur --exclude=partition.py pykickstart-1.8/pykickstart/commands/logvol.py pykickstart-1.8-Mirroring/pykickstart/commands/logvol.py
--- pykickstart-1.8/pykickstart/commands/logvol.py 2007-08-09 20:51:38.000000000 +0200
+++ pykickstart-1.8-Mirroring/pykickstart/commands/logvol.py 2007-08-31 15:04:41.000000000 +0200
@@ -89,6 +89,30 @@
return retval + "\n"
+class F8_LogVolData(FC4_LogVolData):
+ def __init__(self, bytesPerInode=4096, fsopts="", fstype="", grow=False,
+ maxSizeMB=0, name="", format=True, percent=0,
+ recommended=False, size=None, preexist=False, vgname="",
+ mountpoint="", mirrors=0, devs=[], nocorelog=True):
+ FC4_LogVolData.__init__(self, bytesPerInode=bytesPerInode, fsopts=fsopts, fstype=fstype, grow=grow,
+ maxSizeMB=maxSizeMB, name=name, format=format, percent=percent, recommended=recommended,
+ size=size, preexist=preexist, vgname=vgname, mountpoint=mountpoint)
+ self.mirrors = mirrors
+ self.devs = devs
+ self.nocorelog = nocorelog
+
+ def __str__(self):
+ retval = FC4_LogVolData.__str__(self).strip()
+
+ if self.mirrors > 0:
+ retval += " --mirrors=%d" % self.mirrors
+ if self.nocorelog:
+ retval += " --nocorelog"
+ if self.devs > 0:
+ retval += " --devs=%s"%",".join(self.devs)
+
+ return retval + "\n"
+
class FC3_LogVol(KickstartCommand):
def __init__(self, writePriority=132, lvList=None):
KickstartCommand.__init__(self, writePriority)
@@ -183,3 +207,54 @@
self._setToObj(op, opts, lvd)
lvd.mountpoint=extra[0]
self.add(lvd)
+
+class F8_LogVol(FC4_LogVol):
+ def __init__(self, writePriority=132, lvList=None):
+ FC4_LogVol.__init__(self, writePriority, lvList)
+
+ def parse(self, args):
+ def lv_cb (option, opt_str, value, parser):
+ parser.values.format = False
+ parser.values.preexist = True
+
+ def dev_cb (option, opt_str, value, parser):
+ for d in value.split(','):
+ parser.values.ensure_value(option.dest, []).append(d)
+
+ op = KSOptionParser(lineno=self.lineno)
+ op.add_option("--bytes-per-inode", dest="bytesPerInode", action="store",
+ type="int", nargs=1)
+ op.add_option("--fsoptions", dest="fsopts")
+ op.add_option("--fstype", dest="fstype")
+ op.add_option("--grow", dest="grow", action="store_true",
+ default=False)
+ op.add_option("--maxsize", dest="maxSizeMB", action="store", type="int",
+ nargs=1)
+ op.add_option("--name", dest="name", required=1)
+ op.add_option("--noformat", action="callback", callback=lv_cb,
+ dest="format", default=True, nargs=0)
+ op.add_option("--percent", dest="percent", action="store", type="int",
+ nargs=1)
+ op.add_option("--recommended", dest="recommended", action="store_true",
+ default=False)
+ op.add_option("--size", dest="size", action="store", type="int",
+ nargs=1)
+ op.add_option("--useexisting", dest="preexist", action="store_true",
+ default=False)
+ op.add_option("--vgname", dest="vgname", required=1)
+ op.add_option("--mirrors", "-m", dest="mirrors", type="int", action="store",
+ nargs=1, default=0)
+ op.add_option("--devs", dest="devs", type="string", action="callback",
+ callback=dev_cb, nargs=1, default=[])
+ op.add_option("--nocorelog", dest="nocorelog", action="store_true", default=False)
+
+ (opts, extra) = op.parse_args(args=args)
+
+ if len(extra) == 0:
+ raise KickstartValueError, formatErrorMsg(self.lineno, msg=_("Mount point required for %s") % "logvol")
+
+ lvd = F8_LogVolData()
+ self._setToObj(op, opts, lvd)
+ lvd.mountpoint=extra[0]
+ lvd.corelog = not lvd.nocorelog
+ self.add(lvd)
diff -ur --exclude=partition.py pykickstart-1.8/pykickstart/handlers/control.py pykickstart-1.8-Mirroring/pykickstart/handlers/control.py
--- pykickstart-1.8/pykickstart/handlers/control.py 2007-08-09 20:51:38.000000000 +0200
+++ pykickstart-1.8-Mirroring/pykickstart/handlers/control.py 2007-08-31 14:00:07.000000000 +0200
@@ -321,7 +321,7 @@
"keyboard": keyboard.FC3_Keyboard,
"lang": lang.FC3_Lang,
"logging": logging.FC6_Logging,
- "logvol": logvol.FC4_LogVol,
+ "logvol": logvol.F8_LogVol,
"mediacheck": mediacheck.FC4_MediaCheck,
"monitor": monitor.FC6_Monitor,
"multipath": multipath.FC6_MultiPath,