[PATCH 2/7] Remove the anaconda attribute from Storage and add a bootloader attr.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



---
 pyanaconda/rescue.py               |    5 +-
 pyanaconda/storage/__init__.py     |  363 +++++++++---------------------------
 pyanaconda/storage/errors.py       |    6 +
 pyanaconda/storage/partitioning.py |  226 +++++++++--------------
 pyanaconda/upgrade.py              |    2 +-
 5 files changed, 185 insertions(+), 417 deletions(-)

diff --git a/pyanaconda/rescue.py b/pyanaconda/rescue.py
index 6fab62d..0698357 100644
--- a/pyanaconda/rescue.py
+++ b/pyanaconda/rescue.py
@@ -339,8 +339,9 @@ def doRescue(anaconda):
 
     if root:
         try:
-            rc = mountExistingSystem(anaconda, root,
-                                     allowDirty = 1, warnDirty = 1,
+            # TODO: add a callback to warn about dirty filesystems
+            rc = mountExistingSystem(anaconda.storage.fsset, root,
+                                     allowDirty = 1,
                                      readOnly = readOnly)
 
             if not flags.imageInstall:
diff --git a/pyanaconda/storage/__init__.py b/pyanaconda/storage/__init__.py
index ae6e26f..e4f0b17 100644
--- a/pyanaconda/storage/__init__.py
+++ b/pyanaconda/storage/__init__.py
@@ -304,25 +304,18 @@ class StorageDiscoveryConfig(object):
 
 
 class Storage(object):
-    def __init__(self, anaconda=None, intf=None, platform=None):
+    def __init__(self, data=None, platform=None):
         """ Create a Storage instance.
 
             Keyword Arguments:
 
-                anaconda    -   an Anaconda instance
-                intf        -   an InstallInterface instance
+                data        -   a pykickstart Handler instance
                 platform    -   a Platform instance
 
-            All arguments are optional. An Anaconda instance will contain
-            an InstallInterface and a Platform instance, so it makes sense
-            to pass in either an Anaconda instance or as many of the other
-            two as is desired. Explicitly passed intf or platform will take
-            precedence over those in the Anaconda instance.
-
         """
-        self.anaconda = anaconda
-        self._intf = intf
-        self._platform = platform
+        self.data = data
+        self.platform = platform
+        self._bootloader = None
 
         self.config = StorageDiscoveryConfig()
 
@@ -365,8 +358,8 @@ class Storage(object):
         self.doEncryptionPassphraseRetrofits()
 
         # now set the boot partition's flag
-        if self.anaconda:
-            if self.anaconda.bootloader.stage2_bootable:
+        if self.bootloader:
+            if self.bootloader.stage2_bootable:
                 boot = self.bootDevice
             else:
                 boot = self.bootLoaderDevice
@@ -437,7 +430,7 @@ class Storage(object):
                               self.config.exclusiveDisks,
                               self.config.zeroMbr)
         clearPartType = self.config.clearPartType # save this before overriding it
