summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeremy Katz <katzj@redhat.com>2002-02-13 19:31:23 +0000
committerJeremy Katz <katzj@redhat.com>2002-02-13 19:31:23 +0000
commit76d7d2de6f08ca3dc889c1e460a6c0c2d0fd9a2a (patch)
treed69b340204c852ed2e7490f9d84bd5b0598de79f
parent3cc5e61f10ba9bbe6539539cecedfadb795199e0 (diff)
downloadanaconda-76d7d2de6f08ca3dc889c1e460a6c0c2d0fd9a2a.tar.gz
anaconda-76d7d2de6f08ca3dc889c1e460a6c0c2d0fd9a2a.tar.xz
anaconda-76d7d2de6f08ca3dc889c1e460a6c0c2d0fd9a2a.zip
even more fun... move Partitions object to partitions.py and adjust accordingly.
move the Request object into partRequests.py and actually make it a nicer object with subclasses for the various types.
-rw-r--r--autopart.py8
-rw-r--r--constants.py21
-rw-r--r--instdata.py4
-rw-r--r--iw/partition_gui.py27
-rw-r--r--kickstart.py6
-rw-r--r--partIntfHelpers.py23
-rw-r--r--partRequests.py425
-rw-r--r--partitioning.py662
-rw-r--r--partitions.py513
-rw-r--r--textw/partition_text.py5
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)