From c016e6078b9563a7514d975f1d88e79eb952c25c Mon Sep 17 00:00:00 2001 From: Chris Lumens Date: Wed, 6 Aug 2014 11:09:44 -0400 Subject: [PATCH] Fix problems with the hdiso method (#1274855) (1) Be more lenient when it comes to deciding if the hdiso method has changed. The user can specify "/dev/sda1" or "sda", and they can give the file name with or without a leading slash. anaconda internally follows different rules, which leads to situations where we compare "/dev/sda1" to "sda1" and device things have changed. Of course, they haven't. (2) The user may also specify the HDISO source via inst.repo=hd:/dev/disk/by-uuid which we completely fail to handle. Fix that. (3) If the user gives us a bad value for inst.repo= (like an invalid path, perhaps from a typo), handle it in the UI with an error instead of raising a traceback that doesn't make much sense. (4) Fix two problems caused by cherry-picked patches. (5) The big one - if you boot up via some method that also involves mounting the install.img from an HDISO source, the install.img will keep all our mount points tied up. There's not really any way to fix this because there's no way to unmount the install.img, and there's nowhere to move it to that doesn't involve eating up more memory. Thus, just prevent people from changing the source when in this situation and slap a tooltip up explaining why. Resolves: rhbz#1274855 (cherry picked from commit 77c1fc4e271e92f08cb14df67c04883aa2063c2b) --- pyanaconda/packaging/__init__.py | 4 ++++ pyanaconda/packaging/yumpayload.py | 6 +++++- pyanaconda/ui/gui/spokes/source.py | 32 +++++++++++++++++++++--------- pyanaconda/ui/tui/spokes/source.py | 10 ++++++++-- 4 files changed, 40 insertions(+), 12 deletions(-) diff --git a/pyanaconda/packaging/__init__.py b/pyanaconda/packaging/__init__.py index 5da1b22094a..62d52c0f15a 100644 --- a/pyanaconda/packaging/__init__.py +++ b/pyanaconda/packaging/__init__.py @@ -878,8 +878,12 @@ def _setupInstallDevice(self, storage, checkmount): needmount = False # We don't setup an install_device here # because we can't tear it down + isodevice = storage.devicetree.resolveDevice(devspec) if needmount: + if not isodevice: + raise PayloadSetupError("device for HDISO install %s does not exist" % devspec) + self._setupMedia(isodevice) url = "file://" + INSTALL_TREE self.install_device = isodevice diff --git a/pyanaconda/packaging/yumpayload.py b/pyanaconda/packaging/yumpayload.py index 8474992b8e2..a5228ce97ac 100644 --- a/pyanaconda/packaging/yumpayload.py +++ b/pyanaconda/packaging/yumpayload.py @@ -516,7 +516,11 @@ def updateBaseRepo(self, fallback=True, root=None, checkmount=True): retrieval fails. """ log.info("configuring base repo") - url, mirrorlist, sslverify = self._setupInstallDevice(self.storage, checkmount) + + try: + url, mirrorlist, sslverify = self._setupInstallDevice(self.storage, checkmount) + except PayloadSetupError: + self.data.method.method = None releasever = None method = self.data.method diff --git a/pyanaconda/ui/gui/spokes/source.py b/pyanaconda/ui/gui/spokes/source.py index 6428fc4e7a3..e9cad81bdd4 100644 --- a/pyanaconda/ui/gui/spokes/source.py +++ b/pyanaconda/ui/gui/spokes/source.py @@ -47,7 +47,7 @@ from pyanaconda import constants from pyanaconda import nm -from blivet.util import get_mount_paths +from blivet.util import get_mount_device, get_mount_paths __all__ = ["SourceSpoke"] @@ -300,7 +300,7 @@ class IsoChooser(GUIObject): def __init__(self, data): GUIObject.__init__(self, data) - self._chooser = self.builder.get_object("isoChooserDialog") + self._chooser = self.builder.get_object("isoChooser") # pylint: disable=arguments-differ def refresh(self, currentFile=""): @@ -409,8 +409,8 @@ def _method_changed(self): # The / gets stripped off by payload.ISOImage self.data.method.dir = "/" + self._currentIsoFile if (old_source.method == "harddrive" and - old_source.partition == self.data.method.partition and - old_source.dir == self.data.method.dir): + self.storage.devicetree.resolveDevice(old_source.partition) == part and + old_source.dir in [self._currentIsoFile, "/" + self._currentIsoFile]): return False # Make sure anaconda doesn't touch this device. @@ -744,6 +744,10 @@ def refresh(self): added = False active = 0 idx = 0 + + if self.data.method.method == "harddrive": + methodDev = self.storage.devicetree.resolveDevice(self.data.method.partition) + for dev in potentialHdisoSources(self.storage.devicetree): # path model size format type uuid of format dev_info = { "model" : self._sanitize_model(dev.disk.model), @@ -759,7 +763,7 @@ def refresh(self): dev_info["label"] = "\n" + dev_info["label"] store.append([dev, "%(model)s %(path)s (%(size)s MB) %(format)s %(label)s" % dev_info]) - if self.data.method.method == "harddrive" and self.data.method.partition in [dev.path, dev.name]: + if self.data.method.method == "harddrive" and dev == methodDev: active = idx added = True idx += 1 @@ -845,10 +849,20 @@ def refresh(self): # Setup the addon repos self._reset_repoStore() - # Then, some widgets get enabled/disabled/greyed out depending on - # how others are set up. We can use the signal handlers to handle - # that condition here too. - self.on_protocol_changed(self._protocolComboBox) + if self.data.method.method == "harddrive" and \ + get_mount_device(constants.DRACUT_ISODIR) == get_mount_device(constants.DRACUT_REPODIR): + # If the stage2 image is mounted from an HDISO source, there's really + # no way we can tear down that source to allow the user to change it. + # Thus, this portion of the spoke should be insensitive. + for widget in [self._autodetectButton, self._autodetectBox, self._isoButton, + self._isoBox, self._networkButton, self._networkBox]: + widget.set_sensitive(False) + widget.set_tooltip_text(_("The installation source is in use by the installer and cannot be changed.")) + else: + # Then, some widgets get enabled/disabled/greyed out depending on + # how others are set up. We can use the signal handlers to handle + # that condition here too. + self.on_protocol_changed(self._protocolComboBox) if not nm.nm_is_connected(): self._networkButton.set_sensitive(False) diff --git a/pyanaconda/ui/tui/spokes/source.py b/pyanaconda/ui/tui/spokes/source.py index 1b62ef81a53..edb8587dea3 100644 --- a/pyanaconda/ui/tui/spokes/source.py +++ b/pyanaconda/ui/tui/spokes/source.py @@ -32,12 +32,12 @@ from pyanaconda.constants import THREAD_SOURCE_WATCHER, THREAD_PAYLOAD from pyanaconda.constants import THREAD_STORAGE_WATCHER -from pyanaconda.constants import THREAD_CHECK_SOFTWARE, ISO_DIR, DRACUT_ISODIR +from pyanaconda.constants import THREAD_CHECK_SOFTWARE, ISO_DIR, DRACUT_ISODIR, DRACUT_REPODIR from pyanaconda.constants_text import INPUT_PROCESSED from pyanaconda.ui.helpers import SourceSwitchHandler -from blivet.util import get_mount_paths +from blivet.util import get_mount_device, get_mount_paths import re import os @@ -143,6 +143,12 @@ def refresh(self, args=None): threadMgr.wait(THREAD_PAYLOAD) + if self.data.method.method == "harddrive" and \ + get_mount_device(DRACUT_ISODIR) == get_mount_device(DRACUT_REPODIR): + message = _("The installation source is in use by the installer and cannot be changed.") + self._window += [TextWidget(message), ""] + return True + _methods = [_("CD/DVD"), _("local ISO file"), _("Network")] if args == 3: text = [TextWidget(_(p)) for p in self._protocols]