-        if getattr(self.anaconda, "upgrade", False):
+        if self.data and self.data.upgrade.upgrade:
             self.config.clearPartType = CLEARPART_TYPE_NONE
 
         self.devicetree.reset(conf=self.config,
@@ -449,16 +442,12 @@ class Storage(object):
         self.config.clearPartType = clearPartType # set it back
         self.fsset = FSSet(self.devicetree)
         self.eddDict = get_edd_dict(self.partitioned)
-        if hasattr(self.anaconda, "rootParts") and \
-           hasattr(self.anaconda, "upgradeRoot"):
-            self.anaconda.rootParts = None
-            self.anaconda.upgradeRoot = None
-        if self.anaconda:
+        if self.bootloader:
             # 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.bootloader.clear_drive_list()
+            self.bootloader.stage1_drive = None
+            self.bootloader.stage1_device = None
 
         self.dumpState("initial")
 
@@ -657,24 +646,7 @@ class Storage(object):
     @property
     def liveImage(self):
         """ The OS image used by live installs. """
-        _image = None
-        if flags.livecdInstall and hasattr(self.anaconda, "methodstr"):
-            _image = self.devicetree.getDeviceByPath(self.anaconda.methodstr[9:])
-        return _image
-
-    @property
-    def intf(self):
-        _intf = self._intf
-        if not _intf:
-            _intf = getattr(self.anaconda, "intf", None)
-        return _intf
-
-    @property
-    def platform(self):
-        _platform = self._platform
-        if not _platform:
-            _platform = getattr(self.anaconda, "platform", None)
-        return _platform
+        raise NotImplementedError()
 
     def exceptionDisks(self):
         """ Return a list of removable devices to save exceptions to.
@@ -839,8 +811,8 @@ class Storage(object):
             name = kwargs.pop("name")
         else:
             hostname = ""
-            if hasattr(self.anaconda, "network"):
-                hostname = self.anaconda.network.hostname
+            if self.data:
+                hostname = self.data.network.hostname
             name = self.createSuggestedVGName(hostname=hostname)
 
         if name in [d.name for d in self.devices]:
@@ -1056,7 +1028,6 @@ class Storage(object):
         try:
             boot = self.bootDevice
         except (DeviceError, AttributeError):
-            # AttributeError means we have no anaconda or platform. it's ok.
             boot = None
 
         if not root:
@@ -1069,19 +1040,7 @@ class Storage(object):
                               "megabytes which is usually too small to "
                               "install %s.") % (productName,))
 
-        if (root and
-            hasattr(self.anaconda, "backend") and
-            root.size < self.anaconda.backend.getMinimumSizeMB("/")):
-            if flags.livecdInstall:
-                live = " Live"
-            else:
-                live = ""
-            errors.append(_("Your / partition is less than %(min)s "
-                            "MB which is lower than recommended "
-                            "for a normal %(productName)s%(live)s install.")
-                          % {'min': self.anaconda.backend.getMinimumSizeMB("/"),
-                             'productName': productName,
-                             'live': live})
+        # FIXME: put a check here for enough space on the filesystems. maybe?
 
         # livecds have to have the rootfs type match up
         if (root and
@@ -1142,23 +1101,23 @@ class Storage(object):
             warnings.append(_("Installing on a FireWire device.  This may "
                               "or may not produce a working system."))
 
-        if self.anaconda and self.anaconda.dispatch.step_enabled('instbootloader'):
-            stage1 = self.anaconda.bootloader.stage1_device
+        if self.data and self.data.bootloader.location is not None:
+            stage1 = self.bootloader.stage1_device
             if not stage1:
                 errors.append(_("you have not created a bootloader stage1 "
                                 "target device"))
             else:
-                self.anaconda.bootloader.is_valid_stage1_device(stage1)
-                errors.extend(self.anaconda.bootloader.errors)
-                warnings.extend(self.anaconda.bootloader.warnings)
+                self.bootloader.is_valid_stage1_device(stage1)
+                errors.extend(self.bootloader.errors)
+                warnings.extend(self.bootloader.warnings)
 
-            stage2 = self.anaconda.bootloader.stage2_device
+            stage2 = self.bootloader.stage2_device
             if not stage2:
                 errors.append(_("You have not created a bootable partition."))
             else:
-                self.anaconda.bootloader.is_valid_stage2_device(stage2)
-                errors.extend(self.anaconda.bootloader.errors)
-                warnings.extend(self.anaconda.bootloader.warnings)
+                self.bootloader.is_valid_stage2_device(stage2)
+                errors.extend(self.bootloader.errors)
+                warnings.extend(self.bootloader.warnings)
 
         if not swaps:
             from pyanaconda.storage.size import Size
@@ -1203,14 +1162,8 @@ class Storage(object):
 
     def checkNoDisks(self):
         """Check that there are valid disk devices."""
-        if not self.disks and self.intf:
-            self.intf.messageWindow(_("No Drives Found"),
-                               _("An error has occurred - no valid devices were "
-                                 "found on which to create new file systems. "
-                                 "Please check your hardware for the cause "
-                                 "of this problem."))
-            return True
-        return False
+        if not self.disks:
+            raise NoDisksError()
 
     def dumpState(self, suffix):
         """ Dump the current device list to the storage shelf. """
@@ -1290,21 +1243,19 @@ class Storage(object):
         f.write("\n")
 
     def turnOnSwap(self, upgrading=None):
-        self.fsset.turnOnSwap(intf=self.intf,
-                              rootPath=ROOT_PATH,
+        self.fsset.turnOnSwap(rootPath=ROOT_PATH,
                               upgrading=upgrading)
 
     def mountFilesystems(self, raiseErrors=None, readOnly=None, skipRoot=False):
-        self.fsset.mountFilesystems(intf=self.intf,
-                                    rootPath=ROOT_PATH,
+        self.fsset.mountFilesystems(rootPath=ROOT_PATH,
                                     raiseErrors=raiseErrors,
                                     readOnly=readOnly, skipRoot=skipRoot)
 
     def umountFilesystems(self, ignoreErrors=True, swapoff=True):
         self.fsset.umountFilesystems(ignoreErrors=ignoreErrors, swapoff=swapoff)
 
-    def parseFSTab(self, anaconda=None, chroot=None):
-        self.fsset.parseFSTab(anaconda=anaconda, chroot=chroot)
+    def parseFSTab(self, chroot=None):
+        self.fsset.parseFSTab(chroot=chroot)
 
     def mkDevRoot(self):
         self.fsset.mkDevRoot()
@@ -1313,32 +1264,39 @@ class Storage(object):
         self.fsset.createSwapFile(device, size)
 
     @property
-    def bootDevice(self):
-        dev = None
-        if self.anaconda:
-            dev = self.anaconda.bootloader.stage2_device
-        return dev
+    def bootloader(self):
+        if self._bootloader is None and self.platform is not None:
+            self._bootloader = self.platform.bootloaderClass(self.platform)
+        return self._bootloader
+
+    @property
+    def bootDisk(self):
+        disk = None
+        if self.data:
+            spec = self.data.bootloader.bootDrive
+            disk = self.devicetree.resolveDevice(spec)
+        return disk
 
     @property
-    def bootLoaderDevice(self):
+    def bootDevice(self):
         dev = None
-        if self.anaconda:
-            dev = self.anaconda.bootloader.stage1_device
+        if self.fsset:
+            dev = self.mountpoints.get("/boot", self.rootDevice)
         return dev
 
     @property
     def bootFSTypes(self):
         """A list of all valid filesystem types for the boot partition."""
         fstypes = []
-        if self.anaconda:
-            fstypes = self.anaconda.bootloader.stage2_format_types
+        if self.bootloader:
+            fstypes = self.bootloader.stage2_format_types
         return fstypes
 
     @property
     def defaultBootFSType(self):
         """The default filesystem type for the boot partition."""
         fstype = None
-        if self.anaconda:
+        if self.bootloader:
             fstype = self.bootFSTypes[0]
         return fstype
 
@@ -1516,13 +1474,15 @@ def findExistingRootDevices(anaconda, upgradeany=False):
 
     return (rootDevs, notUpgradable)
 
-def mountExistingSystem(anaconda, rootEnt,
-                        allowDirty=None, warnDirty=None,
+def mountExistingSystem(fsset, rootEnt,
+                        allowDirty=None, dirtyCB=None,
                         readOnly=None):
     """ Mount filesystems specified in rootDevice's /etc/fstab file. """
     rootDevice = rootEnt[0]
     rootPath = ROOT_PATH
-    fsset = anaconda.storage.fsset
+    if dirtyCB is None:
+        dirtyCB = lambda l: False
+
     if readOnly:
         readOnly = "ro"
     else:
@@ -1539,7 +1499,7 @@ def mountExistingSystem(anaconda, rootEnt,
                                 mountpoint="/",
                                 options=readOnly)
 
-    fsset.parseFSTab(anaconda=anaconda)
+    fsset.parseFSTab()
 
     # check for dirty filesystems
     dirtyDevs = []
@@ -1558,28 +1518,10 @@ def mountExistingSystem(anaconda, rootEnt,
                                                             device.format.type))
             dirtyDevs.append(device.path)
 
