Okay, newer patch implementing resizing. Still against an older tree (726a485e58706b70c8fb2b9d4febe938a7c88963) but just to get it out there while I work on the fun of rebasing to the current code and merging with dlehman's encryption bits. The patch implements the following: 1) Adds "pulsing progress bars" for GUI where you have the progress bar bounce due to something taking an indeterminate amount of time. We should also be able to use this for other filesystem creation options that we don't know how long they take. For text mode, this just gives a message and no progress bar 2) Moves writing out partitioning and mounting filesystems to be right after the partitioning screen. Note: this still needs something to let the user know that their changes are going to be done immediately 3) Adds support for resizing partitions in the autopart loop. This requires the pyparted patch which I sent last time 4) Determines the maximum size a partition can be grown to 5) Adds support for resizing ext[23] filesystems and determining the minimum size of the ext[23] filesystem 6) Cleans up the graphical UI when editing a pre-existing partition and adds support for resize. Contrast http://katzj.fedorapeople.org/resize-poc.png to http://katzj.fedorapeople.org/new-edit-part-dialog.png At this point, I'm pretty happy with how things are looking and am probably going to go ahead and commit once I get things rebased unless anyone has any strong concerns. There are still some more things which can be done, but they can be easily done as small follow-up patches. Jeremy
diff --git a/autopart.py b/autopart.py index 8886241..9036224 100644 --- a/autopart.py +++ b/autopart.py @@ -865,6 +865,23 @@ def setPreexistParts(diskset, requests): part = disk.next_partition() while part: if part.geom.start == request.start and part.geom.end == request.end: + # if the partition is being resized, we do that now + if request.targetSize is not None: + startSec = part.geom.start + endSec = part.geom.start + long(((request.targetSize * 1024L * 1024L) / disk.dev.sector_size)) - 1 + + try: + g = part.geom.duplicate() + g.set_end(endSec) + constraint = g.constraint_exact() + part.set_geometry(constraint, startSec, endSec) + except parted.error, msg: + log.error("error setting geometry for partition %s: %s" %(partedUtils.get_partition_name(part), msg)) + raise PartitioningError, _("Error resizing partition %s.\n\n%s") %(partedUtils.get_partition_name(part), msg) + + if startSec != part.geom.start: + raise PartitioningError, _("Start of partition %s was moved when resizing") %(partedUtils.get_partition_name(part),) + request.device = partedUtils.get_partition_name(part) if request.fstype: if request.fstype.getName() != request.origfstype.getName(): @@ -987,13 +1004,18 @@ def processPartitioning(diskset, requests, newParts): for request in requests.requests: if request.type == REQUEST_RAID: request.size = request.getActualSize(requests, diskset) - if request.type == REQUEST_VG: + elif request.type == REQUEST_VG: request.size = request.getActualSize(requests, diskset) - if request.type == REQUEST_LV: + elif request.type == REQUEST_LV: if request.grow: request.setSize(request.getStartSize()) else: request.size = request.getActualSize(requests, diskset) + elif request.preexist: + # we need to keep track of the max size of preexisting partitions + # FIXME: we should also get the max size for LVs at some point + part = partedUtils.get_partition_by_name(diskset.disks, request.device) + request.maxSize = partedUtils.getMaxAvailPartSizeMB(part) ## print "disk layout after everything is done" ## print diskset.diskState() diff --git a/cmdline.py b/cmdline.py index c343eb9..972ce9c 100644 --- a/cmdline.py +++ b/cmdline.py @@ -38,6 +38,9 @@ class ProgressWindow: def pop(self): print "" + def pulse(self): + pass + def set(self, amount): if amount == self.total: print _("Completed"), @@ -45,7 +48,7 @@ class ProgressWindow: def refresh(self): pass - def __init__(self, title, text, total, updpct = 0.05): + def __init__(self, title, text, total, updpct = 0.05, pulse = False): self.total = total print text print _("In progress... "), @@ -61,8 +64,8 @@ class InstallInterface: def shutdown(self): pass - def progressWindow(self, title, text, total, updpct = 0.05): - return ProgressWindow(title, text, total, updpct) + def progressWindow(self, title, text, total, updpct = 0.05, pulse = False): + return ProgressWindow(title, text, total, updpct, pulse) def kickstartErrorWindow(self, text): s = _("The following error was found while parsing your " diff --git a/dispatch.py b/dispatch.py index 5775108..8d36483 100644 --- a/dispatch.py +++ b/dispatch.py @@ -78,8 +78,10 @@ installSteps = [ ("upgradeswapsuggestion", upgradeSwapSuggestion, ), ("addswap", ), ("partitiondone", partitioningComplete, ), + ("enablefilesystems", turnOnFilesystems, ), ("upgrademigfind", upgradeMigrateFind, ), ("upgrademigratefs", ), + ("migratefilesystems", doMigrateFilesystems, ), ("upgbootloader", ), ("bootloadersetup", bootloaderSetupChoices, ), ("bootloader", ), @@ -96,8 +98,6 @@ installSteps = [ ("confirminstall", ), ("confirmupgrade", ), ("install", ), - ("enablefilesystems", turnOnFilesystems, ), - ("migratefilesystems", doMigrateFilesystems, ), ("setuptime", setupTimezone, ), ("preinstallconfig", doPreInstall, ), ("installpackages", doInstall, ), diff --git a/fsset.py b/fsset.py index 61ba6a0..9141411 100644 --- a/fsset.py +++ b/fsset.py @@ -2,6 +2,7 @@ # fsset.py: filesystem management # # Matt Wilson <msw@xxxxxxxxxx> +# Jeremy Katz <katzj@xxxxxxxxxx> # # Copyright 2001-2007 Red Hat, Inc. # @@ -13,6 +14,7 @@ # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # +import math import string import isys import iutil @@ -177,10 +179,18 @@ class FileSystemType: self.extraFormatArgs = [] self.maxLabelChars = 16 self.packages = [] + self.resizable = False self.supportsFsProfiles = False self.fsProfileSpecifier = None self.fsprofile = None + def isResizable(self): + return self.resizable + def resize(self, entry, size, progress, chroot='/'): + pass + def getMinimumSize(self, device): + pass + def isKernelFS(self): """Returns True if this is an in-kernel pseudo-filesystem.""" return False @@ -505,6 +515,81 @@ class extFileSystem(FileSystemType): self.packages = [ "e2fsprogs" ] self.supportsFsProfiles = True self.fsProfileSpecifier = "-T" + self.resizable = True + + def resize(self, entry, size, progress, chroot='/'): + devicePath = entry.device.setupDevice(chroot) + + log.info("checking %s prior to resize" %(devicePath,)) + w = None + if progress: + w = progress(_("Checking"), + _("Checking filesystem on %s...") %(devicePath), + 100, pulse = True) + + rc = iutil.execWithPulseProgress("e2fsck", ["-f", "-p", "-C", "0", devicePath], + stdout="/dev/tty5", + stderr="/dev/tty5", progress = w) + if rc >= 4: + raise RuntimeError, "Check of %s failed" %(devicePath,) + if progress: + w.pop() + w = progress(_("Resizing"), + _("Resizing filesystem on %s...") %(devicePath), + 100, pulse = True) + + log.info("resizing %s" %(devicePath,)) + rc = iutil.execWithPulseProgress("resize2fs", + ["-p", devicePath, "%sM" %(size,)], + stdout="/dev/tty5", stderr="/dev/tty5", + progress = w) + if progress: + w.pop() + if rc: + raise RuntimeError, "Resize of %s failed" %(devicePath,) + + def getMinimumSize(self, device): + """Return the minimum filesystem size in megabytes""" + devicePath = "/dev/%s" % (device,) + if not os.path.exists(devicePath): + isys.makeDevInode(device, devicePath) + + # FIXME: it'd be nice if we didn't have to parse this out ourselves + buf = iutil.execWithCapture("/tmp/updates/dumpe2fs", + ["-h", devicePath], + stderr = "/dev/tty5") + blocks = free = bs = 0 + for l in buf.split("\n"): + if l.startswith("Free blocks"): + try: + free = l.split()[2] + free = int(free) + except Exception, e: + log.warning("error determining free blocks on %s: %s" %(devicePath, e)) + free = 0 + elif l.startswith("Block size"): + try: + bs = l.split()[2] + bs = int(bs) + except Exception, e: + log.warning("error determining block size of %s: %s" %(devicePath, e)) + bs = 0 + elif l.startswith("Block count"): + try: + blocks = l.split()[2] + blocks = int(blocks) + except Exception, e: + log.warning("error determining block count of %s: %s" %(devicePath, e)) + blocks = 0 + + if free == 0 or bs == 0: + log.warning("Unable to determinine minimal size for %s", devicePath) + return 1 + + used = math.ceil((blocks - free) * bs / 1024.0 / 1024.0) + log.info("used size of %s is %s" %(devicePath, used)) + # FIXME: should we bump this beyond the absolute minimum? + return used def labelDevice(self, entry, chroot): devicePath = entry.device.setupDevice(chroot) @@ -1376,6 +1461,24 @@ MAILADDR root if bootPart: del bootPart + def resizeFilesystems (self, chroot = '/', shrink = False, grow = False): + for entry in self.entries: + if not entry.fsystem or not entry.fsystem.isResizable(): + continue + if entry.resizeTargetSize is None: + continue + if shrink and not (entry.resizeTargetSize < entry.resizeOrigSize): + continue + if grow and not (entry.resizeTargetSize > entry.resizeOrigSize): + continue + entry.fsystem.resize(entry, entry.resizeTargetSize, + self.progressWindow, chroot) + + def shrinkFilesystems (self, chroot): + self.resizeFilesystems(chroot, shrink = True) + def growFilesystems (self, chroot): + self.resizeFilesystems(chroot, grow = True) + def formatSwap (self, chroot, forceFormat=False): formatted = [] notformatted = [] @@ -1826,6 +1929,8 @@ class FileSystemSetEntry: self.fsystem = fsystem self.origfsystem = origfsystem self.migrate = migrate + self.resizeTargetSize = None + self.resizeOrigSize = None self.options = options self.mountcount = 0 self.label = None @@ -1907,6 +2012,15 @@ class FileSystemSetEntry: def getMigrate (self): return self.migrate + def setResizeTarget (self, targetsize, size): + if not self.fsystem.isResizable() and targetsize is not None: + raise ValueError, "Can't set a resize target for a non-resizable filesystem" + self.resizeTargetSize = targetsize + self.resizeOrigSize = size + + def getResizeTarget (self): + return self.targetsize + def isMounted (self): return self.mountcount > 0 diff --git a/gui.py b/gui.py index b8ebb63..686ba76 100755 --- a/gui.py +++ b/gui.py @@ -511,7 +511,7 @@ class WaitWindow: class ProgressWindow: def __init__(self, title, text, total, updpct = 0.05, updsecs=10, - parent = None): + parent = None, pulse = False): if flags.rootpath or not runningMiniWm(): self.window = gtk.Window() if parent: @@ -543,6 +543,11 @@ class ProgressWindow: def refresh(self): processEvents() + def pulse(self): + self.progress.set_pulse_step(self.updpct) + self.progress.pulse() + processEvents() + def set (self, amount): # only update widget if we've changed by 5% or our timeout has # expired @@ -940,11 +945,12 @@ class InstallInterface: else: return WaitWindow (title, text) - def progressWindow (self, title, text, total, updpct = 0.05): + def progressWindow (self, title, text, total, updpct = 0.05, pulse = False): if self.icw: - return ProgressWindow (title, text, total, updpct, self.icw.window) + return ProgressWindow (title, text, total, updpct, + parent = self.icw.window, pulse = pulse) else: - return ProgressWindow (title, text, total, updpct) + return ProgressWindow (title, text, total, updpct, pulse = pulse) def packageProgressWindow (self, total, totalSize): self.ppw.setSizes (total, totalSize) diff --git a/iutil.py b/iutil.py index 926b0c6..f617487 100644 --- a/iutil.py +++ b/iutil.py @@ -96,6 +96,66 @@ def execWithCapture(command, argv, stdin = 0, stderr = 2, root='/'): pipe.wait() return rc +def execWithPulseProgress(command, argv, stdin = 0, stdout = 1, stderr = 2, + progress = None, root = '/'): + def chroot(): + os.chroot(root) + + argv = list(argv) + if type(stdin) == type("string"): + if os.access(stdin, os.R_OK): + stdin = open(stdin) + else: + stdin = 0 + if type(stdout) == type("string"): + stdout = open(stdout, "w") + if type(stderr) == type("string"): + stderr = open(stderr, "w") + + p = os.pipe() + childpid = os.fork() + if not childpid: + os.close(p[0]) + os.dup2(p[1], 1) + os.dup2(stderr.fileno(), 2) + os.close(p[1]) + stderr.close() + + os.execvp(command, [command] + argv) + os._exit(1) + + os.close(p[1]) + + while 1: + try: + s = os.read(p[0], 1) + except OSError, args: + (num, str) = args + if (num != 4): + raise IOError, args + + stdout.write(s) + if progress: progress.pulse() + + if len(s) < 1: + break + + try: + (pid, status) = os.waitpid(childpid, 0) + except OSError, (num, msg): + log.critical("exception from waitpid: %s %s" %(num, msg)) + + progress and progress.pop() + + # *shrug* no clue why this would happen, but hope that things are fine + if status is None: + return 0 + + if os.WIFEXITED(status): + return os.WEXITSTATUS(status) + + return 1 + ## Run a shell. def execConsole(): try: diff --git a/iw/lvm_dialog_gui.py b/iw/lvm_dialog_gui.py index ae9c614..5368598 100644 --- a/iw/lvm_dialog_gui.py +++ b/iw/lvm_dialog_gui.py @@ -479,25 +479,15 @@ class VolumeGroupEditor: format = 1 migrate = 0 else: - if self.fsoptionsDict.has_key("formatrb"): - formatrb = self.fsoptionsDict["formatrb"] - else: - formatrb = None - - if formatrb: - format = formatrb.get_active() + if self.fsoptionsDict.has_key("formatcb"): + format = self.fsoptionsDict["formatcb"].get_active() if format: fsystem = self.fsoptionsDict["fstypeCombo"].get_active_value() else: format = 0 - if self.fsoptionsDict.has_key("migraterb"): - migraterb = self.fsoptionsDict["migraterb"] - else: - migraterb = None - - if migraterb: - migrate = migraterb.get_active() + if self.fsoptionsDict.has_key("migratecb"): + migrate = self.fsoptionsDict["migratecb"].get_active() if migrate: fsystem = self.fsoptionsDict["migfstypeCombo"].get_active_value() else: diff --git a/iw/partition_dialog_gui.py b/iw/partition_dialog_gui.py index 042be17..69849c3 100644 --- a/iw/partition_dialog_gui.py +++ b/iw/partition_dialog_gui.py @@ -190,30 +190,26 @@ class PartitionEditor: # preexisting partition, just set mount point and format flag request = copy.copy(self.origrequest) - if self.fsoptionsDict.has_key("formatrb"): - formatrb = self.fsoptionsDict["formatrb"] - else: - formatrb = None - - if formatrb: - request.format = formatrb.get_active() + if self.fsoptionsDict.has_key("formatcb"): + request.format = self.fsoptionsDict["formatcb"].get_active() if request.format: request.fstype = self.fsoptionsDict["fstypeCombo"].get_active_value() else: request.format = 0 - if self.fsoptionsDict.has_key("migraterb"): - migraterb = self.fsoptionsDict["migraterb"] - else: - migraterb = None - - if migraterb: - request.migrate = migraterb.get_active() + if self.fsoptionsDict.has_key("migratecb"): + request.migrate = self.fsoptionsDict["migratecb"].get_active() if request.migrate: request.fstype =self.fsoptionsDict["migfstypeCombo"].get_active_value() else: request.migrate = 0 + if self.fsoptionsDict.has_key("resizecb") and self.fsoptionsDict["resizecb"].get_active(): + request.targetSize = self.fsoptionsDict["resizesb"].get_value_as_int() + else: + request.targetSize = None + print "the target size for %s is %s" %(request.mountpoint, request.targetSize) + # set back if we are not formatting or migrating origfstype = self.origrequest.origfstype if not request.format and not request.migrate: @@ -299,21 +295,6 @@ class PartitionEditor: lbl.set_mnemonic_widget(self.newfstypeCombo) maintable.attach(self.newfstypeCombo, 1, 2, row, row + 1) else: - maintable.attach(createAlignedLabel(_("Original File System " - "Type:")), - 0, 1, row, row + 1) - - if self.origrequest.origfstype: - typestr = self.origrequest.origfstype.getName() - if self.origrequest.origfstype.getName() == "foreign": - part = get_partition_by_name(self.diskset.disks, - self.origrequest.device) - typestr = map_foreign_to_fsname(part.native_type) - else: - typestr = _("Unknown") - - fstypelabel = gtk.Label(typestr) - maintable.attach(fstypelabel, 1, 2, row, row + 1) self.newfstypeCombo = None row = row + 1 @@ -417,10 +398,6 @@ class PartitionEditor: cursize = (endsec - startsec)/2048 bycyl_sizelabel.set_text("%s" % (int(cursize))) else: - maintable.attach(createAlignedLabel(_("Size (MB):")), - 0, 1, row, row + 1) - sizelabel = gtk.Label("%d" % (origrequest.size)) - maintable.attach(sizelabel, 1, 2, row, row + 1) self.sizespin = None row = row + 1 diff --git a/iw/partition_ui_helpers_gui.py b/iw/partition_ui_helpers_gui.py index be66780..89a45d2 100644 --- a/iw/partition_ui_helpers_gui.py +++ b/iw/partition_ui_helpers_gui.py @@ -29,6 +29,11 @@ from partedUtils import * import rhpl from rhpl.translate import _, N_ +def istruefalse(val): + if val is None or not val: + return False + return True + class WideCheckList(checklist.CheckList): def toggled_item(self, data, row): @@ -206,6 +211,9 @@ def mountptchangeCB(widget, fstypecombo): if rhpl.getArch() == "ia64" and widget.get_children()[0].get_text() == "/boot/efi": fstypecombo.set_active_text("vfat") +def resizeOptionCB(widget, resizesb): + resizesb.set_sensitive(widget.get_active()) + def formatOptionCB(widget, data): (combowidget, mntptcombo, ofstype) = data combowidget.set_sensitive(widget.get_active()) @@ -232,87 +240,80 @@ def noformatCB(widget, data): Returns the value of row after packing into the maintable, and a dictionary consistenting of: - noformatrb - radiobutton for 'leave fs unchanged' - formatrb - radiobutton for 'format as new fs' + noformatcb - checkbutton for 'format as new fs' fstype - part of format fstype menu fstypeMenu - part of format fstype menu - migraterb - radiobutton for migrate fs - migfstype - menu for migrate fs types + migratecb - checkbutton for migrate fs migfstypeMenu - menu for migrate fs types + resizecb - checkbutton for 'resize fs' + resizesb - spinbutton with resize target """ def createPreExistFSOptionSection(origrequest, maintable, row, mountCombo, ignorefs=[]): + rc = {} ofstype = origrequest.fstype - maintable.attach(gtk.HSeparator(), 0, 2, row, row + 1) - row = row + 1 - - label = gtk.Label(_("How would you like to prepare the file system " - "on this partition?")) - label.set_line_wrap(1) - label.set_alignment(0.0, 0.0) + formatcb = gtk.CheckButton(label=_("_Format as:")) + maintable.attach(formatcb, 0, 1, row, row + 1) + formatcb.set_active(istruefalse(origrequest.format)) + rc["formatcb"] = formatcb - maintable.attach(label, 0, 2, row, row + 1) - row = row + 1 - - noformatrb = gtk.RadioButton(label=_("Leave _unchanged " - "(preserve data)")) - noformatrb.set_active(1) - maintable.attach(noformatrb, 0, 2, row, row + 1) - row = row + 1 - - formatrb = gtk.RadioButton(label=_("_Format partition as:"), - group=noformatrb) - formatrb.set_active(0) - if origrequest.format: - formatrb.set_active(1) - - maintable.attach(formatrb, 0, 1, row, row + 1) fstypeCombo = createFSTypeMenu(ofstype, fstypechangeCB, mountCombo, ignorefs=ignorefs) - fstypeCombo.set_sensitive(formatrb.get_active()) + fstypeCombo.set_sensitive(formatcb.get_active()) maintable.attach(fstypeCombo, 1, 2, row, row + 1) - row = row + 1 + row += 1 + rc["fstypeCombo"] = fstypeCombo - if not formatrb.get_active() and not origrequest.migrate: + if not formatcb.get_active() and not origrequest.migrate: mountCombo.set_data("prevmountable", ofstype.isMountable()) - formatrb.connect("toggled", formatOptionCB, - (fstypeCombo, mountCombo, ofstype)) + formatcb.connect("toggled", formatOptionCB, + (fstypeCombo, mountCombo, ofstype)) - noformatrb.connect("toggled", noformatCB, - (fstypeCombo, mountCombo, origrequest.origfstype)) if origrequest.origfstype.isMigratable(): - migraterb = gtk.RadioButton(label=_("Mi_grate partition to:"), - group=noformatrb) - migraterb.set_active(0) - if origrequest.migrate: - migraterb.set_active(1) + migratecb = gtk.CheckButton(label=_("Mi_grate filesystem to:")) + migratecb.set_active(istruefalse(origrequest.migrate)) migtypes = origrequest.origfstype.getMigratableFSTargets() - maintable.attach(migraterb, 0, 1, row, row + 1) + maintable.attach(migratecb, 0, 1, row, row + 1) migfstypeCombo = createFSTypeMenu(ofstype, None, None, availablefstypes = migtypes) - migfstypeCombo.set_sensitive(migraterb.get_active()) + migfstypeCombo.set_sensitive(migratecb.get_active()) maintable.attach(migfstypeCombo, 1, 2, row, row + 1) - row = row + 1 - - migraterb.connect("toggled", formatOptionCB, + row += 1 + migratecb.connect("toggled", formatOptionCB, (migfstypeCombo, mountCombo, ofstype)) - else: - migraterb = None - migfstypeCombo = None - - row = row + 1 - - rc = {} - for var in ['noformatrb', 'formatrb', 'fstypeCombo', - 'migraterb', 'migfstypeCombo']: - if eval("%s" % (var,)) is not None: - rc[var] = eval("%s" % (var,)) - + rc["migratecb"] = migratecb + rc["migfstypeCombo"] = migfstypeCombo + + # FIXME: we should support resizing LVs too + if origrequest.origfstype.isResizable() and origrequest.type == REQUEST_PREEXIST: + resizecb = gtk.CheckButton(label=_("_Resize partition")) + resizecb.set_active(origrequest.targetSize is not None) + rc["resizecb"] = resizecb + maintable.attach(resizecb, 0, 1, row, row + 1) + + if origrequest.targetSize is not None: + value = origrequest.targetSize + else: + value = origrequest.size + adj = gtk.Adjustment(value = value, + lower = origrequest.getMinimumResizeMB(), + upper = origrequest.getMaximumResizeMB(), + step_incr = 1) + resizesb = gtk.SpinButton(adj, digits = 0) + resizesb.set_property('numeric', True) + rc["resizesb"] = resizesb + maintable.attach(resizesb, 1, 2, row, row + 1) + + resizecb.connect('toggled', resizeOptionCB, resizesb) + resizeOptionCB(resizecb, resizesb) + + row += 1 + return (row, rc) # do tests we just want in UI for now, not kickstart diff --git a/iw/raid_dialog_gui.py b/iw/raid_dialog_gui.py index 69e1cf6..09de387 100644 --- a/iw/raid_dialog_gui.py +++ b/iw/raid_dialog_gui.py @@ -167,27 +167,17 @@ class RaidEditor: else: request.format = 0 else: - if self.fsoptionsDict.has_key("formatrb"): - formatrb = self.fsoptionsDict["formatrb"] - else: - formatrb = None - - if formatrb: - request.format = formatrb.get_active() + if self.fsoptionsDict.has_key("formatcb"): + request.format = self.fsoptionsDict["formatcb"].get_active() if request.format: - request.fstype = self.fsoptionsDict["fstypeCombo"].get_active_value() + request.fsystem = self.fsoptionsDict["fstypeCombo"].get_active_value() else: request.format = 0 - if self.fsoptionsDict.has_key("migraterb"): - migraterb = self.fsoptionsDict["migraterb"] - else: - migraterb = None - - if migraterb: - request.migrate = migraterb.get_active() + if self.fsoptionsDict.has_key("migratecb"): + request.migrate = self.fsoptionsDict["migratecb"].get_active() if request.migrate: - request.fstype =self.fsoptionsDict["migfstypeCombo"].get_active_value() + request.fsystem = self.fsoptionsDict["migfstypeCombo"].get_active_value() else: request.migrate = 0 diff --git a/packages.py b/packages.py index aeefde2..09f3685 100644 --- a/packages.py +++ b/packages.py @@ -148,8 +148,10 @@ def turnOnFilesystems(anaconda): searchPath = 1) anaconda.id.partitions.doMetaDeletes(anaconda.id.diskset) anaconda.id.fsset.setActive(anaconda.id.diskset) + anaconda.id.fsset.shrinkFilesystems(anaconda.rootPath) if not anaconda.id.fsset.isActive(): anaconda.id.diskset.savePartitions () + anaconda.id.fsset.growFilesystems(anaconda.rootPath) if not anaconda.id.fsset.volumesCreated: anaconda.id.fsset.createLogicalVolumes(anaconda.rootPath) anaconda.id.fsset.formatSwap(anaconda.rootPath) diff --git a/partRequests.py b/partRequests.py index 3fbb812..fbb5e13 100644 --- a/partRequests.py +++ b/partRequests.py @@ -152,6 +152,9 @@ class RequestSpec: self.dev = None """A Device() as defined in fsset.py to correspond to this request.""" + self.targetSize = None + """Size to resize to""" + def __str__(self): if self.fstype: fsname = self.fstype.getName() @@ -209,6 +212,9 @@ class RequestSpec: if self.fslabel: entry.setLabel(self.fslabel) + if self.targetSize and self.fstype.isResizable(): + entry.setResizeTarget(self.targetSize, self.size) + return entry def setProtected(self, val): @@ -558,6 +564,18 @@ class PreexistingPartitionSpec(PartitionSpec): mountpoint = mountpoint, preexist = 1) self.type = REQUEST_PREEXIST + self.maxResizeSize = None + """Maximum size of this partition request""" + + def getMaximumResizeMB(self): + if self.maxResizeSize is not None: + return self.maxResizeSize + log.warning("%s doesn't have a max size set" %(self.device,)) + return MAX_PART_SIZE + + def getMinimumResizeMB(self): + return self.fstype.getMinimumSize(self.device) + class RaidRequestSpec(RequestSpec): """Request to represent RAID devices.""" diff --git a/partedUtils.py b/partedUtils.py index 273f372..a4bac97 100644 --- a/partedUtils.py +++ b/partedUtils.py @@ -96,6 +96,24 @@ def getDeviceSizeMB(dev): return (float(dev.heads * dev.cylinders * dev.sectors) / (1024 * 1024) * dev.sector_size) +def getMaxAvailPartSizeMB(part): + """Return the maximum size this partition can grow to by looking + at contiguous freespace partitions.""" + + disk = part.disk + maxlen = part.geom.length + + # let's look at the next partition(s) and if they're freespace, + # they can add to our maximum size. + np = disk.next_partition(part) + while np: + if np.type & parted.PARTITION_FREESPACE: + maxlen += np.geom.length + else: + break + np = disk.next_partition(np) + return math.floor(maxlen * part.geom.dev.sector_size / 1024.0 / 1024.0) + def get_partition_by_name(disks, partname): """Return the parted part object associated with partname. diff --git a/partitions.py b/partitions.py index 101b3f9..2d3fda0 100644 --- a/partitions.py +++ b/partitions.py @@ -101,30 +101,6 @@ def partitioningComplete(anaconda): raise RuntimeError, ("Managed to not get an entry back from " "request.toEntry") - if (not flags.setupFilesystems - or iutil.memAvailable() > isys.EARLY_SWAP_RAM): - return - - if not anaconda.isKickstart: - rc = anaconda.intf.messageWindow(_("Low Memory"), - _("As you don't have much memory in this " - "machine, we need to turn on swap space " - "immediately. To do this we'll have to " - "write your new partition table to the disk " - "immediately. Is that OK?"), "yesno") - else: - rc = 1 - - if rc: - anaconda.id.partitions.doMetaDeletes(anaconda.id.diskset) - anaconda.id.fsset.setActive(anaconda.id.diskset) - anaconda.id.diskset.savePartitions () - anaconda.id.fsset.createLogicalVolumes(anaconda.rootPath) - anaconda.id.fsset.formatSwap(anaconda.rootPath) - anaconda.id.fsset.turnOnSwap(anaconda.rootPath) - - return - class Partitions: """Defines all of the partition requests and delete requests.""" @@ -217,6 +193,7 @@ class Partitions: drive = drive, format = format) spec.device = fsset.PartedPartitionDevice(part).getDevice() + spec.maxSize = partedUtils.getMaxAvailPartSizeMB(part) # set label if makes sense if ptype and ptype.isMountable() and \ @@ -225,6 +202,7 @@ class Partitions: if labels[spec.device] and len(labels[spec.device])>0: spec.fslabel = labels[spec.device] + print "added %s of size %s with max size of %s" %(spec.device, size, spec.maxSize) self.addRequest(spec) part = disk.next_partition(part) diff --git a/scripts/upd-instroot b/scripts/upd-instroot index 8312eb9..4d695df 100755 --- a/scripts/upd-instroot +++ b/scripts/upd-instroot @@ -416,6 +416,7 @@ sbin/busybox.anaconda sbin/clock sbin/debugfs sbin/dosfslabel +sbin/dumpe2fs sbin/e2fsck sbin/e2fsadm sbin/e2label diff --git a/text.py b/text.py index a5eefb5..87b8bc2 100644 --- a/text.py +++ b/text.py @@ -115,6 +115,9 @@ class ProgressWindow: del self.scale self.scale = None + def pulse(self): + pass + def set(self, amount): self.scale.set(int(float(amount) * self.multiplier)) self.screen.refresh() @@ -122,7 +125,7 @@ class ProgressWindow: def refresh(self): pass - def __init__(self, screen, title, text, total, updpct = 0.05): + def __init__(self, screen, title, text, total, updpct = 0.05, pulse = False): self.multiplier = 1 if total == 1.0: self.multiplier = 100 @@ -136,7 +139,8 @@ class ProgressWindow: g.add(t, 0, 0, (0, 0, 0, 1), anchorLeft=1) self.scale = Scale(int(width), int(float(total) * self.multiplier)) - g.add(self.scale, 0, 1) + if not pulse: + g.add(self.scale, 0, 1) g.draw() self.screen.refresh() @@ -351,8 +355,8 @@ class InstallInterface: pdb.post_mortem(tb) os._exit(1) - def progressWindow(self, title, text, total, updpct = 0.05): - return ProgressWindow(self.screen, title, text, total, updpct) + def progressWindow(self, title, text, total, updpct = 0.05, pulse = False): + return ProgressWindow(self.screen, title, text, total, updpct, pulse) def messageWindow(self, title, text, type="ok", default = None, custom_icon=None, custom_buttons=[]):
_______________________________________________ Anaconda-devel-list mailing list Anaconda-devel-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/anaconda-devel-list