def input(self, args, key): """Override any input so we can launch rescue mode.""" try: keyid = int(key) - 1 except ValueError: pass if keyid == 3: # quit/reboot d = YesNoDialog(self.app, _(self.app.quit_message)) self.app.switch_screen_modal(d) if d.answer: iutil.execWithRedirect("systemctl", ["--no-wall", "reboot"]) elif keyid == 2: # skip to/run shell run_shell() elif (keyid == 1 or keyid == 0): # user chose 0 (continue/rw-mount) or 1 (ro-mount) # decrypt any luks devices self._unlock_devices() # this sleep may look pointless, but it seems necessary, in # order for some task to complete; otherwise no existing # installations are discovered. IOW, this is a hack. time.sleep(2) # attempt to find previous installations roots = findExistingInstallations(self.storage.devicetree) if len(roots) == 1: self._root = roots[0] elif len(roots) > 1: # have to prompt user for which root to mount rootspoke = RootSpoke(self.app, self.data, self.storage, self.payload, self.instclass, roots) self.app.switch_screen_modal(rootspoke) self._root = rootspoke.root # if only one root detected, or user has chosen which root # to mount, go ahead and do that newspoke = RescueMountSpoke(self.app, self.data, self.storage, self.payload, self.instclass, keyid, self._root) self.app.switch_screen_modal(newspoke) self.close() else: # user entered some invalid number choice return key return INPUT_PROCESSED
def doRescue(intf, rescue_mount, ksdata): import blivet # XXX: hook the exception handler wrapper that turns off snack first orig_hook = sys.excepthook sys.excepthook = lambda ty, val, tb: _exception_handler_wrapper(orig_hook, intf.screen, ty, val, tb) for f in ["services", "protocols", "group", "joe", "man.config", "nsswitch.conf", "selinux", "mke2fs.conf"]: try: os.symlink('/mnt/runtime/etc/' + f, '/etc/' + f) except OSError: pass # Early shell access with no disk access attempts if not rescue_mount: # the %post should be responsible for mounting all needed file systems # NOTE: 1st script must be bash or simple python as nothing else might be available in the rescue image if flags.automatedInstall and ksdata.scripts: runPostScripts(ksdata.scripts) else: runShell() sys.exit(0) if flags.automatedInstall: readOnly = ksdata.rescue.romount else: # prompt to see if we should try and find root filesystem and mount # everything in /etc/fstab on that root while True: rc = ButtonChoiceWindow(intf.screen, _("Rescue"), _("The rescue environment will now attempt to find your " "Linux installation and mount it under the directory " "%s. You can then make any changes required to your " "system. If you want to proceed with this step choose " "'Continue'. You can also choose to mount your file systems " "read-only instead of read-write by choosing 'Read-Only'. " "\n\n" "If for some reason this process fails you can choose 'Skip' " "and this step will be skipped and you will go directly to a " "command shell.\n\n") % (iutil.getSysroot(),), [_("Continue"), _("Read-Only"), _("Skip")]) if rc == _("Skip").lower(): runShell(intf.screen) sys.exit(0) else: readOnly = rc == _("Read-Only").lower() break sto = blivet.Blivet(ksdata=ksdata) storageInitialize(sto, ksdata, []) _unlock_devices(intf, sto) roots = osinstall.findExistingInstallations(sto.devicetree) if not roots: root = None elif len(roots) == 1: root = roots[0] else: height = min(len(roots), 12) if height == 12: scroll = 1 else: scroll = 0 lst = [] for root in roots: lst.append("%s" % root.name) (button, choice) = \ ListboxChoiceWindow(intf.screen, _("System to Rescue"), _("Which device holds the root partition " "of your installation?"), lst, [_("OK"), _("Exit")], width=30, scroll=scroll, height=height, help="multipleroot") if button == _("Exit").lower(): root = None else: root = roots[choice] rootmounted = False if root: try: if not flags.imageInstall: msg = _("The system will reboot automatically when you exit " "from the shell.") else: msg = _("Run %s to unmount the system " "when you are finished.") % ANACONDA_CLEANUP mountExistingSystem(sto.fsset, root.device, readOnly=readOnly) if flags.automatedInstall: log.info("System has been mounted under: %s", iutil.getSysroot()) else: ButtonChoiceWindow(intf.screen, _("Rescue"), _("Your system has been mounted under %(rootPath)s.\n\n" "Press <return> to get a shell. If you would like to " "make your system the root environment, run the command:\n\n" "\tchroot %(rootPath)s\n\n%(msg)s") % {'rootPath': iutil.getSysroot(), 'msg': msg}, [_("OK")]) rootmounted = True # now turn on swap if not readOnly: try: sto.turnOnSwap() except StorageError: log.error("Error enabling swap") # and selinux too if flags.selinux: # we have to catch the possible exception # because we support read-only mounting try: fd = open("%s/.autorelabel" % iutil.getSysroot(), "w+") fd.close() except IOError: log.warning("cannot touch /.autorelabel") # set a library path to use mounted fs libdirs = os.environ.get("LD_LIBRARY_PATH", "").split(":") mounted = ["/mnt/sysimage%s" % mdir for mdir in libdirs] iutil.setenv("LD_LIBRARY_PATH", ":".join(libdirs + mounted)) # find groff data dir gversion = None try: glst = os.listdir("/mnt/sysimage/usr/share/groff") except OSError: pass else: # find a directory which is a numeral, its where # data files are for gdir in glst: if re.match(r'\d[.\d]+\d$', gdir): gversion = gdir break if gversion is not None: gpath = "/mnt/sysimage/usr/share/groff/"+gversion iutil.setenv("GROFF_FONT_PATH", gpath + '/font') iutil.setenv("GROFF_TMAC_PATH", "%s:/mnt/sysimage/usr/share/groff/site-tmac" % (gpath + '/tmac',)) # do we have bash? try: if os.access("/usr/bin/bash", os.R_OK): os.symlink("/usr/bin/bash", "/bin/bash") except OSError: pass except (ValueError, LookupError, SyntaxError, NameError): raise except Exception as e: # pylint: disable=broad-except log.error("doRescue caught exception: %s", e) if flags.automatedInstall: log.error("An error occurred trying to mount some or all of your system") else: if not flags.imageInstall: msg = _("The system will reboot automatically when you " "exit from the shell.") else: msg = _("Run %s to unmount the system " "when you are finished.") % ANACONDA_CLEANUP ButtonChoiceWindow(intf.screen, _("Rescue"), _("An error occurred trying to mount some or all of your " "system. Some of it may be mounted under %s.\n\n" "Press <return> to get a shell.") % iutil.getSysroot() + msg, [_("OK")]) else: if flags.automatedInstall and ksdata.reboot.action in [KS_REBOOT, KS_SHUTDOWN]: log.info("No Linux partitions found") intf.screen.finish() print(_("You don't have any Linux partitions. Rebooting.\n")) sys.exit(0) else: if not flags.imageInstall: msg = _(" The system will reboot automatically when you exit " "from the shell.") else: msg = "" ButtonChoiceWindow(intf.screen, _("Rescue Mode"), _("You don't have any Linux partitions. Press " "return to get a shell.%s") % msg, [_("OK")], width=50) msgStr = "" if rootmounted and not readOnly: sto.makeMtab() try: makeResolvConf(iutil.getSysroot()) except (OSError, IOError) as e: log.error("error making a resolv.conf: %s", e) msgStr = _("Your system is mounted under the %s directory.") % (iutil.getSysroot(),) ButtonChoiceWindow(intf.screen, _("Rescue"), msgStr, [_("OK")]) # we do not need ncurses anymore, shut them down intf.shutdown() #create /etc/fstab in ramdisk, so it is easier to work with RO mounted filesystems makeFStab() # run %post if we've mounted everything if rootmounted and not readOnly and flags.automatedInstall: runPostScripts(ksdata.scripts) # start shell if reboot wasn't requested if not flags.automatedInstall or not ksdata.reboot.action in [KS_REBOOT, KS_SHUTDOWN]: runShell(msg=msgStr) sys.exit(0)