summaryrefslogtreecommitdiffstats
path: root/partitioning.py
diff options
context:
space:
mode:
Diffstat (limited to 'partitioning.py')
-rw-r--r--partitioning.py662
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
+