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.
--
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 27 Aug 2007 18:18:05 -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, LogicalVolumeDevice) and entry.device.mirrors > 0:
+ 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):
@@ -2160,7 +2170,12 @@
class LogicalVolumeDevice(Device):
# note that size is in megabytes!
- def __init__(self, vgname, size, lvname, vg, existing = 0):
+ 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.
+ """
Device.__init__(self)
self.vgname = vgname
self.size = size
@@ -2169,6 +2184,9 @@
self.isSetup = existing
self.doLabel = None
self.vg = vg
+ self.mirrors = mirrors #If mirrors is set to 0 mirroring is ignored.
+ self.devs = devs
+ self.corelog = corelog
# these are attributes we might want to expose. or maybe not.
# self.chunksize
@@ -2179,7 +2197,7 @@
def setupDevice(self, chroot="/", devPrefix='/tmp', vgdevice = None):
if not self.isSetup:
- lvm.lvcreate(self.name, self.vgname, self.size)
+ lvm.lvcreate(self.name, self.vgname, self.size, mirrors=self.mirrors, corelog=self.corelog, devs=self.devs)
self.isSetup = 1
if vgdevice and vgdevice.isNetdev():
Index: kickstart.py
===================================================================
RCS file: /usr/local/CVS/anaconda/kickstart.py,v
retrieving revision 1.385
diff -u -r1.385 kickstart.py
--- kickstart.py 23 Aug 2007 19:38:51 -0000 1.385
+++ kickstart.py 27 Aug 2007 18:18:05 -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,47 @@
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 +735,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 27 Aug 2007 18:18:05 -0000
@@ -157,12 +157,15 @@
log.error("running vgchange failed: %s" %(rc,))
# lvmDevicePresent = 0
-def lvcreate(lvname, vgname, size):
+def lvcreate(lvname, vgname, size, mirrors=0, corelog=True, devs=[]):
"""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.
+ 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:
@@ -171,6 +174,8 @@
vgscan()
args = ["lvcreate", "-v", "-L", "%dM" %(size,), "-n", lvname, "-An", vgname]
+ if mirrors > 0:
+ args = args[:4]+["-m","%s"%mirrors, corelog and "--corelog"]+args[4:]+devs
try:
rc = lvmExec(*args)
except:
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 27 Aug 2007 18:18:05 -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, "Somehow 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.LogicalVolumeDevice(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.
+ #Canget 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 27 Aug 2007 18:18:05 -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 []:
--- 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-24 18:15:11.000000000 +0200
@@ -183,3 +183,53 @@
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("--corelog", dest="corelog", action="store_true", default=True)
+
+ (opts, extra) = op.parse_args(args=args)
+
+ if len(extra) == 0:
+ raise KickstartValueError, formatErrorMsg(self.lineno, msg=_("Mount point required for %s") % "logvol")
+
+ lvd = FC4_LogVolData()
+ self._setToObj(op, opts, lvd)
+ lvd.mountpoint=extra[0]
+ self.add(lvd)