-    messageWindow = anaconda.intf.messageWindow
-    if not allowDirty and dirtyDevs:
-        messageWindow(_("Dirty File Systems"),
-                      _("The following file systems for your Linux system "
-                        "were not unmounted cleanly.  Please boot your "
-                        "Linux installation, let the file systems be "
-                        "checked and shut down cleanly to upgrade.\n"
-                        "%s") % "\n".join(dirtyDevs))
-        anaconda.storage.devicetree.teardownAll()
-        sys.exit(0)
-    elif warnDirty and dirtyDevs:
-        rc = messageWindow(_("Dirty File Systems"),
-                           _("The following file systems for your Linux "
-                             "system were not unmounted cleanly.  Would "
-                             "you like to mount them anyway?\n"
-                             "%s") % "\n".join(dirtyDevs),
-                             type = "yesno")
-        if rc == 0:
-            return -1
+    if dirtyDevs and (not allowDirty or dirtyCB(dirtyDevs)):
+        raise DirtyFSError("\n".join(dirtyDevs))
 
-    fsset.mountFilesystems(intf=anaconda.intf, rootPath=ROOT_PATH,
-                           readOnly=readOnly, skipRoot=True)
+    fsset.mountFilesystems(rootPath=ROOT_PATH, readOnly=readOnly, skipRoot=True)
 
 
 class BlkidTab(object):
@@ -1908,7 +1850,7 @@ class FSSet(object):
 
         return device
 
