FAQ Search Today's Posts Mark Forums Read
» Video Reviews

» Linux Archive

Linux-archive is a website aiming to archive linux email lists and to make them easily accessible for linux users/developers.


» Sponsor

» Partners

» Sponsor

Go Back   Linux Archive > Debian > Debian Development

 
 
LinkBack Thread Tools
 
Old 05-02-2011, 10:27 AM
Ales Kozumplik
 
Default Turn sshd setup, kicstart execution and the rescue mode into dispatch steps.

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("in stbootloader")
+ 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("cleardiskss el")
+ 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.timezo ne, 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.

"
"Press <return> to get a shell. If you would like to "
"make your system the root environment, run the command:

"
@@ -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.

"
"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.
"))
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@redhat.com
https://www.redhat.com/mailman/listinfo/anaconda-devel-list
 
Old 05-03-2011, 08:52 AM
Ales Kozumplik
 
Default Turn sshd setup, kicstart execution and the rescue mode into dispatch steps.

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 | 26 ++++--
pyanaconda/rescue.py | 53 ++++++------
pyanaconda/sshd.py | 89 ++++++++++++++++++++
9 files changed, 191 insertions(+), 166 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..8e058bb 100644
--- a/pyanaconda/kickstart.py
+++ b/pyanaconda/kickstart.py
@@ -1203,6 +1203,14 @@ class AnacondaKSHandler(superclass):
"configuration file:

%s") % e)
sys.exit(1)

+ def setSteps(self):
+ for n in self.skipSteps:
+ self.anaconda.dispatch.skipStep(n)
+ for n in self.permanentSkipSteps:
+ self.anaconda.dispatch.skipStep(n, permanent=1)
+ for n in self.showSteps:
+ self.anaconda.dispatch.skipStep(n, skip = 0)
+
class AnacondaPreParser(KickstartParser):
# A subclass of KickstartParser that only looks for %pre scripts and
# sets them up to be run. All other scripts and commands are ignored.
@@ -1266,6 +1274,16 @@ 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()
+ # executing kickstart commands dynamically disables or enables certain
+ # dispatch steps, process the lists now.
+ anaconda.ksdata.setSteps()
+
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 +1494,7 @@ def setSteps(anaconda):
else:
anaconda.instClass.setSteps(anaconda)
dispatch.skipStep("findrootparts")
+ dispatch.skipStep("kickstart", skip = 0)

dispatch.skipStep("betanag")
dispatch.skipStep("network")
@@ -1509,13 +1528,6 @@ def setSteps(anaconda):
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)
-
# 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
# everything that would be provided by a missing section now and error
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.

"
"Press <return> to get a shell. If you would like to "
"make your system the root environment, run the command:

"
@@ -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.

"
"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.
"))
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@redhat.com
https://www.redhat.com/mailman/listinfo/anaconda-devel-list
 

Thread Tools




All times are GMT. The time now is 10:20 PM.

VBulletin, Copyright ©2000 - 2014, Jelsoft Enterprises Ltd.
Content Relevant URLs by vBSEO ©2007, Crawlability, Inc.
Copyright 2007 - 2008, www.linux-archive.org