diff options
-rw-r--r-- | autopart.py | 8 | ||||
-rw-r--r-- | constants.py | 21 | ||||
-rw-r--r-- | instdata.py | 4 | ||||
-rw-r--r-- | iw/partition_gui.py | 27 | ||||
-rw-r--r-- | kickstart.py | 6 | ||||
-rw-r--r-- | partIntfHelpers.py | 23 | ||||
-rw-r--r-- | partRequests.py | 425 | ||||
-rw-r--r-- | partitioning.py | 662 | ||||
-rw-r--r-- | partitions.py | 513 | ||||
-rw-r--r-- | textw/partition_text.py | 5 |
10 files changed, 1007 insertions, 687 deletions
diff --git a/autopart.py b/autopart.py index 02351115f..5522ea2f3 100644 --- a/autopart.py +++ b/autopart.py @@ -20,6 +20,7 @@ import string, sys import fsset from partitioning import * import partedUtils +import partRequests from constants import * from translate import _, N_ from partErrors import * @@ -812,7 +813,8 @@ def doClearPartAction(partitions, diskset): partitions.removeRequest(old) drive = partedUtils.get_partition_drive(part) - delete = DeleteSpec(drive, part.geom.start, part.geom.end) + delete = partRequests.DeleteSpec(drive, part.geom.start, + part.geom.end) partitions.addDelete(delete) # ia64 autopartitioning is strange as /boot/efi is vfat -- @@ -847,8 +849,10 @@ def doClearPartAction(partitions, diskset): disk = diskset.disks[drive] ext = disk.extended_partition + # if the extended is empty, blow it away if ext and len(partedUtils.get_logical_partitions(disk)) == 0: - delete = DeleteSpec(drive, ext.geom.start, ext.geom.end) + delete = partRequests.DeleteSpec(drive, ext.geom.start, + ext.geom.end) old = partitions.getRequestByDeviceName(partedUtils.get_partition_name(ext)) partitions.removeRequest(old) partitions.addDelete(delete) diff --git a/constants.py b/constants.py index 9746ebb84..ed24b0436 100644 --- a/constants.py +++ b/constants.py @@ -16,3 +16,24 @@ DISPATCH_BACK = -1 DISPATCH_FORWARD = 1 DISPATCH_NOOP = None + + +# 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 diff --git a/instdata.py b/instdata.py index 9cfa4e6a2..73121c947 100644 --- a/instdata.py +++ b/instdata.py @@ -22,7 +22,7 @@ import desktop import users import fsset import bootloader -import partitioning +import partitions import partedUtils from flags import * @@ -64,7 +64,7 @@ class InstallData: # XXX move fsset and/or diskset into Partitions object? self.fsset.reset() self.diskset = partedUtils.DiskSet() - self.partitions = partitioning.Partitions() + self.partitions = partitions.Partitions() self.bootloader = bootloader.getBootloader() self.dependencies = [] self.dbpath = None diff --git a/iw/partition_gui.py b/iw/partition_gui.py index f07f88ed1..d092fe41b 100644 --- a/iw/partition_gui.py +++ b/iw/partition_gui.py @@ -32,6 +32,7 @@ from partitioning import * from partIntfHelpers import * from partedUtils import * from fsset import * +from partRequests import * STRIPE_HEIGHT = 32.0 LOGICAL_INSET = 3.0 @@ -1003,7 +1004,7 @@ class PartitionWindow(InstallWindow): def newCB(self, widget): # create new request of size 1M - request = PartitionSpec(fileSystemTypeGetDefault(), REQUEST_NEW, 1) + request = NewPartitionSpec(fileSystemTypeGetDefault(), size = 1) self.editPartitionRequest(request, isNew = 1) @@ -1922,8 +1923,8 @@ class PartitionWindow(InstallWindow): iter = self.getCurrentLogicalVolume() self.logvolstore.remove(iter) - request = PartitionSpec(fsystem, REQUEST_LV, mountpoint = mntpt, - volname = lvname, size = size) + request = LogicalVolumeRequestSpec(fsystem, mountpoint = mntpt, + lvname = lvname, size = size) self.logvolreqs.append(request) iter = self.logvolstore.append() @@ -2148,9 +2149,8 @@ class PartitionWindow(InstallWindow): origname = None if origvname != volname: - tmpreq = PartitionSpec(fileSystemTypeGet("volume group (LVM)"), - REQUEST_VG, physvolumes = pv, - vgname = volname) + tmpreq = VolumeGroupRequestSpec(physvols = pv, + vgname = volname) if isVolumeGroupNameInUse(self.partitions, tmpreq): self.intf.messageWindow(_("Name in use"), _("The volume group name %s is " @@ -2172,14 +2172,8 @@ class PartitionWindow(InstallWindow): self.partitions.removeRequest(origvgrequest) - request = PartitionSpec(fileSystemTypeGet("volume group (LVM)"), - REQUEST_VG, physvolumes = pv, - vgname = volname) - - self.partitions.addRequest(request) - - # this is an evil hack for now. should addRequest return the id? - vgID = self.partitions.nextUniqueID - 1 + request = VolumeGroupRequestSpec(physvols = pv, vgname = volname) + vgID = self.partitions.addRequest(request) # now add the logical volumes for lv in self.logvolreqs: @@ -2203,14 +2197,13 @@ class PartitionWindow(InstallWindow): def makeLvmCB(self, widget): - request = PartitionSpec(fileSystemTypeGet("volume group (LVM)"), - REQUEST_VG) + request = VolumeGroupRequestSpec() self.editLVMVolumeGroup(request, isNew = 1) return def makeraidCB(self, widget): - request = PartitionSpec(fileSystemTypeGetDefault(), REQUEST_RAID, 1) + request = RaidRequestSpec(fileSystemTypeGetDefault()) self.editRaidRequest(request, isNew = 1) def getScreen(self, fsset, diskset, partitions, intf): diff --git a/kickstart.py b/kickstart.py index c18b3fd3a..abec04593 100644 --- a/kickstart.py +++ b/kickstart.py @@ -660,8 +660,7 @@ class KickstartBase(BaseInstallClass): if len(raidmems) == 0: raise ValueError, "RAID Partition defined without any RAID members" - request = PartitionSpec(filesystem, REQUEST_RAID, - mountpoint = mountpoint, + request = RaidRequestSpec(filesystem, mountpoint = mountpoint, raidmembers = raidmems, raidlevel = level, raidspares = spares, format = format, raidminor = raidDev) @@ -771,7 +770,8 @@ class KickstartBase(BaseInstallClass): if fsopts: filesystem.extraFormatArgs.extend(fsopts) - request = PartitionSpec(filesystem, mountpoint = mountpoint, format=1) + request = PartitionRequestSpec(filesystem, mountpoint = mountpoint, + format = 1) if size: request.size = size if start: diff --git a/partIntfHelpers.py b/partIntfHelpers.py index 1a9b8d79e..a5b6226cd 100644 --- a/partIntfHelpers.py +++ b/partIntfHelpers.py @@ -19,15 +19,14 @@ import string from translate import _ +from constants import * import partedUtils import parted import fsset import iutil +import partRequests -from partitioning import REQUEST_PROTECTED, REQUEST_PREEXIST, REQUEST_RAID -from partitioning import REQUEST_VG, REQUEST_LV, REQUEST_NEW -from partitioning import containsImmutablePart, DeleteSpec, PartitionSpec -from partitioning import deleteAllLogicalPartitions +from partitioning import containsImmutablePart, deleteAllLogicalPartitions def sanityCheckVolumeGroupName(volname): """Make sure that the volume group name doesn't contain invalid chars.""" @@ -148,8 +147,8 @@ def doDeletePartitionByRequest(intf, requestlist, partition): if partition.type & parted.PARTITION_EXTENDED: deleteAllLogicalPartitions(partition, requestlist) - delete = DeleteSpec(drive, partition.geom.start, - partition.geom.end) + delete = partRequests.DeleteSpec(drive, partition.geom.start, + partition.geom.end) requestlist.addDelete(delete) else: # is this a extended partition we made? if partition.type & parted.PARTITION_EXTENDED: @@ -192,12 +191,12 @@ def doEditPartitionByRequest(intf, requestlist, part): "inititalize this partition")) return (None, None) elif part.type & parted.PARTITION_FREESPACE: - request = PartitionSpec(fsset.fileSystemTypeGetDefault(), REQUEST_NEW, - start = partedUtils.start_sector_to_cyl(part.geom.disk.dev, - part.geom.start), - end = partedUtils.end_sector_to_cyl(part.geom.disk.dev, - part.geom.end), - drive = [ partedUtils.get_partition_drive(part) ]) + request = partRequests.PartitionSpec(fsset.fileSystemTypeGetDefault(), + start = partedUtils.start_sector_to_cyl(part.geom.disk.dev, + part.geom.start), + end = partedUtils.end_sector_to_cyl(part.geom.disk.dev, + part.geom.end), + drive = [ partedUtils.get_partition_drive(part) ]) return ("NEW", request) elif part.type & parted.PARTITION_EXTENDED: diff --git a/partRequests.py b/partRequests.py new file mode 100644 index 000000000..dea247aa5 --- /dev/null +++ b/partRequests.py @@ -0,0 +1,425 @@ +# +# partRequests.py: partition request objects and management thereof +# +# Matt Wilson <msw@redhat.com> +# Jeremy Katz <katzj@redhat.com> +# Mike Fulbright <msf@redhat.com> +# Harald Hoyer <harald@redhat.de> +# +# Copyright 2002 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. +# +"""Partition request objects and management thereof.""" + +import parted +import iutil +import string +import os, sys + +from constants import * + +import fsset +import partedUtils + +class DeleteSpec: + """Defines a preexisting partition which is intended to be removed.""" + + def __init__(self, drive, start, end): + """Initializes a DeleteSpec. + + drive is the text form of the drive + start is the start sector of the deleted partition + end is the end sector of the deleted partition + """ + + 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) + +class RequestSpec: + """Generic Request specification.""" + def __init__(self, fstype, size = None, mountpoint = None, format = None, + badblocks = None, preexist = 0, + migrate = None, origfstype = None): + """Create a generic RequestSpec. + + This should probably never be externally used. + """ + + self.fstype = fstype + self.mountpoint = mountpoint + self.size = size + self.format = format + self.badblocks = badblocks + + self.migrate = migrate + self.origfstype = origfstype + self.fslabel = None + + self.device = None + """what we currently think the device is""" + + self.uniqueID = None + """uniqueID is an integer and *MUST* be unique.""" + + self.ignoreBootConstraints = 0 + """Booting constraints should be ignored for this request.""" + + self.preexist = preexist + """Did this partition exist before we started playing with things?""" + + self.protected = 0 + """Is this partitiion 'protected', ie does it contain install media.""" + + def __str__(self): + if self.fstype: + fsname = self.fstype.getName() + else: + fsname = "None" + + str = ("Generic Request -- mountpoint: %(mount)s uniqueID: %(id)s\n" + " type: %(fstype)s format: %(format)s badblocks: %(bb)s\n" + " device: %(dev)s migrate: %(migrate)s" % + {"mount": self.mountpoint, "id": self.uniqueID, + "fstype": fsname, "format": self.format, "bb": self.badblocks, + "dev": self.device, "migrate": self.migrate}) + return str + + def getDevice(self, partitions): + """Return a device to solidify.""" + + sys.stderr.write("WARNING: Abstract RequestSpec.getDevice() called\n") + import traceback + traceback.print_stack() + + def toEntry(self, partitions): + """Turn a request into a fsset entry and return the entry.""" + device = self.getDevice(partitions) + + # 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 + + def setProtected(self, val): + """Set the protected value for this partition.""" + self.protected = val + + def getProtected(self): + """Return the protected value for this partition.""" + return self.protected + + def getPreExisting(self): + """Return whether the partition existed before we started playing.""" + return self.preexist + +# XXX preexistings store start/end as sectors, new store as cylinders. ICK +class PartitionSpec(RequestSpec): + """Object to define a requested partition.""" + + # XXX eep, still a few too many options but a lot better + def __init__(self, fstype, size = None, mountpoint = None, + preexist = 0, migrate = None, + grow = 0, maxSizeMB = None, + start = None, end = None, + drive = None, primary = None, format = None): + """Create a new PartitionSpec object. + + fstype is the fsset filesystem type. + size is the requested size (in megabytes). + mountpoint is the mountpoint. + grow is whether or not the partition is growable. + maxSizeMB is the maximum size of the partition in megabytes. + start is the starting cylinder/sector (new/preexist). + end is the ending cylinder/sector (new/preexist). + drive is the drive the partition goes on. + primary is whether or not the partition should be forced as primary. + format is whether or not the partition should be formatted. + preexist is whether this partition is preexisting. + migrate is whether or not the partition should be migrated. + """ + + # if it's preexisting, the original fstype should be set + if preexist == 1: + origfs = fstype + else: + origfs = None + + RequestSpec.__init__(self, fstype = fstype, size = size, + mountpoint = mountpoint, format = format, + preexist = preexist, migrate = None, + origfstype = origfs) + self.type = REQUEST_NEW + + self.grow = grow + self.maxSizeMB = maxSizeMB + self.requestSize = size + self.start = start + self.end = end + + self.drive = drive + self.primary = primary + + # should be able to map this from the device =\ + self.currentDrive = None + """Drive that this request will currently end up on.""" + + + def __str__(self): + if self.fstype: + fsname = self.fstype.getName() + else: + fsname = "None" + + if self.origfstype: + oldfs = self.origfstype.getName() + else: + oldfs = "None" + + if self.preexist == 0: + pre = "New" + else: + pre = "Existing" + + str = ("%(n)s Part Request -- mountpoint: %(mount)s uniqueID: %(id)s\n" + " type: %(fstype)s format: %(format)s badblocks: %(bb)s\n" + " device: %(dev)s drive: %(drive) primary: %(primary)s\n" + " size: %(size)s grow: %(grow)s maxsize: %(max)s\n" + " start: %(start)s end: %(end)s" + " migrate: %(migrate)s origfstype: %(origfs)s" % + {"n": pre, "mount": self.mountpoint, "id": self.uniqueID, + "fstype": fsname, "format": self.format, + "dev": self.device, "drive": self.drive, + "primary": self.primary, "size": self.size, + "grow": self.grow, "max": self.maxSizeMB, + "start": self.start, "end": self.end, "bb": self.badblocks, + "migrate": self.migrate, "origfs": oldfs}) + return str + + + def getDevice(self, partitions): + """Return a device to solidify.""" + dev = fsset.PartitionDevice(self.device) + return dev + +class NewPartitionSpec(PartitionSpec): + """Object to define a NEW requested partition.""" + + # XXX eep, still a few too many options but a lot better + def __init__(self, fstype, size = None, mountpoint = None, + grow = 0, maxSizeMB = None, + start = None, end = None, + drive = None, primary = None, format = None): + """Create a new NewPartitionSpec object. + + fstype is the fsset filesystem type. + size is the requested size (in megabytes). + mountpoint is the mountpoint. + grow is whether or not the partition is growable. + maxSizeMB is the maximum size of the partition in megabytes. + start is the starting cylinder. + end is the ending cylinder. + drive is the drive the partition goes on. + primary is whether or not the partition should be forced as primary. + format is whether or not the partition should be formatted. + """ + + PartitionSpec.__init__(self, fstype = fstype, size = size, + mountpoint = mountpoint, grow = grow, + maxSizeMB = maxSizeMB, start = start, + end = end, drive = drive, primary = primary, + format = format, preexist = 0) + self.type = REQUEST_NEW + +class PreexistingPartitionSpec(PartitionSpec): + """Request to represent partitions which already existed.""" + + def __init__(self, fstype, size = None, start = None, end = None, + drive = None, format = None, migrate = None, + mountpoint = None): + """Create a new PreexistingPartitionSpec object. + + fstype is the fsset filesystem type. + size is the size (in megabytes). + start is the starting sector. + end is the ending sector. + drive is the drive which the partition is on. + format is whether or not the partition should be formatted. + migrate is whether or not the partition fs should be migrated. + mountpoint is the mountpoint. + """ + + PartitionSpec.__init__(self, fstype = fstype, size = size, + start = start, end = end, drive = drive, + format = format, migrate = migrate, + mountpoint = mountpoint, preexist = 1) + self.type = REQUEST_PREEXIST + +class RaidRequestSpec(RequestSpec): + """Request to represent RAID devices.""" + + def __init__(self, fstype, format = None, mountpoint = None, + raidlevel = None, raidmembers = None, + raidspares = None, raidminor = None): + """Create a new RaidRequestSpec object. + + fstype is the fsset filesystem type. + format is whether or not the partition should be formatted. + mountpoint is the mountpoint. + raidlevel is the raidlevel (as 'RAID0', 'RAID1', 'RAID5'). + raidmembers is list of ids corresponding to the members of the RAID. + raidspares is the number of spares to setup. + raidminor is the minor of the device which should be used. + """ + + RequestSpec.__init__(self, fstype = fstype, format = format, + mountpoint = mountpoint) + self.type = REQUEST_RAID + + + self.raidlevel = raidlevel + self.raidmembers = raidmembers + self.raidspares = raidspares + self.raidminor = raidminor + + 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) + + str = ("RAID Request -- mountpoint: %(mount)s uniqueID: %(id)s\n" + " type: %(fstype)s format: %(format)s badblocks: %(bb)s\n" + " raidlevel: %(level)s raidspares: %(spares)s\n" + " raidmembers: %(members)s" % + {"mount": self.mountpoint, "id": self.uniqueID, + "fstype": fsname, "format": self.format, "bb": self.badblocks, + "level": self.raidlevel, "spares": self.raidspares, + "members": self.raidmembers}) + return str + + def getDevice(self, partitions): + """Return a device which can be solidified.""" + raidmems = [] + for member in self.raidmembers: + raidmems.append(partitions.getRequestByID(member).device) + dev = fsset.RAIDDevice(int(self.raidlevel[-1:]), + raidmems, minor = self.raidminor, + spares = self.raidspares) + return dev + +class VolumeGroupRequestSpec(RequestSpec): + """Request to represent volume group devices.""" + + def __init__(self, fstype =None, format = None, + vgname = None, physvols = None): + """Create a new VolumeGroupRequestSpec object. + + fstype is the fsset filesystem type. + format is whether or not the volume group should be created. + vgname is the name of the volume group. + physvols is a list of the ids for the physical volumes in the vg. + """ + + if not fstype: + fsset.fileSystemTypeGet("volume group (LVM)") + RequestSpec.__init__(self, fstype = fstype, format = format) + self.type = REQUEST_LV + + self.volumeGroupName = vgname + self.physicalVolumes = physvols + + def __str__(self): + physvols = [] + if self.physicalVolumes: + for i in self.physicalVolumes: + physvols.append(i) + + str = ("VG Request -- name: %(vgname)s uniqueID: %(id)s\n" + " format: %(format)s physvols: %(physvol)s" % + {"vgname": self.volumeGroupName, "id": self.uniqueID, + "format": self.format, "physvol": physvols}) + return str + + def getDevice(self, partitions): + """Return a device which can be solidified.""" + pvs = [] + for pv in self.physicalVolumes: + pvs.append(partitions.getRequestByID(pv).device) + dev = fsset.VolumeGroupDevice(self.volumeGroupName, pvs) + return dev + +class LogicalVolumeRequestSpec(RequestSpec): + """Request to represent logical volume devices.""" + + def __init__(self, fstype, format = None, mountpoint = None, + size = None, volgroup = None, lvname = None): + """Create a new VolumeGroupRequestSpec object. + + fstype is the fsset filesystem type. + format is whether or not the volume group should be created. + mountpoint is the mountpoint for the request. + size is the size of the request in MB. + volgroup is the request ID of the volume group. + lvname is the name of the logical volume. + """ + + RequestSpec.__init__(self, fstype = fstype, format = format, + mountpoint = mountpoint, size = size) + self.type = REQUEST_VG + + self.logicalVolumeName = lvname + self.volumeGroup = volgroup + + def __str__(self): + if self.fstype: + fsname = self.fstype.getName() + else: + fsname = "None" + + str = ("LV Request -- mountpoint: %(mount)s uniqueID: %(id)s\n" + " type: %(fstype)s format: %(format)s badblocks: %(bb)s\n" + " size: %(size)s lvname: %(lvname)s volgroup: %(vgid)s" % + {"mount": self.mountpoint, "id": self.uniqueID, + "fstype": fsname, "format": self.format, "bb": self.badblocks, + "lvname": self.logicalVolumeName, "vgid": self.volumeGroup, + "size": self.size}) + return str + + def getDevice(self, partitions): + """Return a device which can be solidified.""" + vg = partitions.getRequestByID(self.volumeGroup) + vgname = vg.volumeGroupName + dev = fsset.LogicalVolumeDevice(vgname, self.size, + self.logicalVolumeName) + return dev 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 + diff --git a/partitions.py b/partitions.py new file mode 100644 index 000000000..229d7a483 --- /dev/null +++ b/partitions.py @@ -0,0 +1,513 @@ +# +# partitions.py: partition object containing partitioning info +# +# Matt Wilson <msw@redhat.com> +# Jeremy Katz <katzj@redhat.com> +# Mike Fulbright <msf@redhat.com> +# Harald Hoyer <harald@redhat.de> +# +# Copyright 2002 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. +# +"""Overarching partition object.""" + +import parted +import iutil +import string +import os, sys + +from constants import * + +import fsset +import partedUtils +import partRequests + +class Partitions: + """Defines all of the partition requests and delete requests.""" + def __init__ (self, diskset = None): + """Initializes a Partitions object. + + Can pass in the diskset if it already exists. + """ + self.requests = [] + """A list of RequestSpec objects for all partitions.""" + + self.deletes = [] + """A list of DeleteSpec objects for partitions to be deleted.""" + + self.autoPartitionRequests = [] + """A list of RequestSpec objects for autopartitioning. + These are setup by the installclass and folded into self.requests + by auto partitioning.""" + + self.autoClearPartType = CLEARPART_TYPE_NONE + """What type of partitions should be cleared?""" + + self.autoClearPartDrives = None + """Drives to clear partitions on (note that None is equiv to all).""" + + self.nextUniqueID = 1 + """Internal counter. Don't touch unless you're smarter than me.""" + + self.reinitializeDisks = 0 + """Should the disk label be reset on all disks?""" + + self.zeroMbr = 0 + """Should the mbr be zero'd?""" + + # partition method to be used. not to be touched externally + 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) + + + def setFromDisk(self, diskset): + """Clear the delete list and set self.requests to reflect disk.""" + 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 = partRequests.PreexistingPartitionSpec(ptype, + size = size, + start = start, + end = end, + drive = drive, + format = format) + spec.device = fsset.PartedPartitionDevice(part).getDevice() + print spec.device, ptype + + # 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): + """Add a new request to the list.""" + if not request.uniqueID: + request.uniqueID = self.nextUniqueID + self.nextUniqueID = self.nextUniqueID + 1 + self.requests.append(request) + self.requests.sort() + + return request.uniqueID + + def addDelete (self, delete): + """Add a new DeleteSpec to the list.""" + self.deletes.append(delete) + self.deletes.sort() + + def removeRequest (self, request): + """Remove a request from the list.""" + self.requests.remove(request) + + def getRequestByMountPoint(self, mount): + """Find and return the request with the given mountpoint.""" + 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): + """Find and return the request with the given device name.""" + if device is None: + return None + + for request in self.requests: + if request.device == device: + return request + return None + + def getRequestByVolumeGroupName(self, volname): + """Find and return the request with the given volume group name.""" + 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): + """Find and return the request with the given logical volume name.""" + if lvname is None: + return None + for request in self.requests: + if (request.type == REQUEST_LV and + request.logicalVolumeName == lvname): + return request + return None + + def getRequestByID(self, id): + """Find and return the request with the given unique ID. + + Note that if id is a string, it will be converted to an int for you. + """ + 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): + """Find and return a list of all of the RAID requests.""" + retval = [] + for request in self.requests: + if request.type == REQUEST_RAID: + retval.append(request) + + return retval + + def isRaidMember(self, request): + """Return whether or not the request is being used in a RAID device.""" + 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 + + def getLVMLVForVG(self, vgrequest): + """Find and return a list of all of the LVs in the VG.""" + retval = [] + vgid = vgrequest.uniqueID + for request in self.requests: + if request.type == REQUEST_LV: + if request.volumeGroup == vgid: + retval.append(request) + + return retval + + def getLVMRequests(self): + """Return a dictionary of all of the LVM bits. + + The dictionary returned is of the form vgname: [ lvrequests ] + """ + retval = {} + for request in self.requests: + if request.type == REQUEST_VG: + retval[request.volumeGroupName] = self.getLVMLVForVG(request) + + return retval + + def getLVMVGRequests(self): + """Find and return a list of all of the volume groups.""" + retval = [] + for request in self.requests: + if request.type == REQUEST_VG: + retval.append(request) + + return retval + + def getLVMLVRequests(self): + """Find and return a list of all of the logical volumes.""" + retval = [] + for request in self.requests: + if request.type == REQUEST_LV: + retval.append(request) + + return retval + + def isLVMVolumeGroupMember(self, request): + """Return whether or not the request is being used in an LVM device.""" + volgroups = self.getLVMVGRequests() + if not volgroups: + return 0 + + # XXX is it nonsensical to check if this isn't a real partition? + + for volgroup in volgroups: + if volgroup.physicalVolumes: + if request.uniqueID in volgroup.physicalVolumes: + return 1 + + return 0 + + def getBootableRequest(self): + """Return the name of the current 'boot' mount point.""" + 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 + + def isBootable(self, request): + """Returns if the request should be considered a 'bootable' request. + + This basically means that it should be sorted to the beginning of + the drive to avoid cylinder problems in most cases. + """ + 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): + """Resort the requests into allocation order.""" + 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): + """Deep copy the object.""" + 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): + """Get the kickstart directive related to the clearpart being used.""" + 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): + """Write out the partitioning information in kickstart format.""" + 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": + # since we guarantee that uniqueIDs are ints now... + args.append("raid.%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))) + diff --git a/textw/partition_text.py b/textw/partition_text.py index 30e8c696a..e14d460a8 100644 --- a/textw/partition_text.py +++ b/textw/partition_text.py @@ -22,6 +22,7 @@ import parted from partitioning import * from partedUtils import * from partIntfHelpers import * +from partRequests import * from fsset import * from autopart import * from snack import * @@ -928,12 +929,12 @@ class PartitionWindow: self.screen.popWindow() def newCb(self): - request = PartitionSpec(fileSystemTypeGetDefault(), REQUEST_NEW, 1) + request = NewPartitionSpec(fileSystemTypeGetDefault(), 1) self.editPartitionRequest(request, isNew = 1) def makeraidCb(self): - request = PartitionSpec(fileSystemTypeGetDefault(), REQUEST_RAID, 1) + request = RaidRequestSpec(fileSystemTypeGetDefault()) self.editRaidRequest(request, isNew = 1) |