-    def parseFSTab(self, anaconda=None, chroot=None):
+    def parseFSTab(self, chroot=None):
         """ parse /etc/fstab
 
             preconditions:
@@ -1977,16 +1919,6 @@ class FSSet(object):
                     # just write the line back out as-is after upgrade
                     self.preserveLines.append(line)
                     continue
-                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:
                     continue
@@ -1998,25 +1930,14 @@ class FSSet(object):
                         # just write duplicates back out post-install
                         self.preserveLines.append(line)
 
-    def turnOnSwap(self, intf=None, rootPath="", upgrading=None):
-        def swapErrorDialog(msg, device):
-            if not intf:
-                # can't show a dialog? ignore this busted device.
-                ret = 0
-            else:
-                buttons = [_("Skip"), _("Format"), _("_Exit")]
-                ret = intf.messageWindow(_("Error"), msg, type="custom",
-                                         custom_buttons=buttons,
-                                         custom_icon="warning")
+    def turnOnSwap(self, rootPath="", upgrading=None, errorcb=None):
+        """ Activate the system's swap space.
 
-            if ret == 0:
-                self.devicetree._removeDevice(device)
-                return False
-            elif ret == 1:
-                device.format.create(force=True)
-                return True
-            else:
-                sys.exit(0)
+            errorcb should accept an Exception instance and a Device instance
+            return True if the exception should be fatal, which is the default.
+        """
+        if errorcb is None:
+            errorcb = lambda e,d: True
 
         for device in self.swapDevices:
             if isinstance(device, FileDevice):
@@ -2036,69 +1957,23 @@ class FSSet(object):
                 try:
                     device.setup()
                     device.format.setup()
-                except OldSwapError:
-                    msg = _("The swap device:\n\n     %s\n\n"
-                            "is an old-style Linux swap partition.  If "
-                            "you want to use this device for swap space, "
-                            "you must reformat as a new-style Linux swap "
-                            "partition.") \
-                          % device.path
-
-                    if swapErrorDialog(msg, device):
-                        continue
-                except SuspendError:
-                    if upgrading:
-                        msg = _("The swap device:\n\n     %s\n\n"
-                                "in your /etc/fstab file is currently in "
-                                "use as a software suspend device, "
-                                "which means your system is hibernating. "
-                                "To perform an upgrade, please shut down "
-                                "your system rather than hibernating it.") \
-                              % device.path
-                    else:
-                        msg = _("The swap device:\n\n     %s\n\n"
-                                "in your /etc/fstab file is currently in "
-                                "use as a software suspend device, "
-                                "which means your system is hibernating. "
-                                "If you are performing a new install, "
-                                "make sure the installer is set "
-                                "to format all swap devices.") \
-                              % device.path
-
-                    if swapErrorDialog(msg, device):
-                        continue
-                except UnknownSwapError:
-                    msg = _("The swap device:\n\n     %s\n\n"
-                            "does not contain a supported swap volume.  In "
-                            "order to continue installation, you will need "
-                            "to format the device or skip it.") \
-                          % device.path
-
-                    if swapErrorDialog(msg, device):
-                        continue
-                except DeviceError as (msg, name):
-                    if intf:
-                        if upgrading:
-                            err = _("Error enabling swap device %(name)s: "
-                                    "%(msg)s\n\n"
-                                    "The /etc/fstab on your upgrade partition "
-                                    "does not reference a valid swap "
-                                    "device.\n\nPress OK to exit the "
-                                    "installer") % {'name': name, 'msg': msg}
-                        else:
-                            err = _("Error enabling swap device %(name)s: "
-                                    "%(msg)s\n\n"
-                                    "This most likely means this swap "
-                                    "device has not been initialized.\n\n"
-                                    "Press OK to exit the installer.") % \
-                                  {'name': name, 'msg': msg}
-                        intf.messageWindow(_("Error"), err)
-                    sys.exit(0)
-
-                break
+                except StorageError as e:
+                    if errorcb(e, device):
+                        raise
+                else:
+                    break
 
-    def mountFilesystems(self, intf=None, rootPath="", readOnly=None,
+    def mountFilesystems(self, rootPath="", readOnly=None, errorcb=None,
                          skipRoot=False, raiseErrors=None):
+        """ Mount the system's filesystems.
+
+            errorcb should accept an Exception instance and a Device instance
+            and return True if the exception should be fatal, which is the
+            default.
+        """
+        if errorcb is None:
+            errorcb = lambda e,d: True
+
         devices = self.mountpoints.values() + self.swapDevices
         devices.extend([self.dev, self.devshm, self.devpts, self.sysfs,
                         self.proc, self.selinux, self.usb])
@@ -2135,8 +2010,10 @@ class FSSet(object):
             try:
                 device.setup()
             except Exception as msg:
-                # FIXME: need an error popup
-                continue
+                if errorcb(e, device):
+                    raise
+                else:
+                    continue
 
             if readOnly:
                 options = "%s,%s" % (options, readOnly)
@@ -2144,73 +2021,11 @@ class FSSet(object):
             try:
                 device.format.setup(options=options,
                                     chroot=rootPath)
-            except OSError as e:
-                log.error("OSError: (%d) %s" % (e.errno, e.strerror))
-
-                if intf:
-                    if e.errno == errno.EEXIST:
-                        intf.messageWindow(_("Invalid mount point"),
-                                           _("An error occurred when trying "
-                                             "to create %s.  Some element of "
-                                             "this path is not a directory. "
-                                             "This is a fatal error and the "
-                                             "install cannot continue.\n\n"
-                                             "Press <Enter> to exit the "
-                                             "installer.")
-                                           % (device.format.mountpoint,))
-                    else:
-                        na = {'mountpoint': device.format.mountpoint,
-                              'msg': e.strerror}
-                        intf.messageWindow(_("Invalid mount point"),
-                                           _("An error occurred when trying "
-                                             "to create %(mountpoint)s: "
-                                             "%(msg)s.  This is "
-                                             "a fatal error and the install "
-                                             "cannot continue.\n\n"
-                                             "Press <Enter> to exit the "
-                                             "installer.") % na)
-                sys.exit(0)
-            except SystemError as (num, msg):
-                log.error("SystemError: (%d) %s" % (num, msg) )
-
-                if raiseErrors:
+            except Exception as e:
+                log.error("error mounting %s on %s: %s"
+                          % (device.path, device.format.mountpoint, e))
+                if errorcb(e, device):
                     raise
-                if intf and not device.format.linuxNative:
-                    na = {'path': device.path,
-                          'mountpoint': device.format.mountpoint}
-                    ret = intf.messageWindow(_("Unable to mount filesystem"),
-                                             _("An error occurred mounting "
-                                             "device %(path)s as "
-                                             "%(mountpoint)s.  You may "
-                                             "continue installation, but "
-                                             "there may be problems.") % na,
-                                             type="custom",
-                                             custom_icon="warning",
-                                             custom_buttons=[_("_Exit installer"),
-                                                            _("_Continue")])
-
-                    if ret == 0:
-                        sys.exit(0)
-                    else:
-                        continue
-
-                sys.exit(0)
-            except FSError as msg:
-                log.error("FSError: %s" % msg)
-
-                if intf:
-                    na = {'path': device.path,
-                          'mountpoint': device.format.mountpoint,
-                          'msg': msg}
-                    intf.messageWindow(_("Unable to mount filesystem"),
-                                       _("An error occurred mounting "
-                                         "device %(path)s as %(mountpoint)s: "
-                                         "%(msg)s. This is "
-                                         "a fatal error and the install "
-                                         "cannot continue.\n\n"
-                                         "Press <Enter> to exit the "
-                                         "installer.") % na)
-                sys.exit(0)
 
         self.active = True
 
diff --git a/pyanaconda/storage/errors.py b/pyanaconda/storage/errors.py
index 2217873..6b7e5fc 100644
--- a/pyanaconda/storage/errors.py
+++ b/pyanaconda/storage/errors.py
@@ -25,6 +25,9 @@ class StorageError(Exception):
         self.hardware_fault = kwargs.pop("hardware_fault", False)
         super(StorageError, self).__init__(*args, **kwargs)
 
+class NoDisksError(StorageError):
+    pass
+
 # Device
 class DeviceError(StorageError):
     pass
@@ -78,6 +81,9 @@ class FSResizeError(FSError):
 class FSMigrateError(FSError):
     pass
 
+class DirtyFSError(FSError):
+    pass
+
 class LUKSError(DeviceFormatError):
     pass
 
diff --git a/pyanaconda/storage/partitioning.py b/pyanaconda/storage/partitioning.py
index 7dba783..cbcb43a 100644
--- a/pyanaconda/storage/partitioning.py
+++ b/pyanaconda/storage/partitioning.py
@@ -104,6 +104,17 @@ def _schedulePartitions(storage, disks):
     if len(all_free) > 1:
         free += all_free[1].getSize()
 
+    # The boot disk must be set at this point. See if any platform-specific
+    # stage1 device we might allocate already exists on the boot disk.
+    stage1_device = None
+    for device in storage.devices:
+        if storage.bootloader.stage1_drive not in device.disks:
+            continue
+
+        if storage.bootloader._is_valid_stage1_device(device):
+            stage1_device = device
+            break
+
     #
     # First pass is for partitions only. We'll do LVs later.
     #
@@ -120,27 +131,17 @@ def _schedulePartitions(storage, disks):
             else:
                 request.fstype = storage.defaultFSType
 
-        elif request.fstype == "prepboot" and storage.bootLoaderDevice:
-            # there should never be a need for more than one of these
-            # partitions, so skip them.
-            log.info("skipping unneeded stage1 prepboot request")
-            log.debug(request)
-            log.debug(storage.bootLoaderDevice)
-            continue
-        elif request.fstype == "efi" and storage.bootLoaderDevice:
-            # there should never be a need for more than one of these
-            # partitions, so skip them.
-            log.info("skipping unneeded stage1 efi request")
-            log.debug(request)
-            # Set the mountpoint for the existing EFI boot partition
-            storage.bootLoaderDevice.format.mountpoint = "/boot/efi"
-            log.debug(storage.bootLoaderDevice)
-            continue
-        elif request.fstype == "biosboot" and storage.bootLoaderDevice:
-            log.info("skipping unneeded stage1 biosboot request")
-            log.debug(request)
-            log.debug(storage.bootLoaderDevice)
-            continue
+        elif request.fstype in ("prepboot", "efi", "biosboot") and stage1_device:
+             # there should never be a need for more than one of these
+             # partitions, so skip them.
+             log.info("skipping unneeded stage1 %s request" % request.fstype)
+             log.debug(request)
+
+            if request.fstype == "efi":
+                # Set the mountpoint for the existing EFI boot partition
+                stage1_device.format.mountpoint = "/boot/efi"
+
+            log.debug(stage1_device)
 
         # This is a little unfortunate but let the backend dictate the rootfstype
         # so that things like live installs can do the right thing
@@ -244,121 +245,75 @@ def scheduleShrinkActions(storage):
         if device.targetSize != size:
             device.format.targetSize = device.targetSize
 
-def doAutoPartition(anaconda):
-    log.debug("doAutoPartition(%s)" % anaconda)
-    log.debug("doAutoPart: %s" % anaconda.storage.doAutoPart)
-    log.debug("encryptedAutoPart: %s" % anaconda.storage.encryptedAutoPart)
-    log.debug("lvmAutoPart: %s" % anaconda.storage.lvmAutoPart)
-    log.debug("clearPartType: %s" % anaconda.storage.config.clearPartType)
-    log.debug("clearPartDisks: %s" % anaconda.storage.config.clearPartDisks)
-    log.debug("autoPartitionRequests:\n%s" % "".join([str(p) for p in anaconda.storage.autoPartitionRequests]))
-    log.debug("storage.disks: %s" % [d.name for d in anaconda.storage.disks])
-    log.debug("storage.partitioned: %s" % [d.name for d in anaconda.storage.partitioned])
-    log.debug("all names: %s" % [d.name for d in anaconda.storage.devices])
-    if anaconda.dir == DISPATCH_BACK:
-        return
+def doAutoPartition(storage, data, errorcb=None, warningcb=None):
+    log.debug("doAutoPart: %s" % storage.doAutoPart)
+    log.debug("encryptedAutoPart: %s" % storage.encryptedAutoPart)
+    log.debug("lvmAutoPart: %s" % storage.lvmAutoPart)
+    log.debug("clearPartType: %s" % storage.config.clearPartType)
+    log.debug("clearPartDisks: %s" % storage.config.clearPartDisks)
+    log.debug("autoPartitionRequests:\n%s" % "".join([str(p) for p in storage.autoPartitionRequests]))
+    log.debug("storage.disks: %s" % [d.name for d in storage.disks])
+    log.debug("storage.partitioned: %s" % [d.name for d in storage.partitioned])
+    log.debug("all names: %s" % [d.name for d in storage.devices])
+    log.debug("boot disk: %s" % getattr(storage.bootDisk, "name", None))
 
     disks = []
     devs = []
 
-    if anaconda.storage.doAutoPart:
-        scheduleShrinkActions(anaconda.storage)
-        clearPartitions(anaconda.storage, bootloader=anaconda.bootloader)
+    if errorcb is None:
+        errorcb = lambda e: True
+    if warningcb is None:
+        warningcb = lambda e: True
+
+    if storage.doAutoPart:
+        scheduleShrinkActions(storage)
+        clearPartitions(storage)
         # update the bootloader's drive list to add disks which have their
         # whole disk format replaced by a disklabel. Make sure to keep any
         # previous boot order selection from clearpart_gui or kickstart
         anaconda.bootloader.clear_drive_list()
 
-        disks = _getCandidateDisks(anaconda.storage)
-        devs = _schedulePVs(anaconda.storage, disks)
+        disks = _getCandidateDisks(storage)
+        devs = _schedulePVs(storage, disks)
         log.debug("candidate disks: %s" % disks)
         log.debug("devs: %s" % devs)
 
         if disks == []:
-            if anaconda.ksdata:
-                msg = _("Could not find enough free space for automatic "
-                        "partitioning.  Press 'OK' to exit the installer.")
-            else:
-                msg = _("Could not find enough free space for automatic "
-                        "partitioning, please use another partitioning method.")
-
-            anaconda.intf.messageWindow(_("Error Partitioning"), msg,
-                                        custom_icon='error')
-
-            if anaconda.ksdata:
-                sys.exit(0)
+            raise PartitioningError("not enough free space")
 
-            anaconda.storage.reset()
-            return DISPATCH_BACK
-
-        _schedulePartitions(anaconda.storage, disks)
+        _schedulePartitions(storage, disks)
 
     # run the autopart function to allocate and grow partitions
     try:
-        doPartitioning(anaconda.storage, bootloader=anaconda.bootloader)
+        doPartitioning(storage)
 
-        if anaconda.storage.doAutoPart:
-            _scheduleLVs(anaconda.storage, devs)
+        if storage.doAutoPart:
+            _scheduleLVs(storage, devs)
 
         # grow LVs
-        growLVM(anaconda.storage)
-    except PartitioningWarning as msg:
-        if not anaconda.ksdata:
-            anaconda.intf.messageWindow(_("Warnings During Automatic "
-                                          "Partitioning"),
-                           _("Following warnings occurred during automatic "
-                           "partitioning:\n\n%s") % (msg,),
-                           custom_icon='warning')
-        else:
-            log.warning(msg)
-    except PartitioningError as msg:
-        # restore drives to original state
-        anaconda.storage.reset()
-
-        extra = ""
-        if anaconda.ksdata:
-            extra = _("\n\nPress 'OK' to exit the installer.")
-        else:
-            anaconda.dispatch.request_steps_gently("partition")
-        anaconda.intf.messageWindow(_("Error Partitioning"),
-               _("Could not allocate requested partitions: \n\n"
-                 "%(msg)s.%(extra)s") % {'msg': msg, 'extra': extra},
-               custom_icon='error')
-
-        if anaconda.ksdata:
-            sys.exit(0)
-        else:
-            return DISPATCH_BACK
+        growLVM(storage)
+    except PartitioningWarning as e:
+        log.warning(str(e))
+        warningcb(e)
+    except PartitioningError as e:
+        log.error(str(e))
+        errorcb(e)
+        storage.reset()
+        raise
+
+    storage.setUpBootLoader()
 
     # now do a full check of the requests
-    (errors, warnings) = anaconda.storage.sanityCheck()
-    if warnings:
-        for warning in warnings:
-            log.warning(warning)
+    (errors, warnings) = storage.sanityCheck()
+    for error in errors:
+        log.error(error)
+    for warning in warnings:
+        log.warning(warning)
     if errors:
-        errortxt = "\n".join(errors)
-        if anaconda.ksdata:
-            extra = _("\n\nPress 'OK' to exit the installer.")
-        else:
-            extra = _("\n\nPress 'OK' to choose a different partitioning option.")
-
-        anaconda.intf.messageWindow(_("Automatic Partitioning Errors"),
-                           _("The following errors occurred with your "
-                             "partitioning:\n\n%(errortxt)s\n\n"
-                             "This can happen if there is not enough "
-                             "space on your hard drive(s) for the "
-                             "installation. %(extra)s")
-                           % {'errortxt': errortxt, 'extra': extra},
-                           custom_icon='error')
-        #
-        # XXX if in kickstart we reboot
-        #
-        if anaconda.ksdata:
-            anaconda.intf.messageWindow(_("Unrecoverable Error"),
-                               _("The system will now reboot."))
-            sys.exit(0)
-        anaconda.storage.reset()
-        return DISPATCH_BACK
+        exn = PartitioningError("\n".join(errors))
+        errorcb(exn)
+        storage.reset()
+        raise exn
 
 def shouldClear(device, clearPartType, clearPartDisks=None):
     if clearPartType not in [CLEARPART_TYPE_LINUX, CLEARPART_TYPE_ALL]:
@@ -409,7 +364,7 @@ def shouldClear(device, clearPartType, clearPartDisks=None):
 
     return True
 
-def clearPartitions(storage, bootloader=None):
+def clearPartitions(storage):
     """ Clear partitions and dependent devices from disks.
 
         Arguments:
