Involves: - making the RescueInterface compatible with the gui and tui interfaces (so they all can be instantiated in the same way) - the rescue step is disabled by default and never returns. It is enabled if kickstart/command line requires it. - kickstart step is disabled by default, enabled only if a kickstart file was provided. - all the sshd methods (setting user accounts, generating keys) were moved to a separete file, 'sshd.py' - the order of actions during anaconda startup had to be changed (setupDisplay() was called before we parsed kickstart which tells us whether or not to use vnc) Related: https://fedoraproject.org/wiki/Anaconda/Features/Rework_dispatch --- anaconda | 159 ++++++------------------------------ pyanaconda/__init__.py | 4 + pyanaconda/dispatch.py | 7 ++- pyanaconda/installclass.py | 1 + pyanaconda/installinterfacebase.py | 3 + pyanaconda/iutil.py | 15 ++++ pyanaconda/kickstart.py | 62 +++++++------- pyanaconda/rescue.py | 53 ++++++------ pyanaconda/sshd.py | 89 ++++++++++++++++++++ 9 files changed, 203 insertions(+), 190 deletions(-) create mode 100644 pyanaconda/sshd.py diff --git a/anaconda b/anaconda index a0a8fad..212ce6b 100755 --- a/anaconda +++ b/anaconda @@ -381,101 +381,10 @@ def setupGraphicalLinks(): except: pass -def handleSshPw(anaconda): - if not anaconda.ksdata: - return - - from pyanaconda import users - u = users.Users(anaconda) - - userdata = anaconda.ksdata.sshpw.dataList() - for ud in userdata: - if u.checkUserExists(ud.username, root="/"): - u.setUserPassword(username=ud.username, password=ud.password, - isCrypted=ud.isCrypted, lock=ud.lock) - else: - kwargs = ud.__dict__ - kwargs.update({"root": "/", "mkmailspool": False}) - u.createUser(ud.username, **kwargs) - - del u - -def createSshKey(algorithm, keyfile): - path = '/etc/ssh/%s' % (keyfile,) - argv = ['-q','-t',algorithm,'-f',path,'-C','','-N',''] - if os.access(path, os.R_OK): - return - log.info("running \"%s\"" % (" ".join(['ssh-keygen']+argv),)) - - so = "/tmp/ssh-keygen-%s-stdout.log" % (algorithm,) - se = "/tmp/ssh-keygen-%s-stderr.log" % (algorithm,) - iutil.execWithRedirect('ssh-keygen', argv, stdout=so, stderr=se) - -def fork_orphan(): - """Forks an orphan. - - Returns 1 in the parent and 0 in the orphaned child. - """ - intermediate = os.fork() - if not intermediate: - if os.fork(): - # the intermediate child dies - os._exit(0) - return 0; - # the original process waits for the intermediate child - os.waitpid(intermediate, 0) - return 1 - -def startSsh(): - if iutil.isS390(): - return - - if not fork_orphan(): - os.open("/var/log/lastlog", os.O_RDWR | os.O_CREAT, 0644) - ssh_keys = { - 'rsa1':'ssh_host_key', - 'rsa':'ssh_host_rsa_key', - 'dsa':'ssh_host_dsa_key', - } - for (algorithm, keyfile) in ssh_keys.items(): - createSshKey(algorithm, keyfile) - sshd = iutil.find_program_in_path("sshd") - args = [sshd, "-f", "/etc/ssh/sshd_config.anaconda"] - os.execv(sshd, args) - sys.exit(1) - def startDebugger(signum, frame): import epdb epdb.serve(skip=1) -def runRescueMode(anaconda, opts): - anaconda.rescue = True - - from pyanaconda import rescue - - if anaconda.ksdata: - anaconda.instClass.configure(anaconda) - - # We need an interface before running kickstart execute methods for - # storage. - from snack import SnackScreen - screen = SnackScreen() - anaconda.intf = rescue.RescueInterface(screen) - - anaconda.ksdata.execute() - - anaconda.intf = None - screen.finish() - - # command line 'nomount' overrides kickstart /same for vnc/ - anaconda.rescue_mount = not (opts.rescue_nomount or - anaconda.ksdata.rescue.nomount) - - rescue.runRescue(anaconda) - - # shouldn't get back here - sys.exit(1) - def setupDisplay(anaconda, opts): graphical_failed = 0 vncS = vnc.VncServer() # The vnc Server object. @@ -506,7 +415,9 @@ def setupDisplay(anaconda, opts): anaconda.xdriver = opts.xdriver anaconda.writeXdriver(root="/") - if not opts.rescue: + if anaconda.rescue: + anaconda.displayMode = 'r' + else: if anaconda.ksdata: if anaconda.ksdata.vnc.enabled: flags.usevnc = 1 @@ -629,9 +540,9 @@ def setupDisplay(anaconda, opts): runVNC(vncS) doStartupX11Actions() - # with X running we can initialize the UI interface - anaconda.initInterface() - anaconda.instClass.configure(anaconda) + # with X running we can initialize the UI interface + anaconda.initInterface() + anaconda.instClass.configure(anaconda) def runDogtail(opts): import urlgrabber @@ -707,7 +618,6 @@ if __name__ == "__main__": from pyanaconda import iutil from pyanaconda import vnc - from pyanaconda import users from pyanaconda import kickstart import gettext @@ -805,7 +715,7 @@ if __name__ == "__main__": if opts.targetArch: flags.targetarch = opts.targetArch - # set flags + # set flags flags.dmraid = opts.dmraid flags.mpath = opts.mpath flags.selinux = opts.selinux @@ -825,12 +735,31 @@ if __name__ == "__main__": if opts.debug: flags.debug = True + if opts.rescue: + anaconda.rescue = True + log.info("anaconda called with cmdline = %s" %(sys.argv,)) log.info("Default encoding = %s " % sys.getdefaultencoding()) - setupDisplay(anaconda, opts) os.system("udevadm control --env=ANACONDA=1") + # parse (not execute) kickstart now, the ks commands can affect things like + # UI interface type or enabling rescue mode + if opts.ksfile: + kickstart.preScriptPass(anaconda, opts.ksfile) + anaconda.ksdata = kickstart.parseKickstart(anaconda, opts.ksfile) + if anaconda.ksdata.rescue.rescue: + anaconda.rescue = True + # now start the interface + setupDisplay(anaconda, opts) + # setting the install steps requires interface to be running + if opts.ksfile: + kickstart.setSteps(anaconda) + else: + anaconda.instClass.setSteps(anaconda) + if anaconda.rescue: + anaconda.dispatch.skipStep("rescue", skip=0) + image_count = 0 for image in opts.images: image_spec = image.rsplit(":", 1) @@ -851,26 +780,6 @@ if __name__ == "__main__": if image_count: anaconda.storage.setupDiskImages() - # This is the one place we do all kickstart file parsing. - if opts.ksfile: - kickstart.preScriptPass(anaconda, opts.ksfile) - anaconda.ksdata = kickstart.parseKickstart(anaconda, opts.ksfile) - opts.rescue = opts.rescue or anaconda.ksdata.rescue.rescue - - if flags.sshd: - # we need to have a libuser.conf that points to the installer root for - # sshpw, but after that we start sshd, we need one that points to the - # install target. - luserConf = users.createLuserConf(instPath="") - handleSshPw(anaconda) - startSsh() - del(os.environ["LIBUSER_CONF"]) - - users.createLuserConf(anaconda.rootPath) - - if opts.rescue: - runRescueMode(anaconda, opts) - # comment out the next line to make exceptions non-fatal from pyanaconda.exception import initExceptionHandling anaconda.mehConfig = initExceptionHandling(anaconda) @@ -896,24 +805,10 @@ if __name__ == "__main__": anaconda.keyboard.set(opts.keymap) anaconda.keyboard.activate() - if anaconda.ksdata: - from pyanaconda import storage - storage.storageInitialize(anaconda) - - # Now having initialized storage, we can apply all the other kickstart - # commands. This gives us the ability to check that storage commands - # are correctly formed and refer to actual devices. - anaconda.ksdata.execute() - # set up the headless case if anaconda.isHeadless: anaconda.dispatch.skipStep("keyboard", permanent = 1) - if not anaconda.ksdata: - anaconda.instClass.setSteps(anaconda) - else: - kickstart.setSteps(anaconda) - try: anaconda.dispatch.run() except SystemExit, code: diff --git a/pyanaconda/__init__.py b/pyanaconda/__init__.py index 4a0edba..ccbf07b 100644 --- a/pyanaconda/__init__.py +++ b/pyanaconda/__init__.py @@ -245,6 +245,10 @@ class Anaconda(object): if not os.environ.has_key("LANG"): os.environ["LANG"] = "en_US.UTF-8" + if self.displayMode == 'r': + import rescue + InstallInterface = rescue.RescueInterface + if self.displayMode == 'c': from cmdline import InstallInterface diff --git a/pyanaconda/dispatch.py b/pyanaconda/dispatch.py index c67e96a..6c778bf 100644 --- a/pyanaconda/dispatch.py +++ b/pyanaconda/dispatch.py @@ -40,7 +40,9 @@ from upgrade import restoreTime from upgrade import upgradeSwapSuggestion, upgradeMigrateFind from upgrade import findRootParts, queryUpgradeContinue from installmethod import doMethodComplete -from kickstart import runPostScripts +from kickstart import doKickstart, runPostScripts +from sshd import doSshd +from rescue import doRescue from backend import doPostSelection, doBackendSetup, doBasePackageSelect from backend import doPreInstall, doPostInstall, doInstall @@ -66,6 +68,9 @@ log = logging.getLogger("anaconda") # All install steps take the anaconda object as their sole argument. This # gets passed in when we call the function. installSteps = [ + ("sshd", doSshd), + ("rescue", doRescue), + ("kickstart", doKickstart), ("language", ), ("keyboard", ), ("betanag", betaNagScreen, ), diff --git a/pyanaconda/installclass.py b/pyanaconda/installclass.py index 7b2719f..8092e94 100644 --- a/pyanaconda/installclass.py +++ b/pyanaconda/installclass.py @@ -84,6 +84,7 @@ class BaseInstallClass(object): def setSteps(self, anaconda): dispatch = anaconda.dispatch dispatch.setStepList( + "sshd", "language", "keyboard", "filtertype", diff --git a/pyanaconda/installinterfacebase.py b/pyanaconda/installinterfacebase.py index 898c863..7a65017 100644 --- a/pyanaconda/installinterfacebase.py +++ b/pyanaconda/installinterfacebase.py @@ -33,6 +33,9 @@ class InstallInterfaceBase(object): self._initLabelAnswers = {} self._inconsistentLVMAnswers = {} + def setSteps(self, anaconda): + pass + def messageWindow(self, title, text, type="ok", default = None, custom_buttons=None, custom_icon=None): raise NotImplementedError diff --git a/pyanaconda/iutil.py b/pyanaconda/iutil.py index 139d61d..2387576 100644 --- a/pyanaconda/iutil.py +++ b/pyanaconda/iutil.py @@ -950,3 +950,18 @@ def find_program_in_path(prog, raise_on_error=False): if raise_on_error: raise RuntimeError("Unable to locate a needed executable: '%s'" % prog) return None + +def fork_orphan(): + """Forks an orphan. + + Returns 1 in the parent and 0 in the orphaned child. + """ + intermediate = os.fork() + if not intermediate: + if os.fork(): + # the intermediate child dies + os._exit(0) + return 0; + # the original process waits for the intermediate child + os.waitpid(intermediate, 0) + return 1 diff --git a/pyanaconda/kickstart.py b/pyanaconda/kickstart.py index 0dfecd2..cc7e891 100644 --- a/pyanaconda/kickstart.py +++ b/pyanaconda/kickstart.py @@ -226,7 +226,7 @@ class AutoPart(commands.autopart.F12_AutoPart): self.anaconda.storage.autoPartAddBackupPassphrase = \ self.backuppassphrase - self.anaconda.ksdata.skipSteps.extend(["partition", "zfcpconfig", "parttype"]) + map(self.anaconda.dispatch.skipStep, ["partition", "zfcpconfig", "parttype"]) class AutoStep(commands.autostep.FC3_AutoStep): def execute(self): @@ -249,9 +249,9 @@ class Bootloader(commands.bootloader.F15_Bootloader): self.anaconda.bootloader.update_only = True if location is None: - self.anaconda.ksdata.permanentSkipSteps.append("instbootloader") + self.anaconda.dispatch.skipStep("instbootloader", permanent=1) else: - self.anaconda.ksdata.showSteps.append("bootloader") + self.anaconda.dispatch.skipStep("bootloader", skip=0) if self.appendLine: args = self.appendLine.split() @@ -276,7 +276,8 @@ class Bootloader(commands.bootloader.F15_Bootloader): self.anaconda.bootloader.drive_order = self.driveorder - self.anaconda.ksdata.permanentSkipSteps.extend(["upgbootloader", "bootloader"]) + map(lambda step: self.anaconda.dispatch.skipStep(step, permanent=1), + ["upgbootloader", "bootloader"]) class ClearPart(commands.clearpart.FC3_ClearPart): def parse(self, args): @@ -306,7 +307,7 @@ class ClearPart(commands.clearpart.FC3_ClearPart): self.anaconda.storage.config.reinitializeDisks = self.initAll clearPartitions(self.anaconda.storage) - self.anaconda.ksdata.skipSteps.append("cleardiskssel") + self.anaconda.dispatch.skipStep("cleardiskssel") class Fcoe(commands.fcoe.F13_Fcoe): def parse(self, args): @@ -359,7 +360,7 @@ class IgnoreDisk(commands.ignoredisk.RHEL6_IgnoreDisk): def execute(self): if not self.interactive: - self.anaconda.ksdata.skipSteps.extend(["filter", "filtertype"]) + map(self.anaconda.dispatch.skipStep, ["filter", "filtertype"]) class Iscsi(commands.iscsi.F10_Iscsi): class Login(object): @@ -408,14 +409,14 @@ class Keyboard(commands.keyboard.FC3_Keyboard): def execute(self): self.anaconda.keyboard.set(self.keyboard) self.anaconda.keyboard.beenset = 1 - self.anaconda.ksdata.skipSteps.append("keyboard") + self.anaconda.dispatch.skipStep("keyboard") class Lang(commands.lang.FC3_Lang): def execute(self): self.anaconda.instLanguage.instLang = self.lang self.anaconda.instLanguage.systemLang = self.lang self.anaconda.instLanguage.buildLocale() - self.anaconda.ksdata.skipSteps.append("language") + self.anaconda.dispatch.skipStep("language") class LogVolData(commands.logvol.F15_LogVolData): def execute(self): @@ -457,7 +458,7 @@ class LogVolData(commands.logvol.F15_LogVolData): dev.format.mountpoint = self.mountpoint dev.format.mountopts = self.fsopts - self.anaconda.ksdata.skipSteps.extend(["partition", "zfcpconfig", "parttype"]) + map(self.anaconda.dispatch.skipStep, ["partition", "zfcpconfig", "parttype"]) return # Make sure this LV name is not already used in the requested VG. @@ -540,7 +541,7 @@ class LogVolData(commands.logvol.F15_LogVolData): parents=request) storage.createDevice(luksdev) - self.anaconda.ksdata.skipSteps.extend(["partition", "zfcpconfig", "parttype"]) + map(self.anaconda.dispatch.skipStep, ["partition", "zfcpconfig", "parttype"]) class Logging(commands.logging.FC6_Logging): def execute(self): @@ -768,7 +769,7 @@ class PartitionData(commands.partition.F12_PartData): dev.format.mountpoint = self.mountpoint dev.format.mountopts = self.fsopts - self.anaconda.ksdata.skipSteps.extend(["partition", "zfcpconfig", "parttype"]) + map(self.anaconda.dispatch.skipStep, ["partition", "zfcpconfig", "parttype"]) return # Now get a format to hold a lot of these extra values. @@ -857,11 +858,11 @@ class PartitionData(commands.partition.F12_PartData): parents=request) storage.createDevice(luksdev) - self.anaconda.ksdata.skipSteps.extend(["partition", "zfcpconfig", "parttype"]) + map(self.anaconda.dispatch.skipStep, ["partition", "zfcpconfig", "parttype"]) class Reboot(commands.reboot.FC6_Reboot): def execute(self): - self.anaconda.ksdata.skipSteps.append("complete") + self.anaconda.dispatch.skipStep("complete") class RaidData(commands.raid.F15_RaidData): def execute(self): @@ -910,7 +911,7 @@ class RaidData(commands.raid.F15_RaidData): dev.format.mountpoint = self.mountpoint dev.format.mountopts = self.fsopts - self.anaconda.ksdata.skipSteps.extend(["partition", "zfcpconfig", "parttype"]) + map(self.anaconda.dispatch.skipStep, ["partition", "zfcpconfig", "parttype"]) return # Get a list of all the RAID members. @@ -1003,14 +1004,14 @@ class RaidData(commands.raid.F15_RaidData): parents=request) storage.createDevice(luksdev) - self.anaconda.ksdata.skipSteps.extend(["partition", "zfcpconfig", "parttype"]) + map(self.anaconda.dispatch.skipStep, ["partition", "zfcpconfig", "parttype"]) class RootPw(commands.rootpw.F8_RootPw): def execute(self): self.anaconda.users.rootPassword["password"] = self.password self.anaconda.users.rootPassword["isCrypted"] = self.isCrypted self.anaconda.users.rootPassword["lock"] = self.lock - self.anaconda.ksdata.skipSteps.append("accounts") + self.anaconda.dispatch.skipStep("accounts") class SELinux(commands.selinux.FC3_SELinux): def execute(self): @@ -1030,7 +1031,7 @@ class Timezone(commands.timezone.FC6_Timezone): log.warning("Timezone %s set in kickstart is not valid." % (self.timezone,)) self.anaconda.timezone.setTimezoneInfo(self.timezone, self.isUtc) - self.anaconda.ksdata.skipSteps.append("timezone") + self.anaconda.dispatch.skipStep("timezone") class Upgrade(commands.upgrade.F11_Upgrade): def execute(self): @@ -1151,9 +1152,6 @@ class AnacondaKSHandler(superclass): superclass.__init__(self, commandUpdates=commandMap, dataUpdates=dataMap) self.packages = AnacondaKSPackages() - self.permanentSkipSteps = [] - self.skipSteps = [] - self.showSteps = [] self.anaconda = anaconda self.onPart = {} @@ -1266,6 +1264,13 @@ class AnacondaKSParser(KickstartParser): self.handler.add(retval) return retval +def doKickstart(anaconda): + storage.storageInitialize(anaconda) + # Having initialized storage, we can apply all the other kickstart commands. + # This gives us the ability to check that storage commands are correctly + # formed and refer to actual devices. + anaconda.ksdata.execute() + def preScriptPass(anaconda, file): # The first pass through kickstart file processing - look for %pre scripts # and run them. This must come in a separate pass in case a script @@ -1476,6 +1481,7 @@ def setSteps(anaconda): else: anaconda.instClass.setSteps(anaconda) dispatch.skipStep("findrootparts") + dispatch.skipStep("kickstart", skip = 0) dispatch.skipStep("betanag") dispatch.skipStep("network") @@ -1496,25 +1502,19 @@ def setSteps(anaconda): # If the package section included anything, skip group selection. if ksdata.upgrade.upgrade: - ksdata.skipSteps.extend(["tasksel", "group-selection"]) + map(anaconda.dispatch.skipStep, ["tasksel", "group-selection"]) # Special check for this, since it doesn't make any sense. if ksdata.packages.seen: warnings.warn("Ignoring contents of %packages section due to upgrade.") elif havePackages(ksdata.packages): - ksdata.skipSteps.extend(["tasksel", "group-selection"]) + map(anaconda.dispatch.skipStep, ["tasksel", "group-selection"]) else: if ksdata.packages.seen: - ksdata.skipSteps.extend(["tasksel", "group-selection"]) + map(anaconda.dispatch.skipStep, ["tasksel", "group-selection"]) else: - ksdata.showSteps.extend(["tasksel", "group-selection"]) - - for n in ksdata.skipSteps: - dispatch.skipStep(n) - for n in ksdata.permanentSkipSteps: - dispatch.skipStep(n, permanent=1) - for n in ksdata.showSteps: - dispatch.skipStep(n, skip = 0) + map(lambda step: anaconda.dispatch.skipStep(step, skip=0), + ["tasksel", "group-selection"]) # Text mode doesn't have all the steps that graphical mode does, so we # can't stop and prompt for missing information. Make sure we've got diff --git a/pyanaconda/rescue.py b/pyanaconda/rescue.py index 245a597..69786b5 100644 --- a/pyanaconda/rescue.py +++ b/pyanaconda/rescue.py @@ -126,7 +126,7 @@ class RescueInterface(InstallInterfaceBase): return 1 def shutdown (self): - pass + self.screen.finish() def suspend(self): pass @@ -134,9 +134,13 @@ class RescueInterface(InstallInterfaceBase): def resume(self): pass - def __init__(self, screen): + def run(self, anaconda): + self.anaconda = anaconda + self.anaconda.dispatch.dispatch() + + def __init__(self): InstallInterfaceBase.__init__(self) - self.screen = screen + self.screen = SnackScreen() def makeFStab(instPath = ""): if os.access("/proc/mounts", os.R_OK): @@ -231,7 +235,7 @@ def runShell(screen = None, msg=""): if screen: screen.finish() -def runRescue(anaconda): +def doRescue(anaconda): for file in [ "services", "protocols", "group", "joe", "man.config", "nsswitch.conf", "selinux", "mke2fs.conf" ]: try: @@ -241,16 +245,13 @@ def runRescue(anaconda): # see if they would like networking enabled if not network.hasActiveNetDev(): - screen = SnackScreen() while True: - rc = ButtonChoiceWindow(screen, _("Setup Networking"), + rc = ButtonChoiceWindow(anaconda.intf.screen, _("Setup Networking"), _("Do you want to start the network interfaces on " "this system?"), [_("Yes"), _("No")]) if rc != _("No").lower(): - anaconda.intf = RescueInterface(screen) - if not anaconda.intf.enableNetwork(anaconda): anaconda.intf.messageWindow(_("No Network Available"), _("Unable to activate a networking device. Networking " @@ -262,8 +263,9 @@ def runRescue(anaconda): else: break - anaconda.intf = None - screen.finish() + # shutdown the interface now + anaconda.intf.shutdown() + anaconda.intf = None # Early shell access with no disk access attempts if not anaconda.rescue_mount: @@ -277,8 +279,7 @@ def runRescue(anaconda): sys.exit(0) - screen = SnackScreen() - anaconda.intf = RescueInterface(screen) + anaconda.intf = RescueInterface() if anaconda.ksdata: if anaconda.ksdata.rescue and anaconda.ksdata.rescue.romount: @@ -289,7 +290,7 @@ def runRescue(anaconda): # prompt to see if we should try and find root filesystem and mount # everything in /etc/fstab on that root while True: - rc = ButtonChoiceWindow(screen, _("Rescue"), + rc = ButtonChoiceWindow(anaconda.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 " @@ -304,11 +305,11 @@ def runRescue(anaconda): [_("Continue"), _("Read-Only"), _("Skip"), _("Advanced")] ) if rc == _("Skip").lower(): - runShell(screen) + runShell(anaconda.intf.screen) sys.exit(0) elif rc == _("Advanced").lower(): addDialog = addDriveDialog(anaconda) - addDialog.addDriveDialog(screen) + addDialog.addDriveDialog(anaconda.intf.screen) continue elif rc == _("Read-Only").lower(): readOnly = 1 @@ -340,7 +341,7 @@ def runRescue(anaconda): devList.append("%s - %s" % (device.name, relstr)) (button, choice) = \ - ListboxChoiceWindow(screen, _("System to Rescue"), + ListboxChoiceWindow(anaconda.intf.screen, _("System to Rescue"), _("Which device holds the root partition " "of your installation?"), devList, [ _("OK"), _("Exit") ], width = 30, @@ -371,7 +372,7 @@ def runRescue(anaconda): if anaconda.ksdata: log.error("System had dirty file systems which you chose not to mount") else: - ButtonChoiceWindow(screen, _("Rescue"), + ButtonChoiceWindow(anaconda.intf.screen, _("Rescue"), _("Your system had dirty file systems which you chose not " "to mount. Press return to get a shell from which " "you can fsck and mount your partitions. %s") % msg, @@ -381,7 +382,7 @@ def runRescue(anaconda): if anaconda.ksdata: log.info("System has been mounted under: %s" % anaconda.rootPath) else: - ButtonChoiceWindow(screen, _("Rescue"), + ButtonChoiceWindow(anaconda.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" @@ -441,7 +442,7 @@ def runRescue(anaconda): except (ValueError, LookupError, SyntaxError, NameError): raise except Exception as e: - log.error("runRescue caught exception: %s" % e) + log.error("doRescue caught exception: %s" % e) if anaconda.ksdata: log.error("An error occurred trying to mount some or all of your system") else: @@ -452,7 +453,7 @@ def runRescue(anaconda): msg = _("Run %s to unmount the system " "when you are finished.") % ANACONDA_CLEANUP - ButtonChoiceWindow(screen, _("Rescue"), + ButtonChoiceWindow(anaconda.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.") % anaconda.rootPath + msg, @@ -461,7 +462,7 @@ def runRescue(anaconda): if anaconda.ksdata and \ anaconda.ksdata.reboot.action in [KS_REBOOT, KS_SHUTDOWN]: log.info("No Linux partitions found") - screen.finish() + anaconda.intf.screen.finish() print(_("You don't have any Linux partitions. Rebooting.\n")) sys.exit(0) else: @@ -470,7 +471,7 @@ def runRescue(anaconda): "from the shell.") else: msg = "" - ButtonChoiceWindow(screen, _("Rescue Mode"), + ButtonChoiceWindow(anaconda.intf.screen, _("Rescue Mode"), _("You don't have any Linux partitions. Press " "return to get a shell.%s") % msg, [ _("OK") ], width = 50) @@ -484,11 +485,11 @@ def runRescue(anaconda): except (OSError, IOError) as e: log.error("error making a resolv.conf: %s" %(e,)) msgStr = _("Your system is mounted under the %s directory.") % (anaconda.rootPath,) - ButtonChoiceWindow(screen, _("Rescue"), msgStr, [_("OK")] ) + ButtonChoiceWindow(anaconda.intf.screen, _("Rescue"), msgStr, [_("OK")] ) # we do not need ncurses anymore, shut them down - screen.finish() - + anaconda.intf.shutdown() + #create /etc/fstab in ramdisk, so it is easier to work with RO mounted filesystems makeFStab() @@ -500,6 +501,6 @@ def runRescue(anaconda): # start shell if reboot wasn't requested if not anaconda.ksdata or \ not anaconda.ksdata.reboot.action in [KS_REBOOT, KS_SHUTDOWN]: - runShell(screen, msgStr) + runShell(msg=msgStr) sys.exit(0) diff --git a/pyanaconda/sshd.py b/pyanaconda/sshd.py new file mode 100644 index 0000000..8f1110c --- /dev/null +++ b/pyanaconda/sshd.py @@ -0,0 +1,89 @@ +# sshd.py +# Configuring the sshd daemon from Anaconda. +# +# Copyright (C) 2009 Red Hat, Inc. +# +# This copyrighted material is made available to anyone wishing to use, +# modify, copy, or redistribute it subject to the terms and conditions of +# the GNU General Public License v.2, or (at your option) any later version. +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY expressed or implied, including the implied warranties of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General +# Public License for more details. You should have received a copy of the +# GNU General Public License along with this program; if not, write to the +# Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +# 02110-1301, USA. Any Red Hat trademarks that are incorporated in the +# source code or documentation are not subject to the GNU General Public +# License and may only be used or replicated with the express permission of +# Red Hat, Inc. +# + + +import logging +import os +log = logging.getLogger("anaconda") + +import iutil +import users +from flags import flags + +def createSshKey(algorithm, keyfile): + path = '/etc/ssh/%s' % (keyfile,) + argv = ['-q','-t',algorithm,'-f',path,'-C','','-N',''] + if os.access(path, os.R_OK): + return + log.debug("running \"%s\"" % (" ".join(['ssh-keygen']+argv),)) + + so = "/tmp/ssh-keygen-%s-stdout.log" % (algorithm,) + se = "/tmp/ssh-keygen-%s-stderr.log" % (algorithm,) + iutil.execWithRedirect('ssh-keygen', argv, stdout=so, stderr=se) + +def doSshd(anaconda): + if flags.sshd: + # we need to have a libuser.conf that points to the installer root for + # sshpw, but after that we start sshd, we need one that points to the + # install target. + luserConf = users.createLuserConf(instPath="") + handleSshPw(anaconda) + startSsh() + del(os.environ["LIBUSER_CONF"]) + else: + log.info("sshd: not enabled, skipping.") + + users.createLuserConf(anaconda.rootPath) + +def handleSshPw(anaconda): + if not anaconda.ksdata: + return + + u = users.Users(anaconda) + + userdata = anaconda.ksdata.sshpw.dataList() + for ud in userdata: + if u.checkUserExists(ud.username, root="/"): + u.setUserPassword(username=ud.username, password=ud.password, + isCrypted=ud.isCrypted, lock=ud.lock) + else: + kwargs = ud.__dict__ + kwargs.update({"root": "/", "mkmailspool": False}) + u.createUser(ud.username, **kwargs) + + del u + +def startSsh(): + if iutil.isS390(): + return + + if not iutil.fork_orphan(): + os.open("/var/log/lastlog", os.O_RDWR | os.O_CREAT, 0644) + ssh_keys = { + 'rsa1':'ssh_host_key', + 'rsa':'ssh_host_rsa_key', + 'dsa':'ssh_host_dsa_key', + } + for (algorithm, keyfile) in ssh_keys.items(): + createSshKey(algorithm, keyfile) + sshd = iutil.find_program_in_path("sshd") + args = [sshd, "-f", "/etc/ssh/sshd_config.anaconda"] + os.execv(sshd, args) + sys.exit(1) -- 1.7.3.3 _______________________________________________ Anaconda-devel-list mailing list Anaconda-devel-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/anaconda-devel-list