Third patch series for the partition resizing. This time rebased against current HEAD and also split up into more reviewable chunks.
autopart.py | 26 ++++++++- cmdline.py | 9 ++- dispatch.py | 4 - fsset.py | 115 +++++++++++++++++++++++++++++++++++++++++ gui.py | 14 +++- iutil.py | 60 +++++++++++++++++++++ iw/lvm_dialog_gui.py | 18 +----- iw/partition_dialog_gui.py | 43 +++------------ iw/partition_ui_helpers_gui.py | 111 ++++++++++++++++++++------------------- iw/raid_dialog_gui.py | 22 ++----- packages.py | 2 partRequests.py | 18 ++++++ partedUtils.py | 18 ++++++ partitions.py | 25 -------- scripts/upd-instroot | 1 text.py | 12 ++-- 16 files changed, 343 insertions(+), 155 deletions(-)
--- cmdline.py | 9 ++++++--- gui.py | 14 ++++++++++---- text.py | 12 ++++++++---- 3 files changed, 24 insertions(+), 11 deletions(-)
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/gui.py b/gui.py index 7e26536..4eb564b 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 @@ -1037,11 +1042,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/text.py b/text.py index 9af171c..9e11e2b 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=[]):
this is helpful for operations like filesystem checking and resizing when we don't have a good way to do a nice bounded progress bar --- iutil.py | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 60 insertions(+), 0 deletions(-)
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:
--- scripts/upd-instroot | 1 + 1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/scripts/upd-instroot b/scripts/upd-instroot index 6f4b564..7359676 100755 --- a/scripts/upd-instroot +++ b/scripts/upd-instroot @@ -408,6 +408,7 @@ sbin/clock sbin/cryptsetup sbin/debugfs sbin/dosfslabel +sbin/dumpe2fs sbin/e2fsck sbin/e2fsadm sbin/e2label
With resizing, we're going to want sooner feedback so move the applying of partitioning changes to immediately after the partitioning step. This lets us also remove the early swap-on logic.
Still need to put up some scarier warnings about what's going to happen for people --- dispatch.py | 4 ++-- partitions.py | 24 ------------------------ 2 files changed, 2 insertions(+), 26 deletions(-)
diff --git a/dispatch.py b/dispatch.py index ea0d2fb..4c991e4 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/partitions.py b/partitions.py index 955b276..0dcb50c 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."""
--- partedUtils.py | 18 ++++++++++++++++++ 1 files changed, 18 insertions(+), 0 deletions(-)
diff --git a/partedUtils.py b/partedUtils.py index ae095e6..aa28940 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.
We add support to preexisting partitions to be resized by adjusting their partition spec and then acting on the changes within the main partitioning engine. Keep track of what the maximum size for a preexisting partitition is so that we don't have to check in the UI
Filesystems can claim to be resizable and implement the resize() method as well as the getMinimumSize() method --- autopart.py | 26 ++++++++++++++++++++++++-- fsset.py | 39 +++++++++++++++++++++++++++++++++++++++ partRequests.py | 18 ++++++++++++++++++ partitions.py | 1 + 4 files changed, 82 insertions(+), 2 deletions(-)
diff --git a/autopart.py b/autopart.py index 8886241..1492275 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.maxResizeSize = partedUtils.getMaxAvailPartSizeMB(part)
## print "disk layout after everything is done" ## print diskset.diskState() diff --git a/fsset.py b/fsset.py index b50bb27..2830721 100644 --- a/fsset.py +++ b/fsset.py @@ -2,6 +2,7 @@ # fsset.py: filesystem management # # Matt Wilson msw@redhat.com +# Jeremy Katz katzj@redhat.com # # Copyright 2001-2007 Red Hat, Inc. # @@ -177,10 +178,19 @@ 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): + log.warning("Unable to determinine minimal size for %s", device) + return 1 + def isKernelFS(self): """Returns True if this is an in-kernel pseudo-filesystem.""" return False @@ -1396,6 +1406,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 = [] @@ -1847,6 +1875,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 @@ -1928,6 +1958,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/partRequests.py b/partRequests.py index e113278..c5655e0 100644 --- a/partRequests.py +++ b/partRequests.py @@ -155,6 +155,9 @@ class RequestSpec: self.encryption = None """An optional LUKSDevice() describing block device encryption."""
+ self.targetSize = None + """Size to resize to""" + def __str__(self): if self.fstype: fsname = self.fstype.getName() @@ -212,6 +215,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): @@ -576,6 +582,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/partitions.py b/partitions.py index 0dcb50c..b5ec7a3 100644 --- a/partitions.py +++ b/partitions.py @@ -202,6 +202,7 @@ class Partitions: drive = drive, format = format) spec.device = fsset.PartedPartitionDevice(part).getDevice() + spec.maxResizeSize = partedUtils.getMaxAvailPartSizeMB(part)
# set label if makes sense if ptype and ptype.isMountable() and \
We do filesystem shrinking, then commit the partition table, and then filesystem growing so that the container for the filesystem is always as large or larger than the filesystem --- packages.py | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/packages.py b/packages.py index bbf2b8c..99f9a38 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)
Determination of the minimum size is a bit of a hack, but until the tools give us something better, it'll have to do --- fsset.py | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 76 insertions(+), 0 deletions(-)
diff --git a/fsset.py b/fsset.py index 2830721..9a93726 100644 --- a/fsset.py +++ b/fsset.py @@ -14,6 +14,7 @@ # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. #
+import math import string import isys import iutil @@ -515,6 +516,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("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)
This simplifies the edit partition dialog and adds resizing support --- iw/lvm_dialog_gui.py | 18 ++----- iw/partition_dialog_gui.py | 43 ++++------------ iw/partition_ui_helpers_gui.py | 111 +++++++++++++++++++++------------------- iw/raid_dialog_gui.py | 22 ++------ 4 files changed, 78 insertions(+), 116 deletions(-)
diff --git a/iw/lvm_dialog_gui.py b/iw/lvm_dialog_gui.py index 5d81064..472bcf1 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 7c757ae..fa7a6fd 100644 --- a/iw/partition_dialog_gui.py +++ b/iw/partition_dialog_gui.py @@ -206,30 +206,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: @@ -337,21 +333,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 @@ -455,10 +436,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 5fa5f25..4ad6af5 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, lukscb) = data combowidget.set_sensitive(widget.get_active()) @@ -239,100 +247,97 @@ 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 lukscb - checkbutton for 'encrypt using LUKS/dm-crypt' + 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) - - 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) + 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(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())
# this gets added to the table a bit later on lukscb = gtk.CheckButton(_("Encrypt Partition"))
- formatrb.connect("toggled", formatOptionCB, + formatcb.connect("toggled", formatOptionCB, (fstypeCombo, mountCombo, ofstype, lukscb))
- 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, + migratecb.connect("toggled", formatOptionCB, + (migfstypeCombo, mountCombo, ofstype)) + rc["migratecb"] = migratecb + rc["migfstypeCombo"] = migfstypeCombo + migratecb.connect("toggled", formatOptionCB, (migfstypeCombo, mountCombo, ofstype, None)) else: - migraterb = None + migratecb = None migfstypeCombo = None
- row = row + 1 + # 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.encryption and formatrb.get_active(): + 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 = row + 1 + + if origrequest.encryption and formatcb.get_active(): # probably never happen lukscb.set_active(1)
- lukscb.set_sensitive(formatrb.get_active()) - lukscb.set_data("formatstate", formatrb.get_active()) + lukscb.set_sensitive(formatcb.get_active()) + lukscb.set_data("formatstate", formatcb.get_active()) + rc["lukscb"] = lukscb maintable.attach(lukscb, 0, 2, row, row + 1) row = row + 1
- rc = {} - for var in ['noformatrb', 'formatrb', 'fstypeCombo', - 'migraterb', 'migfstypeCombo', 'lukscb']: - if eval("%s" % (var,)) is not None: - rc[var] = eval("%s" % (var,)) - 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 d90a3d0..22123f8 100644 --- a/iw/raid_dialog_gui.py +++ b/iw/raid_dialog_gui.py @@ -183,27 +183,17 @@ class RaidEditor: else: request.encryption = None 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
anaconda-devel@lists.stg.fedoraproject.org