All are for f16-branch, but none for beta.
Patch 4 seems to be a recurring issue. Apparently the last time someone worked on this they only had one disk in their test box.
Patch 5 is also for rhel6-branch.
--- pyanaconda/storage/__init__.py | 10 +++++++--- pyanaconda/storage/formats/fs.py | 25 ++++++++++++++++++++++++- 2 files changed, 31 insertions(+), 4 deletions(-)
diff --git a/pyanaconda/storage/__init__.py b/pyanaconda/storage/__init__.py index 387f3d4..62c66b3 100644 --- a/pyanaconda/storage/__init__.py +++ b/pyanaconda/storage/__init__.py @@ -1917,7 +1917,7 @@ class FSSet(object): fstype)) raise UnrecognizedFSTabEntryError()
- fmt = getFormat(fstype, device=device.path) + fmt = getFormat(fstype, device=device.path, exists=True) if fstype != "auto" and None in (device.format.type, fmt.type): log.info("Unrecognized filesystem type for %s (%s)" % (device.name, fstype)) @@ -1928,8 +1928,12 @@ class FSSet(object): ftype = getattr(fmt, "mountType", fmt.type) dtype = getattr(device.format, "mountType", device.format.type) if fstype != "auto" and ftype != dtype: - raise StorageError("scanned format (%s) differs from fstab " - "format (%s)" % (dtype, ftype)) + if fmt.testMount(): + # XXX FIXME: disallow migration for this FS instance + device.format = fmt + else: + raise StorageError("scanned format (%s) differs from fstab " + "format (%s)" % (dtype, ftype)) del ftype del dtype
diff --git a/pyanaconda/storage/formats/fs.py b/pyanaconda/storage/formats/fs.py index 90d97e7..bb2dddc 100644 --- a/pyanaconda/storage/formats/fs.py +++ b/pyanaconda/storage/formats/fs.py @@ -24,7 +24,6 @@ """ Filesystem classes for use by anaconda.
TODO: - - migration - bug 472127: allow creation of tmpfs filesystems (/tmp, /var/tmp, &c) """ import math @@ -575,6 +574,30 @@ class FS(DeviceFormat): # also need to update the list of supported filesystems. kernel_filesystems = get_kernel_filesystems()
+ def testMount(self, options=None): + """ Try to mount the fs and return True if successful. """ + ret = False + + if self.status: + raise RuntimeError("filesystem is already mounted") + + # create a temp dir + prefix = "%s.%s" % (os.path.basename(self.device), self.type) + mountpoint = tempfile.mkdtemp(prefix=prefix) + + # try the mount + try: + self.mount(mountpoint=mountpoint) + except Exception as e: + log.info("test mount failed: %s" % e) + else: + self.unmount() + ret = True + finally: + os.rmdir(mountpoint) + + return ret + def mount(self, *args, **kwargs): """ Mount this filesystem.
It's a fatal error either way, but showing a popup is nicer than crashing. --- pyanaconda/storage/__init__.py | 25 +++++++++++++++++-------- pyanaconda/storage/errors.py | 3 +++ 2 files changed, 20 insertions(+), 8 deletions(-)
diff --git a/pyanaconda/storage/__init__.py b/pyanaconda/storage/__init__.py index 62c66b3..d77e766 100644 --- a/pyanaconda/storage/__init__.py +++ b/pyanaconda/storage/__init__.py @@ -1332,8 +1332,8 @@ class Storage(object): def umountFilesystems(self, ignoreErrors=True, swapoff=True): self.fsset.umountFilesystems(ignoreErrors=ignoreErrors, swapoff=swapoff)
- def parseFSTab(self): - self.fsset.parseFSTab() + def parseFSTab(self, anaconda=None, chroot=None): + self.fsset.parseFSTab(anaconda=anaconda, chroot=chroot)
def mkDevRoot(self): self.fsset.mkDevRoot() @@ -1581,7 +1581,7 @@ def mountExistingSystem(anaconda, rootEnt, mountpoint="/", options=readOnly)
- fsset.parseFSTab() + fsset.parseFSTab(anaconda=anaconda)
# check for dirty filesystems dirtyDevs = [] @@ -1928,12 +1928,13 @@ class FSSet(object): ftype = getattr(fmt, "mountType", fmt.type) dtype = getattr(device.format, "mountType", device.format.type) if fstype != "auto" and ftype != dtype: + log.info("fstab says %s at %s is %s" % (dtype, mountpoint, ftype)) if fmt.testMount(): - # XXX FIXME: disallow migration for this FS instance + # XXX we should probably disallow migration for this fs device.format = fmt else: - raise StorageError("scanned format (%s) differs from fstab " - "format (%s)" % (dtype, ftype)) + raise FSTabTypeMismatchError("%s: detected as %s, fstab says %s" + % (mountpoint, dtype, ftype)) del ftype del dtype
@@ -1949,7 +1950,7 @@ class FSSet(object):
return device
- def parseFSTab(self, chroot=None): + def parseFSTab(self, anaconda=None, chroot=None): """ parse /etc/fstab
preconditions: @@ -2018,7 +2019,15 @@ class FSSet(object): # just write the line back out as-is after upgrade self.preserveLines.append(line) continue - except Exception as e: + except FSTabTypeMismatchError as e: + if anaconda and hasattr(anaconda.intf, "messageWindow"): + err = _("There is an entry in your /etc/fstab file " + "that contains an invalid or incorrect " + "filesystem type:\n\n ") + err += str(e) + anaconda.intf.messageWindow(_("Error"), err) + sys.exit(0) + raise Exception("fstab entry %s is malformed: %s" % (devspec, e))
if not device: diff --git a/pyanaconda/storage/errors.py b/pyanaconda/storage/errors.py index ea7f91d..6c2ed2e 100644 --- a/pyanaconda/storage/errors.py +++ b/pyanaconda/storage/errors.py @@ -159,6 +159,9 @@ class UdevError(StorageError): class UnrecognizedFSTabEntryError(StorageError): pass
+class FSTabTypeMismatchError(StorageError): + pass + # dasd class DasdFormatError(StorageError): pass
Related: rhbz#739408 --- pyanaconda/bootloader.py | 7 ++++--- pyanaconda/iw/cleardisks_gui.py | 10 +++++----- 2 files changed, 9 insertions(+), 8 deletions(-)
diff --git a/pyanaconda/bootloader.py b/pyanaconda/bootloader.py index f3c9cf8..e7effc9 100644 --- a/pyanaconda/bootloader.py +++ b/pyanaconda/bootloader.py @@ -232,6 +232,7 @@ class BootLoader(object): log.debug("using stage2 device as stage1") self.stage1_device = self.stage2_device else: + log.debug("stage1_drive is %s" % self.stage1_drive) devices = self.stage1_devices if self.stage1_drive: devices = [d for d in devices if @@ -274,7 +275,8 @@ class BootLoader(object):
def _sort_drives(self, drives): """Sort drives based on the drive order.""" - _drives = drives[:] + _drives = sorted(drives, + cmp=self.storage.compareDisks, key=lambda d: d.name) for name in reversed(self._drive_order): try: idx = [d.name for d in _drives].index(name) @@ -298,8 +300,7 @@ class BootLoader(object): # only generate the list if it is empty return self._drives
- # XXX requiring partitioned may break clearpart - drives = [d for d in self.storage.disks if d.partitioned] + drives = [d for d in self.storage.disks if not d.format.hidden] self._drives = self._sort_drives(drives)
# set "boot drive" diff --git a/pyanaconda/iw/cleardisks_gui.py b/pyanaconda/iw/cleardisks_gui.py index 36453a4..9b84474 100644 --- a/pyanaconda/iw/cleardisks_gui.py +++ b/pyanaconda/iw/cleardisks_gui.py @@ -148,10 +148,11 @@ class ClearDisksWindow (InstallWindow): self.rightDS.addColumn(_("Capacity"), 7) self.rightDS.addColumn(_("Identifier"), 9)
- # Store the first disk (according to our detected BIOS order) for + # Store the first disk (according to bootloader ordering) for # auto boot device selection - names = map(lambda d: d.name, disks) - self.bootDisk = sorted(names, self.anaconda.storage.compareDisks)[0] + self.bootDisk = getattr(self.anaconda.bootloader.stage1_drive, + "name", + self.anaconda.bootloader.drives[0].name)
# The device filtering UI set up exclusiveDisks as a list of the names # of all the disks we should use later on. Now we need to go get those, @@ -159,8 +160,7 @@ class ClearDisksWindow (InstallWindow): # selector. for d in disks: rightVisible = d.name in self.anaconda.storage.config.clearPartDisks - rightActive = rightVisible and \ - d == self.anaconda.bootloader.drives[0] + rightActive = rightVisible and d.name == self.bootDisk leftVisible = not rightVisible
if hasattr(d, "wwid"):
- reset storage from autopart_type only if custom selected - reset storage last thing in cleardisks_gui for all autopart, including the single-disk case - unset bootloader stage1_drive and stage1_device in Storage.reset since they are no longer valid after reset - store autopart shrink requests in Storage and reschedule the actions as needed across storage resets when users go back and forth between cleardisks_gui and partitioning
Resolves: rhbz#741587 Related: rhbz#739408 --- pyanaconda/iw/autopart_type.py | 19 ++++++++++--------- pyanaconda/iw/cleardisks_gui.py | 20 ++++++++++++-------- pyanaconda/storage/__init__.py | 6 ++++++ pyanaconda/storage/partitioning.py | 10 ++++++++++ 4 files changed, 38 insertions(+), 17 deletions(-)
diff --git a/pyanaconda/iw/autopart_type.py b/pyanaconda/iw/autopart_type.py index 47e089d..87907b8 100644 --- a/pyanaconda/iw/autopart_type.py +++ b/pyanaconda/iw/autopart_type.py @@ -149,14 +149,6 @@ class PartitionTypeWindow(InstallWindow): if self.storage.checkNoDisks(): raise gui.StayOnScreen
- # reset storage, this is only done when moving forward, not back - # temporarily unset storage.config.clearPartType so that all devices - # will be found during storage reset - clearPartType = self.anaconda.storage.config.clearPartType - self.anaconda.storage.config.clearPartType = None - self.anaconda.storage.reset() - self.anaconda.storage.config.clearPartType = clearPartType - self.storage.clearPartChoice = self.buttonGroup.getCurrent()
if self.buttonGroup.getCurrent() == "custom": @@ -165,13 +157,22 @@ class PartitionTypeWindow(InstallWindow): self.dispatch.request_steps("partition") self.dispatch.request_steps_gently("bootloader")
+ # re-scan all devices. this is handled in cleardisks_gui if autopart self.storage.config.clearPartType = CLEARPART_TYPE_NONE + self.storage.reset() else: if self.buttonGroup.getCurrent() == "shrink": + # we need to store this information so that it can survive + # storage.reset since it may get called going between + # the partitioning screen and the cleardisks screen when users + # elect to do autopart w/ review and go back and forth (rc, actions) = whichToShrink(self.storage, self.intf) if rc == gtk.RESPONSE_OK: for action in actions: - self.storage.devicetree.registerAction(action) + path = action.device.path + size = action.device.targetSize + self.storage.shrinkPartitions[path] = size + self.storage.devicetree.cancelAction(action) else: raise gui.StayOnScreen
diff --git a/pyanaconda/iw/cleardisks_gui.py b/pyanaconda/iw/cleardisks_gui.py index 9b84474..5ce6aee 100644 --- a/pyanaconda/iw/cleardisks_gui.py +++ b/pyanaconda/iw/cleardisks_gui.py @@ -57,12 +57,17 @@ class ClearDisksWindow (InstallWindow): custom_icon="error") raise gui.StayOnScreen
- bootDisk = selected[0][OBJECT_COL] - cleardisks.sort(self.anaconda.storage.compareDisks) + self.resetStorage(clear=cleardisks, boot=selected[0][OBJECT_COL].name)
- self.anaconda.storage.config.clearPartDisks = cleardisks - self.anaconda.bootloader.stage1_drive = bootDisk + def resetStorage(self, clear=None, boot=None): + """ Save clearPartDisks and reset storage, preserving stage1_drive. """ + # Re-scan the devices. We only come here for autopart, so the clearpart + # type should be set appropriately already. + self.anaconda.storage.config.clearPartDisks = clear + self.anaconda.storage.reset() + boot_disk = self.anaconda.storage.devicetree.getDeviceByName(boot) + self.anaconda.bootloader.stage1_drive = boot_disk
def getScreen (self, anaconda): # We can't just use exclusiveDisks here because of kickstart. First, @@ -73,10 +78,11 @@ class ClearDisksWindow (InstallWindow): # issues. disks = filter(lambda d: not d.format.hidden, anaconda.storage.disks)
+ self.anaconda = anaconda + # Skip this screen as well if there's only one disk to use. if len(disks) == 1: - anaconda.storage.config.clearPartDisks = [disks[0].name] - anaconda.bootloader.stage1_drive = disks[0] + self.resetStorage(clear=[disks[0].name], boot=disks[0].name) return None
(xml, self.vbox) = gui.getGladeWidget("cleardisks.glade", "vbox") @@ -87,8 +93,6 @@ class ClearDisksWindow (InstallWindow): self.installTargetImage = xml.get_widget("installTargetImage") self.installTargetTip = xml.get_widget("installTargetTip")
- self.anaconda = anaconda - self.leftVisible = 1 self.leftActive = 2 self.rightVisible = 4 diff --git a/pyanaconda/storage/__init__.py b/pyanaconda/storage/__init__.py index d77e766..f42b49f 100644 --- a/pyanaconda/storage/__init__.py +++ b/pyanaconda/storage/__init__.py @@ -362,6 +362,7 @@ class Storage(object): self.autoPartAddBackupPassphrase = False self.encryptionRetrofit = False self.autoPartitionRequests = [] + self.shrinkPartitions = {} self.eddDict = {}
self.__luksDevs = {} @@ -486,7 +487,12 @@ class Storage(object): self.anaconda.rootParts = None self.anaconda.upgradeRoot = None if self.anaconda: + # clear out bootloader attributes that refer to devices that are + # no longer in the tree self.anaconda.bootloader.clear_drive_list() + self.anaconda.bootloader.stage1_drive = None + self.anaconda.bootloader.stage1_device = None + self.dumpState("initial") if prog: prog.pop() diff --git a/pyanaconda/storage/partitioning.py b/pyanaconda/storage/partitioning.py index e33943f..98ed172 100644 --- a/pyanaconda/storage/partitioning.py +++ b/pyanaconda/storage/partitioning.py @@ -227,6 +227,15 @@ def _scheduleLVs(storage, devs): # schedule the device for creation storage.createDevice(dev)
+def scheduleShrinkActions(storage): + """ Schedule actions to shrink partitions as per autopart selection. """ + for (path, size) in storage.shrinkPartitions.items(): + device = storage.getDeviceByPath(path) + if not device: + raise StorageError("device %s scheduled for shrink disappeared" + % path) + storage.registerAction(ActionResizeFormat(device, size)) + storage.registerAction(ActionResizeDevice(device, size))
def doAutoPartition(anaconda): log.debug("doAutoPartition(%s)" % anaconda) @@ -246,6 +255,7 @@ def doAutoPartition(anaconda): devs = []
if anaconda.storage.doAutoPart: + scheduleShrinkActions(anaconda.storage) clearPartitions(anaconda.storage, bootloader=anaconda.bootloader) # update the bootloader's drive list to add disks which have their # whole disk format replaced by a disklabel. Make sure to keep any
When doing an upgrade we only want to check for dirty filesystems on devices referenced in /etc/fstab. --- pyanaconda/storage/__init__.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/pyanaconda/storage/__init__.py b/pyanaconda/storage/__init__.py index f42b49f..3c70c42 100644 --- a/pyanaconda/storage/__init__.py +++ b/pyanaconda/storage/__init__.py @@ -1591,7 +1591,7 @@ def mountExistingSystem(anaconda, rootEnt,
# check for dirty filesystems dirtyDevs = [] - for device in fsset.devices: + for device in fsset.mountpoints.values(): if not hasattr(device.format, "isDirty"): continue
On 09/29/2011 05:43 PM, David Lehman wrote:
All are for f16-branch, but none for beta.
Patch 4 seems to be a recurring issue. Apparently the last time someone worked on this they only had one disk in their test box.
Patch 5 is also for rhel6-branch.
Anaconda-devel-list mailing list Anaconda-devel-list@redhat.com https://www.redhat.com/mailman/listinfo/anaconda-devel-list
Ack to the set.
Ales
anaconda-devel@lists.fedoraproject.org