@@ -418,7 +373,7 @@ def clearPartitions(storage, bootloader=None):
 
         Keyword arguments:
 
-            bootloader -- a BootLoader instance
+            None
 
         NOTES:
 
@@ -486,11 +441,12 @@ def clearPartitions(storage, bootloader=None):
 
     # make sure that the the boot device has the correct disklabel type if
     # we're going to completely clear it.
+    boot_disk = storage.bootDisk
     for disk in storage.partitioned:
-        if not bootloader or not bootloader.stage1_drive:
+        if not boot_disk:
             break
 
-        if disk != bootloader.stage1_drive:
+        if disk != boot_disk:
             continue
 
         if storage.config.clearPartType != CLEARPART_TYPE_ALL or \
@@ -926,7 +882,7 @@ def updateExtendedPartitions(storage, disks):
         # moment to simplify things
         storage.devicetree._addDevice(device)
 
-def doPartitioning(storage, bootloader=None):
+def doPartitioning(storage):
     """ Allocate and grow partitions.
 
         When this function returns without error, all PartitionDevice
@@ -941,7 +897,7 @@ def doPartitioning(storage, bootloader=None):
 
         Keyword/Optional Arguments:
 
-            bootloader - BootLoader instance
+            None
 
     """
     if not hasattr(storage.platform, "diskLabelTypes"):
