diff options
Diffstat (limited to 'partitioning.py')
-rw-r--r-- | partitioning.py | 662 |
1 files changed, 13 insertions, 649 deletions
diff --git a/partitioning.py b/partitioning.py index c8f182e68..de246b01a 100644 --- a/partitioning.py +++ b/partitioning.py @@ -22,7 +22,6 @@ if __name__ == "__main__": import isys import parted -import math import raid import fsset import os @@ -36,27 +35,7 @@ from log import log from constants import * from flags import flags from partErrors import * - -# different types of partition requests -# REQUEST_PREEXIST is a placeholder for a pre-existing partition on the system -# REQUEST_NEW is a request for a partition which will be automatically -# created based on various constraints on size, drive, etc -# REQUEST_RAID is a request for a raid device -# REQUEST_PROTECTED is a preexisting partition which can't change -# (harddrive install, harddrive with the isos on it) -# -REQUEST_PREEXIST = 1 -REQUEST_NEW = 2 -REQUEST_RAID = 4 -REQUEST_PROTECTED = 8 -REQUEST_VG = 16 # volume group -REQUEST_LV = 32 # logical volume - -# when clearing partitions, what do we clear -CLEARPART_TYPE_LINUX = 1 -CLEARPART_TYPE_ALL = 2 -CLEARPART_TYPE_NONE = 3 - +import partRequests def query_is_linux_native_by_numtype(numtype): linuxtypes = [0x82, 0x83, 0x8e, 0xfd] @@ -234,6 +213,7 @@ def sanityCheckMountPoint(mntpt, fstype, reqtype): # its an existing partition so don't force a mount point return None +# XXX ermm, this function is silly... just check the name not using the req def isVolumeGroupNameInUse(reqpartitions, req): volname = req.volumeGroupName if not volname: @@ -592,629 +572,11 @@ def deleteAllLogicalPartitions(part, requests): requests.removeRequest(request) if request.type == REQUEST_PREEXIST: drive = partedUtils.get_partition_drive(partition) - delete = DeleteSpec(drive, partition.geom.start, partition.geom.end) + delete = partRequests.DeleteSpec(drive, partition.geom.start, + partition.geom.end) requests.addDelete(delete) -class DeleteSpec: - def __init__(self, drive, start, end): - self.drive = drive - self.start = start - self.end = end - - def __str__(self): - return "drive: %s start: %s end: %s" %(self.drive, self.start, self.end) - - -# XXX subclass me. should have a generic specification and derive -# partition, raid, and lvm from me. then it would be a lot less crufty -class PartitionSpec: - def __init__(self, fstype, requesttype = REQUEST_NEW, - size = None, grow = 0, maxSizeMB = None, - mountpoint = None, origfstype = None, - start = None, end = None, partnum = None, - drive = None, primary = None, - format = None, options = None, - constraint = None, migrate = None, - raidmembers = None, raidlevel = None, raidminor = None, - raidspares = None, badblocks = None, fslabel = None, - physvolumes = None, vgname = None, - volgroup = None, volname = None): - # - # requesttype: REQUEST_PREEXIST or REQUEST_NEW or REQUEST_RAID - # - # XXX: unenforced requirements for a partition spec - # must have (size) || (start && end) - # fs_type, mountpoint - # if partnum, require drive - # - # Some notes: - # format - if is 1, format. - # migrate - if is 1, convert from origfstype to fstype. - # - self.type = requesttype - self.fstype = fstype - self.origfstype = origfstype - self.size = size - self.grow = grow - self.maxSizeMB = maxSizeMB - self.mountpoint = mountpoint - self.start = start - self.end = end - self.partnum = partnum - self.drive = drive - self.primary = primary - self.format = format - self.badblocks = badblocks - self.migrate = migrate - self.options = options - self.constraint = constraint - self.partition = None - self.requestSize = size - - # note that the raidmembers are the unique id of the requests - self.raidmembers = raidmembers - self.raidlevel = raidlevel - self.raidspares = raidspares - self.raidminor = raidminor - - # volume group specific. physicalVolumes are unique ids of requests - self.physicalVolumes = physvolumes - self.volumeGroupName = vgname - - # logical volume specific. volgroup is the uniqueID of the VG - self.volumeGroup = volgroup - self.logicalVolumeName = volname - - # fs label (if pre-existing, otherwise None) - self.fslabel = fslabel - - # device is what we currently think the device is - # realDevice is used by partitions which are pre-existing - self.device = None - self.realDevice = None - - # there has to be a way to go from device -> drive... but for now - self.currentDrive = None - - # unique id for each request - self.uniqueID = None - - # ignore booting constraints for this request - self.ignoreBootConstraints = 0 - - def __str__(self): - if self.fstype: - fsname = self.fstype.getName() - else: - fsname = "None" - raidmem = [] - if self.raidmembers: - for i in self.raidmembers: - raidmem.append(i) - - return "mountpoint: %s type: %s uniqueID:%s\n" %(self.mountpoint, fsname, self.uniqueID) +\ - " size: %sM requestSize: %sM grow: %s max: %s\n" %(self.size, self.requestSize, self.grow, self.maxSizeMB) +\ - " start: %s end: %s partnum: %s\n" %(self.start, self.end, self.partnum) +\ - " drive: %s primary: %s \n" %(self.drive, self.primary) +\ - " format: %s, options: %s" %(self.format, self.options) +\ - " device: %s, currentDrive: %s\n" %(self.device, self.currentDrive)+\ - " raidlevel: %s" % (self.raidlevel)+\ - " raidspares: %s" % (self.raidspares)+\ - " raidmembers: %s\n" % (raidmem)+\ - " vgname: %s" % (self.volumeGroupName)+\ - " physical volumes: %s\n" % (self.physicalVolumes)+\ - " parent volume group: %s" % (self.volumeGroup)+\ - " logical volume name: %s" % (self.logicalVolumeName) - - - # turn a partition request into a fsset entry - def toEntry(self, partitions): - if self.type == REQUEST_RAID: - raidmems = [] - for member in self.raidmembers: - raidmems.append(partitions.getRequestByID(member).device) - device = fsset.RAIDDevice(int(self.raidlevel[-1:]), - raidmems, minor = self.raidminor, - spares = self.raidspares) - # XXX need to handle this obviously - elif self.type == REQUEST_VG: - pvs = [] - for pv in self.physicalVolumes: - pvs.append(partitions.getRequestByID(pv).device) - device = fsset.VolumeGroupDevice(self.volumeGroupName, pvs) - elif self.type == REQUEST_LV: - device = fsset.LogicalVolumeDevice( - partitions.getRequestByID(self.volumeGroup).volumeGroupName, - self.size, - self.logicalVolumeName) - else: - device = fsset.PartitionDevice(self.device) - - # pin down our partitions so that we can reread the table - device.solidify() - - if self.fstype.getName() == "swap": - mountpoint = "swap" - else: - mountpoint = self.mountpoint - - entry = fsset.FileSystemSetEntry(device, mountpoint, self.fstype, - origfsystem=self.origfstype) - if self.format: - entry.setFormat(self.format) - - if self.migrate: - entry.setMigrate(self.migrate) - - if self.badblocks: - entry.setBadblocks(self.badblocks) - - return entry - -class Partitions: - def __init__ (self, diskset = None): - # requests for partitions including preexisting partitions - # a list of PartitionSpec objects - self.requests = [] - - # preexisting partitions which should be deleted - # a list of DeleteSpec objects - self.deletes = [] - - # auto partitioning requests - # a list of PartitionSpec objects - # these are set by the installclass and then folded into self.requests - self.autoPartitionRequests = [] - - # CLEARPART_TYPE_LINUX, CLEARPART_TYPE_ALL, CLEARPART_TYPE_NONE - # used by installclasses to say which partitions to clear - self.autoClearPartType = CLEARPART_TYPE_NONE - - # drives to clear partitions on (following self.autoClearPartType) - # note that None clears ALL drives - self.autoClearPartDrives = None - - # internal counter... if you use it as an ID, increment it to avoid - # problems later on - self.nextUniqueID = 1 - - # reinitialize all partitions to default labels? - self.reinitializeDisks = 0 - - # zero mbr flag for kickstart - self.zeroMbr = 0 - - # partition method - self.useAutopartitioning = 1 - self.useFdisk = 0 - - # autopartitioning info becomes kickstart partition requests - # and its useful to be able to differentiate between the two - self.isKickstart = 0 - - if diskset: - self.setFromDisk(diskset) - - - # clear out the delete list and initialize all partitions which - # currently exist on the disk - def setFromDisk(self, diskset): - self.deletes = [] - self.requests = [] - diskset.refreshDevices() - labels = diskset.getLabels() - drives = diskset.disks.keys() - drives.sort() - for drive in drives: - disk = diskset.disks[drive] - part = disk.next_partition() - while part: - if part.type & parted.PARTITION_METADATA: - part = disk.next_partition(part) - continue - - format = None - if part.type & parted.PARTITION_FREESPACE: - ptype = None - elif part.type & parted.PARTITION_EXTENDED: - ptype = None - elif part.get_flag(parted.PARTITION_RAID) == 1: - ptype = fsset.fileSystemTypeGet("software RAID") - elif part.get_flag(parted.PARTITION_LVM) == 1: - ptype = fsset.fileSystemTypeGet("physical volume (LVM)") - elif part.fs_type: - ptype = partedUtils.get_partition_file_system_type(part) - if part.fs_type.name == "linux-swap": - # XXX this is a hack - format = 1 - else: - ptype = fsset.fileSystemTypeGet("foreign") - - start = part.geom.start - end = part.geom.end - size = partedUtils.getPartSizeMB(part) - drive = partedUtils.get_partition_drive(part) - - spec = PartitionSpec(ptype, origfstype = ptype, - requesttype = REQUEST_PREEXIST, - start = start, end = end, size = size, - drive = drive, format = format) - spec.device = fsset.PartedPartitionDevice(part).getDevice() - - # set label if makes sense - if ptype and ptype.isMountable() and \ - (ptype.getName() == "ext2" or ptype.getName() == "ext3"): - if spec.device in labels.keys(): - if labels[spec.device] and len(labels[spec.device])>0: - spec.fslabel = labels[spec.device] - - self.addRequest(spec) - part = disk.next_partition(part) - - def addRequest (self, request): - if not request.uniqueID: - request.uniqueID = self.nextUniqueID - self.nextUniqueID = self.nextUniqueID + 1 - self.requests.append(request) - self.requests.sort() - - def addDelete (self, delete): - self.deletes.append(delete) - self.deletes.sort() - - def removeRequest (self, request): - self.requests.remove(request) - - def getRequestByMountPoint(self, mount): - for request in self.requests: - if request.mountpoint == mount: - return request - - for request in self.requests: - if request.type == REQUEST_LV and request.mountpoint == mount: - return request - return None - - def getRequestByDeviceName(self, device): - if device is None: - return None - - for request in self.requests: - if request.device == device: - return request - - - def getRequestByVolumeGroupName(self, volname): - # now look for a Volume group or logical volume that matches - if volname is None: - return None - - for request in self.requests: - if request.type == REQUEST_VG and request.volumeGroupName == volname: - return request - return None - - def getRequestByLogicalVolumeName(self, lvname): - if lvname is None: - return None - for request in self.requests: - if request.type == REQUEST_LV and request.logicalVolumeName == lvname: - return request - - - def getRequestByID(self, id): - if type(id) == type("a string"): - id = int(id) - for request in self.requests: - if request.uniqueID == id: - return request - return None - - def getRaidRequests(self): - retval = [] - for request in self.requests: - if request.type == REQUEST_RAID: - retval.append(request) - - return retval - - def isRaidMember(self, request): - raiddev = self.getRaidRequests() - if not raiddev or not request.device: - return 0 - for dev in raiddev: - if not dev.raidmembers: - continue - for member in dev.raidmembers: - if request.device == self.getRequestByID(member).device: - return 1 - return 0 - # LVM helpers - def getLVMVolGroupNames(self, requests): - retval = [] - for request in self.requests: - if request.type == REQUEST_VG: - retval.append(request) - - return retval - - def getLVMLVForVG(self, vgrequest): - retval = [] - pvid = vgrequest.uniqueID - for request in self.requests: - if request.type == REQUEST_LV: - if request.volumeGroup == pvid: - retval.append(request) - - return retval - - def getLVMRequests(self): - retval = {} - for request in self.requests: - if request.type == REQUEST_VG: - retval[request.volumeGroupName] = self.getLVMLVForVG(request) - - return retval - - def getLVMVGRequests(self): - retval = [] - for request in self.requests: - if request.type == REQUEST_VG: - retval.append(request) - - return retval - - def getLVMLVRequests(self): - retval = [] - for request in self.requests: - if request.type == REQUEST_LV: - retval.append(request) - - return retval - - def isLVMVolumeGroupMember(self, request): - volgroups = self.getLVMVGRequests() - if not volgroups: - return 0 - - used = 0 - for volgroup in volgroups: - if volgroup.physicalVolumes: - if request.uniqueID in volgroup.physicalVolumes: - used = 1 - - if used: - break - - return used - - # return name of boot mount point in current requests - def getBootableRequest(self): - bootreq = None - - if iutil.getArch() == "ia64": - bootreq = self.getRequestByMountPoint("/boot/efi") - return bootreq - if not bootreq: - bootreq = self.getRequestByMountPoint("/boot") - if not bootreq: - bootreq = self.getRequestByMountPoint("/") - - return bootreq - - # returns if request is a "bootable" - # returns 0 if not, returns 1 if it is returned by getBootableRequest - # or is a member of the RAID request returned by getBootableRequest - def isBootable(self, request): - bootreq = self.getBootableRequest() - if not bootreq: - return 0 - - if bootreq == request: - return 1 - - if bootreq.type == REQUEST_RAID and \ - request.uniqueID in bootreq.raidmembers: - return 1 - - return 0 - - def sortRequests(self): - n = 0 - while n < len(self.requests): - for request in self.requests: - if (request.size and self.requests[n].size and - (request.size < self.requests[n].size)): - tmp = self.requests[n] - index = self.requests.index(request) - self.requests[n] = request - self.requests[index] = tmp - elif (request.start and self.requests[n].start and - (request.drive == self.requests[n].drive) and - (request.type == self.requests[n].type) and - (request.start > self.requests[n].start)): - tmp = self.requests[n] - index = self.requests.index(request) - self.requests[n] = request - self.requests[index] = tmp - elif (request.size and self.requests[n].size and - (request.size == self.requests[n].size) and - (request.uniqueID < self.requests[n].uniqueID)): - tmp = self.requests[n] - index = self.requests.index(request) - self.requests[n] = request - self.requests[index] = tmp - n = n + 1 - - tmp = self.getBootableRequest() - - # if raid, we want all of the contents of the bootable raid - if tmp and tmp.type == REQUEST_RAID: - boot = [] - for member in tmp.raidmembers: - boot.append(self.getRequestByID(member)) - elif tmp: - boot = [tmp] - else: - boot = [] - - # remove the bootables from the request - for bootable in boot: - self.requests.pop(self.requests.index(bootable)) - - # move to the front of the list - boot.extend(self.requests) - self.requests = boot - - def copy (self): - new = Partitions() - for request in self.requests: - new.addRequest(request) - for delete in self.deletes: - new.addDelete(delete) - new.autoPartitionRequests = self.autoPartitionRequests - new.autoClearPartType = self.autoClearPartType - new.autoClearPartDrives = self.autoClearPartDrives - new.nextUniqueID = self.nextUniqueID - new.useAutopartitioning = self.useAutopartitioning - new.useFdisk = self.useFdisk - new.reinitializeDisks = self.reinitializeDisks - return new - - def getClearPart(self): - clearpartargs = [] - if self.autoClearPartType == CLEARPART_TYPE_LINUX: - clearpartargs.append('--linux') - elif self.autoClearPartType == CLEARPART_TYPE_ALL: - clearpartargs.append('--all') - else: - return None - - if self.reinitializeDisks: - clearpartargs.append('--initlabel') - - if self.autoClearPartDrives: - drives = string.join(self.autoClearPartDrives, ',') - clearpartargs.append('--drives=%s' % (drives)) - - return "#clearpart %s\n" %(string.join(clearpartargs)) - - def writeKS(self, f): - f.write("# The following is the partition information you requested\n") - f.write("# Note that any partitions you deleted are not expressed\n") - f.write("# here so unless you clear all partitions first, this is\n") - f.write("# not guaranteed to work\n") - clearpart = self.getClearPart() - if clearpart: - f.write(clearpart) - - # two passes here, once to write out parts, once to write out raids - # XXX what do we do with deleted partitions? - for request in self.requests: - args = [] - if request.type == REQUEST_RAID: - continue - - # no fstype, no deal (same with foreigns) - if not request.fstype or request.fstype.getName() == "foreign": - continue - - # first argument is mountpoint, which can also be swap or - # the unique RAID identifier. I hate kickstart partitioning - # syntax. a lot. too many special cases - if request.fstype.getName() == "swap": - args.append("swap") - elif request.fstype.getName() == "software RAID": - if ((type(request.uniqueID) != type("")) or - (request.uniqueID[0:5] != "raid.")): - args.append("raid.%s" % (request.uniqueID)) - else: - args.append("%s" % (request.uniqueID)) - elif request.mountpoint: - args.append(request.mountpoint) - args.append("--fstype") - args.append(request.fstype.getName()) - else: - continue - - # generic options - if not request.format: - args.append("--noformat") - if request.badblocks: - args.append("--badblocks") - - # preexisting only - if request.type == REQUEST_PREEXIST and request.device: - args.append("--onpart") - args.append(request.device) - # we have a billion ways to specify new partitions - elif request.type == REQUEST_NEW: - if request.size: - args.append("--size=%s" % (request.size)) - if request.grow: - args.append("--grow") - if request.start: - args.append("--start=%s" % (request.start)) - if request.end: - args.append("--end=%s" % (request.end)) - if request.maxSizeMB: - args.append("--maxsize=%s" % (request.maxSizeMB)) - if request.drive: - args.append("--ondisk=%s" % (request.drive[0])) - if request.primary: - args.append("--asprimary") - else: # how the hell did we get this? - continue - - f.write("#part %s\n" % (string.join(args))) - - - for request in self.requests: - args = [] - if request.type != REQUEST_RAID: - continue - - # no fstype, no deal (same with foreigns) - if not request.fstype or request.fstype.getName() == "foreign": - continue - - # also require a raidlevel and raidmembers for raid - if (request.raidlevel == None) or not request.raidmembers: - continue - - # first argument is mountpoint, which can also be swap - if request.fstype.getName() == "swap": - args.append("swap") - elif request.mountpoint: - args.append(request.mountpoint) - else: - continue - - # generic options - if not request.format: - args.append("--noformat") - if request.fstype: - args.append("--fstype") - args.append(request.fstype.getName()) - if request.badblocks: - args.append("--badblocks") - - args.append("--level=%s" % (request.raidlevel)) - - if request.raidspares: - args.append("--spares=%s" % (request.raidspares)) - - # silly raid member syntax - raidmems = [] - for member in request.raidmembers: - if (type(member) != type("")) or (member[0:5] != "raid."): - raidmems.append("raid.%s" % (member)) - else: - raidmems.append(member) - args.append("%s" % (string.join(raidmems))) - - f.write("#raid %s\n" % (string.join(args))) def partitionObjectsInitialize(diskset, partitions, dir, intf): if iutil.getArch() == "s390": @@ -1281,13 +643,12 @@ def autoCreatePartitionRequests(autoreq): else: ptype = fsset.fileSystemTypeGetDefault() - newrequest = PartitionSpec(ptype, - mountpoint = mntpt, - size = minsize, - maxSizeMB = maxsize, - grow = grow, - requesttype = REQUEST_NEW, - format = format) + newrequest = partRequests.PartitionSpec(ptype, + mountpoint = mntpt, + size = minsize, + maxSizeMB = maxsize, + grow = grow, + format = format) requests.append(newrequest) @@ -1327,6 +688,7 @@ def containsImmutablePart(part, requestlist): return _("a partition which is a member of a RAID array.") part = disk.next_partition(part) + return None def partitioningComplete(bl, fsset, diskSet, partitions, intf, instPath, dir): if dir == DISPATCH_BACK and fsset.isActive(): @@ -1373,5 +735,7 @@ def partitioningComplete(bl, fsset, diskSet, partitions, intf, instPath, dir): fsset.formatSwap(instPath) fsset.turnOnSwap(instPath) + return + |