diff options
-rw-r--r-- | autopart.py | 7 | ||||
-rw-r--r-- | fsset.py | 194 | ||||
-rw-r--r-- | iw/keyboard_gui.py | 2 | ||||
-rw-r--r-- | iw/progress_gui.py | 2 | ||||
-rw-r--r-- | iw/upgrade_swap_gui.py | 11 | ||||
-rw-r--r-- | partitioning.py | 55 |
6 files changed, 188 insertions, 83 deletions
diff --git a/autopart.py b/autopart.py index 471801556..00e254143 100644 --- a/autopart.py +++ b/autopart.py @@ -159,7 +159,6 @@ def fitSized(diskset, requests): ret = bestPartType(disk) if ret == PARTITION_FAIL: return ret - print ret if ret == parted.PARTITION_PRIMARY: partType = parted.PARTITION_PRIMARY elif ret == parted.PARTITION_EXTENDED: @@ -291,7 +290,11 @@ def processPartitioning(diskset, requests): for request in requests.requests: if request.type == REQUEST_NEW: request.device = None -# request.requestSize = request.size + + # set the unique identifier for raid devices + if request.type == REQUEST_RAID and not request.device: + request.device = requests.maxcontainer + requests.maxcontainer = requests.maxcontainer + 1 # XXX - handle delete requests for delete in requests.deletes: @@ -21,11 +21,14 @@ import parted from log import log from translate import _, N_ import partitioning +import sys defaultMountPoints = ('/', '/boot', '/home', '/tmp', '/usr', '/var') fileSystemTypes = {} +availRaidLevels = ['RAID-0', 'RAID-1', 'RAID-5'] + def fileSystemTypeGetDefault(): return fileSystemTypeGet('ext2') @@ -87,8 +90,18 @@ class FileSystemType: self.name = "" self.linuxnativefs = 0 self.partedFileSystemType = None - self.partedPartitonFlags = [] + self.partedPartitionFlags = [] + def mount(self, device, mountpoint, readOnly=0): + if not self.isMountable(): + return + iutil.mkdirChain(mountpoint) + isys.mount(device, mountpoint, fstype = self.getName(), + readOnly = readOnly) + + def umount(self, path): + isys.umount(path, removeDir = 0) + def getName(self): return self.name @@ -169,6 +182,37 @@ class ext2FileSystem(FileSystemType): fileSystemTypeRegister(ext2FileSystem()) +class ext3FileSystem(FileSystemType): + def __init__(self): + FileSystemType.__init__(self) + self.partedFileSystemType = parted.file_system_type_get("ext2") + self.formattable = 1 + self.checked = 1 + self.linuxnativefs = 1 + self.name = "ext3" + + def formatDevice(self, entry, progress, message, chroot='/'): + devicePath = entry.device.setupDevice(chroot) + devArgs = self.getDeviceArgs(entry.device) + label = labelFactory.createLabel(entry.mountpoint) + entry.setLabel(label) + args = [ "/usr/sbin/mke2fs", devicePath, '-j', '-L', label ] + args.extend(devArgs) + + rc = ext2FormatFilesystem(args, "/dev/tty5", + progress, + entry.mountpoint) + if rc: + message and message(_("Error"), + _("An error occured trying to format %s. " + "This problem is serious, and the install " + "cannot continue.\n\n" + "Press Enter to reboot your " + "system.") % (entry.device.getDevice(),)) + raise SystemError + +fileSystemTypeRegister(ext3FileSystem()) + class raidMemberDummyFileSystem(FileSystemType): def __init__(self): FileSystemType.__init__(self) @@ -186,12 +230,21 @@ class raidMemberDummyFileSystem(FileSystemType): fileSystemTypeRegister(raidMemberDummyFileSystem()) class swapFileSystem(FileSystemType): + enabledSwaps = {} + def __init__(self): FileSystemType.__init__(self) self.partedFileSystemType = parted.file_system_type_get("linux-swap") self.formattable = 1 self.name = "swap" + def mount(self, device, mountpoint): + isys.swapon (device) + + def umount(self, device, path): + # unfortunately, turning off swap is bad. + pass + def formatDevice(self, entry, progress, message, chroot='/'): file = entry.device.setupDevice(chroot) rc = iutil.execWithRedirect ("/usr/sbin/mkswap", @@ -325,7 +378,7 @@ class FileSystemSet: if bootDev.getName() == "LoopbackDevice": return None elif bootDev.getName() == "RAIDDevice": - return [ bootDev.device, "RAID Device" ] + return [ ( bootDev.device, "RAID Device" ) ] return [ (diskSet.driveList()[0], N_("Master Boot Record (MBR)") ), (bootDev.device, N_("First sector of boot partition")) @@ -333,24 +386,20 @@ class FileSystemSet: def formatSwap (self, chroot): for entry in self.entries: - if entry.mountpoint and entry.fsystem.getName() == "swap": + if (entry.fsystem and entry.fsystem.getName() == "swap" + and entry.getFormat()): entry.fsystem.formatDevice(entry, self.progressWindow, self.messageWindow, chroot) def turnOnSwap (self, chroot): for entry in self.entries: - if entry.mountpoint and entry.fsystem.getName() == "swap": - if not entry.isMounted(): - file = entry.device.setupDevice(chroot) - isys.swapon (file) - entry.setMounted(1) + if entry.fsystem and entry.fsystem.getName() == "swap": + entry.mount(chroot) def turnOffSwap(self, devices = 1, files = 0): for entry in self.entries: - if entry.mountpoint and entry.fsystem.getName() == "swap": - if entry.isMounted(): - isys.swapoff(n) - entry.setMounted(0) + if entry.fsystem and entry.fsystem.getName() == "swap": + entry.umount(chroot) def formattablePartitions(self): list = [] @@ -361,10 +410,9 @@ class FileSystemSet: def makeFilesystems (self, chroot='/'): for entry in self.entries: - if (not entry.format or entry.isMounted() - or not entry.fsystem.isFormattable()): + if (not entry.fsystem.isFormattable() or not entry.getFormat() + or entry.isMounted()): continue - entry.fsystem.formatDevice(entry, self.progressWindow, self.messageWindow, chroot) @@ -372,27 +420,20 @@ class FileSystemSet: for entry in self.entries: if not entry.fsystem.isMountable(): continue - elif (entry.fsystem.isFormattable() - or (entry.fsystem.getName() == "vfat" - and entry.mountpoint == "/boot/efi")): - try: - iutil.mkdirChain(instPath + entry.mountpoint) - isys.mount(entry.device.getDevice(), - instPath + entry.mountpoint, - fstype = entry.fsystem.getName(), - readOnly = readOnly) - entry.setMounted(1) - except SystemError, (errno, msg): - if raiseErrors: - raise SystemError, (errno, msg) - self.messageWindow and self.messageWindow(_("Error"), - _("Error mounting device %s as %s: %s\n\n" - "This most likely means this partition has " - "not been formatted.\n\nPress OK to reboot your " - "system.") % (entry.device.getDevice(), - entry.mountpoint, msg)) - sys.exit(0) - + try: + entry.mount(instPath) + except SystemError, (errno, msg): + if raiseErrors: + raise SystemError, (errno, msg) + self.messageWindow and self.messageWindow(_("Error"), + _("Error mounting device %s as %s: %s\n\n" + "This most likely means this partition has " + "not been formatted.\n\nPress OK to reboot your " + "system.") % (entry.device.getDevice(), + entry.mountpoint, msg)) + sys.exit(0) + + # XXX remove special case... try: os.mkdir (instPath + '/proc') except: @@ -401,6 +442,7 @@ class FileSystemSet: isys.mount('/proc', instPath + '/proc', 'proc') def umountFilesystems(self, instPath, ignoreErrors = 0): + # XXX remove special case try: isys.umount(instPath + '/proc/bus/usb', removeDir = 0) log("Umount USB OK") @@ -412,9 +454,7 @@ class FileSystemSet: reverse.reverse() for entry in reverse: - if entry.isMounted(): - isys.umount(instPath + entry.mountpoint, removeDir = 0) - entry.setMounted(0) + entry.umount(instPath) class FileSystemSetEntry: def __init__ (self, device, mountpoint, @@ -426,7 +466,7 @@ class FileSystemSetEntry: self.mountpoint = mountpoint self.fsystem = fsystem self.options = options - self.mounted = 0 + self.mountcount = 0 self.label = None if fsck == -1: self.fsck = fsystem.isChecked() @@ -444,6 +484,17 @@ class FileSystemSetEntry: if format and not fsystem.isFormattable(): raise RuntimeError, "file system type %s is not formattable, but has been added to fsset with format flag on" % fsystem.getName() self.format = format + + def mount(self, chroot='/', devPrefix='/tmp'): + device = self.device.setupDevice(chroot, devPrefix=devPrefix) + self.fsystem.mount(device, "%s/%s" % (chroot, self.mountpoint)) + self.mountcount = self.mountcount + 1 + + def umount(self, chroot='/'): + if self.mountcount > 0: + self.fssytem.umount(self.device, "%s/%s" % (chroot, + self.mountpoint)) + self.mountcount = self.mountcount - 1 def setFormat (self, state): self.format = state @@ -452,10 +503,7 @@ class FileSystemSetEntry: return self.format def isMounted (self): - return self.mounted - - def setMounted (self, state): - self.isMounted = state + return self.mountcount > 0 def getLabel (self): return self.label @@ -468,6 +516,7 @@ class Device: self.device = "none" self.fsoptions = {} self.label = None + self.isSetup = 0 def __repr__(self): return self.device @@ -478,7 +527,7 @@ class Device: def getDevice (self): return self.device - def setupDevice (self, chroot='/tmp'): + def setupDevice (self, chroot='/', devPrefix='/tmp'): pass def cleanupDevice (self, chroot, devPrefix='/tmp'): @@ -491,16 +540,17 @@ class Device: return self.__class__.__name__ class RAIDDevice(Device): - usedMajors = [] + usedMajors = {} # members is a list of Device based instances that will be # a part of this raid device - def __init__(self, level, members, minor=-1, spares=0): + def __init__(self, level, members, minor=-1, spares=0, existing=0): Device.__init__(self) self.level = level self.members = members self.spares = spares self.numDisks = len(members) - spares + self.isSetup = existing if len(members) < spares: raise RuntimeError, "you requiested more spare devices than online devices!" @@ -512,12 +562,12 @@ class RAIDDevice(Device): # there are 32 major md devices, 0...31 if minor == -1: for I in range(32): - if not I in RAIDDevice.usedMajors: + if not RAIDDevice.usedMajors.has_key(I): minor = I break raise RuntimeError, "Unable to allocate minor number for raid device" minor = I - RAIDDevice.usedMajors.append(minor) + RAIDDevice.usedMajors[minor] = None self.device = "md" + str(minor) self.minor = minor @@ -538,27 +588,37 @@ class RAIDDevice(Device): entry = entry + "nr-raid-disks %d\n" % (self.numDisks,) entry = entry + "chunk-size 64k\n" entry = entry + "persistent-superblock 1\n" - entry = entry + "#nr-spare-disks %d\n" % (self.spares,) + entry = entry + "nr-spare-disks %d\n" % (self.spares,) i = 0 - for device in self.members: + for device in self.members[:self.numDisks]: entry = entry + " device %s/%s\n" % (devPrefix, device.getDevice()) entry = entry + " raid-disk %d\n" % (i,) i = i + 1 + i = 0 + for device in self.members[self.numDisks:]: + entry = entry + " device %s/%s\n" % (devPrefix, + device.getDevice()) + entry = entry + " spare-disk %d\n" % (i,) + i = i + 1 return entry def setupDevice (self, chroot, devPrefix='/tmp'): - raidtab = '/tmp/raidtab.%s' % (self.device,) - f = open(raidtab, 'w') - f.write(self.raidTab('/tmp')) - for device in self.members: - device.setupDevice() node = "%s/%s" % (devPrefix, self.device) - isys.makeDevInode(self.device, node, devPrefix=devPrefix) - iutil.execWithRedirect ("/usr/sbin/mkraid", - [ 'mkraid', '--really-force', '--configfile', - raidtab, node ], - stderr = "/dev/tty5", stdout = "/dev/tty5") + isys.makeDevInode(self.device, node) + + if not self.isSetup: + raidtab = '/tmp/raidtab.%s' % (self.device,) + f = open(raidtab, 'w') + f.write(self.raidTab('/tmp')) + f.close() + for device in self.members: + device.setupDevice(chroot, devPrefix=devPrefix) + iutil.execWithRedirect ("/usr/sbin/mkraid", + ( 'mkraid', '--really-force', + '--configfile', raidtab, node ), + stderr = "/dev/tty5", stdout = "/dev/tty5") + self.isSetup = 1 return node def solidify(self): @@ -582,11 +642,10 @@ class PartitionDevice(Device): isys.makeDevInode(self.getDevice(), path) return path -class PartedPartitionDevice(Device): +class PartedPartitionDevice(PartitionDevice): def __init__(self, partition): - Device.__init__(self) + PartitionDevice.__init__(self, None) self.partition = partition - self.device = None def getDevice(self): if not self.partition: @@ -599,12 +658,9 @@ class PartedPartitionDevice(Device): return "%s%d" % (self.partition.geom.disk.dev.path[5:], self.partition.num) - def setupDevice(self, chroot, devPrefix='/tmp'): - path = '%d/%s' % (self.getDevice(), devPrefix) - isys.makeDevInode(self.getDevice(), path) - return path - def solidify(self): + # drop reference on the parted partition object and note + # the current minor number allocation self.device = self.getDevice() self.partition = None diff --git a/iw/keyboard_gui.py b/iw/keyboard_gui.py index 92b26c538..66946851d 100644 --- a/iw/keyboard_gui.py +++ b/iw/keyboard_gui.py @@ -146,7 +146,7 @@ class KeyboardWindow (InstallWindow): # self.variantList.append (("None",)) # for (key, variant) in self.rules[2].items (): count = 0 - for (key, variant) in (("basic", (_("Enable dead keys"))), + for (key, variant) in (("", (_("Enable dead keys"))), ("nodeadkeys", (_("Disable dead keys")))): loc = self.variantList.append ((variant,)) self.variantList.set_row_data (loc, key) diff --git a/iw/progress_gui.py b/iw/progress_gui.py index 5dfbeb1c0..de3e9b99e 100644 --- a/iw/progress_gui.py +++ b/iw/progress_gui.py @@ -79,6 +79,8 @@ class InstallProgressWindow (InstallWindow): self.totalProgress.update (float (self.sizeComplete) / self.totalSize) return + self.timeCompleteW.setText("%12s" % formatTime(elapsedTime)) + self.timeTotalW.setText("%12s" % formatTime(finishTime)) def setPackage(self, header): if len(self.pixmaps): diff --git a/iw/upgrade_swap_gui.py b/iw/upgrade_swap_gui.py index 7f7361037..c5a85d168 100644 --- a/iw/upgrade_swap_gui.py +++ b/iw/upgrade_swap_gui.py @@ -104,6 +104,7 @@ class UpgradeSwapWindow (InstallWindow): self.swapbox = GtkVBox(FALSE, 5) box.pack_start(self.swapbox, FALSE) + label = GtkLabel (_("Select the partition to put the swap file on:")) a = GtkAlignment(0.2, 0.5) a.add(label) @@ -111,16 +112,9 @@ class UpgradeSwapWindow (InstallWindow): titles = [(_("Mount Point")), (_("Partition")), (_("Free Space (MB)"))] self.clist = GtkCList(3, titles) - self.clist.set_usize(300, 100) self.clist.connect("select-row", self.clist_cb) - - sw = GtkScrolledWindow() - sw.set_policy (POLICY_AUTOMATIC, POLICY_AUTOMATIC) - sw.add(self.clist) - a = GtkAlignment(0.5, 0.5) - a.add(sw) - + a.add(self.clist) self.swapbox.pack_start(a, FALSE, TRUE, 10) count = 0 @@ -131,7 +125,6 @@ class UpgradeSwapWindow (InstallWindow): self.clist.select_row(0, 0) - label = GtkLabel (_("It is recommended that your swap file be at least %d MB. Please enter a size for the swap file:") % suggSize) label.set_usize(400, 40) label.set_line_wrap (TRUE) diff --git a/partitioning.py b/partitioning.py index 57809719f..6bad67c24 100644 --- a/partitioning.py +++ b/partitioning.py @@ -109,7 +109,7 @@ def get_primary_partitions(disk): return rc - +# returns a list of partitions which can make up RAID devices def get_raid_partitions(disk): rc = [] part = disk.next_partition() @@ -124,7 +124,54 @@ def get_raid_partitions(disk): part = disk.next_partition(part) return rc - + + +# returns a list of the actual raid device requests +def get_raid_devices(requests): + raidRequests = [] + for request in requests: + if request.type == REQUEST_RAID: + raidRequests.append(request) + + return raidRequests + + +# returns a list of raid partitions which haven't been used in a device yet +def get_available_raid_partitions(diskset, requests): + rc = [] + drives = diskset.disks.keys() + raiddevs = get_raid_devices(requests) + drives.sort() + for drive in drives: + disk = diskset.disks[drive] + for part in get_raid_partitions(disk): + for raid in raiddevs: + if raid.raidmembers and part in raid.raidmembers: + break + rc.append(part) + return rc + +# return minimum numer of raid members required for a raid level +def get_raid_min_members(raidlevel): + if raidlevel == "RAID-0": + return 2 + elif raidlevel == "RAID-1": + return 2 + elif raidlevel == "RAID-5": + return 3 + else: + raise ValueError, "invalid raidlevel in get_raid_min_members" + +# return max num of spares available for raidlevel and total num of members +def get_raid_max_spares(raidlevel, nummembers): + if raidlevel == "RAID-0": + return 0 + elif raidlevel == "RAID-1": + return 0 + elif raidlevel == "RAID-5": + return max(0, nummembers - get_raid_min_members(raidlevel)) + else: + raise ValueError, "invalid raidlevel in get_raid_max_spares" # returns error string if something not right about request # returns error string if something not right about request @@ -271,6 +318,10 @@ class PartitionRequests: if diskset: self.setFromDisk(diskset) + # identifier used for raid partitions + self.maxcontainer = 0 + + def setFromDisk(self, diskset): self.deletes = [] diskset.refreshDevices() |