@@ -973,14 +929,6 @@ def doPartitioning(storage, bootloader=None):
             # start over with flexible-size requests
             part.req_size = part.req_base_size
 
-    try:
-        storage.bootDevice.req_bootable = True
-    except AttributeError:
-        # there's no stage2 device. hopefully it's temporary.
-        pass
-
-    removeNewPartitions(disks, partitions)
-
     if storage.platform.weight(fstype="biosboot") > 0:
         # add a request for a bios boot partition on every disk that contains a
         # gpt disklabel if we're on a bios platform.
@@ -1017,10 +965,16 @@ def doPartitioning(storage, bootloader=None):
             storage.createDevice(part)
             partitions.append(part)
 
+    try:
+        storage.bootDevice.req_bootable = True
+    except AttributeError:
+        # there's no stage2 device. hopefully it's temporary.
+        pass
+
+    removeNewPartitions(disks, partitions)
     free = getFreeRegions(disks)
     try:
-        allocatePartitions(storage, disks, partitions, free,
-                           bootloader=bootloader)
+        allocatePartitions(storage, disks, partitions, free)
         growPartitions(disks, partitions, free)
     finally:
         # The number and thus the name of partitions may have changed now,
@@ -1034,11 +988,7 @@ def doPartitioning(storage, bootloader=None):
 
         updateExtendedPartitions(storage, disks)
 
-        # make sure the stage1_device gets updated
-        if storage.anaconda:
-            storage.anaconda.bootloader.stage1_device = None
-
-def allocatePartitions(storage, disks, partitions, freespace, bootloader=None):
+def allocatePartitions(storage, disks, partitions, freespace):
     """ Allocate partitions based on requested features.
 
         Non-existing partitions are sorted according to their requested
@@ -1088,14 +1038,10 @@ def allocatePartitions(storage, disks, partitions, freespace, bootloader=None):
 
         # sort the disks, making sure the boot disk is first
         req_disks.sort(key=lambda d: d.name, cmp=storage.compareDisks)
-        boot_index = None
         for disk in req_disks:
-            if bootloader and disk == bootloader.stage1_drive:
+            if storage.bootDisk and disk == storage.bootDisk:
                 boot_index = req_disks.index(disk)
-
-        if boot_index is not None and len(req_disks) > 1:
-            boot_disk = req_disks.pop(boot_index)
-            req_disks.insert(0, boot_disk)
+                req_disks.insert(0, req_disks.pop(boot_index))
 
         boot = _part.req_base_weight > 1000
 
diff --git a/pyanaconda/upgrade.py b/pyanaconda/upgrade.py
index 5d9fe4f..d5dd7a4 100644
--- a/pyanaconda/upgrade.py
+++ b/pyanaconda/upgrade.py
@@ -168,7 +168,7 @@ def upgradeMountFilesystems(anaconda):
     # mount everything and turn on swap
 
     try:
-        mountExistingSystem(anaconda, anaconda.upgradeRoot[0], allowDirty = 0)
+        mountExistingSystem(anaconda.storage.fsset, anaconda.upgradeRoot[0], allowDirty = 0)
     except ValueError as e:
         log.error("Error mounting filesystem: %s" % e)
         anaconda.intf.messageWindow(_("Mount failed"),
-- 
1.7.8.4

_______________________________________________
Anaconda-devel-list mailing list
Anaconda-devel-list@xxxxxxxxxx
https://www.redhat.com/mailman/listinfo/anaconda-devel-list


[Index of Archives]     [Kickstart]     [Fedora Users]     [Fedora Legacy List]     [Fedora Maintainers]     [Fedora Desktop]     [Fedora SELinux]     [Big List of Linux Books]     [Yosemite News]     [Yosemite Photos]     [KDE Users]     [Fedora Tools]
  Powered by Linux