diff options
author | Mark Hamzy <hamzy@us.ibm.com> | 2009-02-16 14:19:35 -0600 |
---|---|---|
committer | David Cantrell <dcantrell@redhat.com> | 2009-03-02 15:20:53 -1000 |
commit | d00ef216099104c03c400f56fb21e19089df4a7d (patch) | |
tree | 7c413e8735cbd86e7fd1a4204778500c3e347f89 | |
parent | 86eee97f1915c1743d7a2cd91c1b072ccd9bd1e7 (diff) | |
download | anaconda-d00ef216099104c03c400f56fb21e19089df4a7d.tar.gz anaconda-d00ef216099104c03c400f56fb21e19089df4a7d.tar.xz anaconda-d00ef216099104c03c400f56fb21e19089df4a7d.zip |
reIPL support for s390
Signed-off-by: David Cantrell <dcantrell@redhat.com>
-rwxr-xr-x | anaconda | 10 | ||||
-rw-r--r-- | dispatch.py | 3 | ||||
-rw-r--r-- | installclass.py | 1 | ||||
-rw-r--r-- | iutil.py | 181 | ||||
-rw-r--r-- | iw/congrats_gui.py | 32 | ||||
-rw-r--r-- | loader/linuxrc.s390 | 32 | ||||
-rw-r--r-- | loader/loader.c | 55 | ||||
-rw-r--r-- | packages.py | 23 | ||||
-rw-r--r-- | textw/complete_text.py | 32 | ||||
-rw-r--r-- | upgrade.py | 1 |
10 files changed, 305 insertions, 65 deletions
@@ -498,6 +498,8 @@ class Anaconda: self.rescue = False self.updateSrc = None self.mediaDevice = None + self.canReIPL = False + self.reIPLMessage = None # *sigh* we still need to be able to write this out self.xdriver = None @@ -1023,3 +1025,11 @@ if __name__ == "__main__": isys.ejectCdrom(drive) del anaconda.intf + + if iutil.isS390(): + if anaconda.canReIPL: + log.info(_("reipl configuration successful => reboot")) + os.kill(os.getppid(), signal.SIGUSR2) + else: + log.info(_("reipl configuration failed => halt")) + os.kill(os.getppid(), signal.SIGUSR1) diff --git a/dispatch.py b/dispatch.py index b773404dd..22015823a 100644 --- a/dispatch.py +++ b/dispatch.py @@ -48,6 +48,8 @@ from backend import doPostSelection, doBackendSetup, doBasePackageSelect from backend import doPreInstall, doPostInstall, doInstall from backend import writeConfiguration +from packages import doReIPL + import logging log = logging.getLogger("anaconda") @@ -99,6 +101,7 @@ installSteps = [ ("basepkgsel", doBasePackageSelect, ), ("group-selection", ), ("postselection", doPostSelection, ), + ("reipl", doReIPL, ), ("install", ), ("preinstallconfig", doPreInstall, ), ("installpackages", doInstall, ), diff --git a/installclass.py b/installclass.py index bf4f58d9c..832fe7d76 100644 --- a/installclass.py +++ b/installclass.py @@ -113,6 +113,7 @@ class BaseInstallClass(object): "tasksel", "postselection", "confirminstall", + "reipl", "install", "enablefilesystems", "migratefilesystems", @@ -21,12 +21,16 @@ # import os, string, stat, sys +import signal import os.path from errno import * import rhpl import warnings import subprocess from flags import flags +from constants import * +from rhpl.translate import _ +import re import logging log = logging.getLogger("anaconda") @@ -660,3 +664,180 @@ def strip_markup(text): elif not inTag: r += c return r.encode("utf-8") + +def writeReiplMethod(reipl_path, reipl_type): + filename = "%s/reipl_type" % (reipl_path,) + + try: + f = open(filename, "w") + except Exception, e: + message = _("Error: On open, cannot set reIPL method to %s (%s: %s)" % (reipl_type,filename,e,)) + log.warning(message) + raise Exception (message) + + try: + f.write(reipl_type) + f.flush() + except Exception, e: + message = _("Error: On write, cannot set reIPL method to %s (%s: %s)" % (reipl_type,filename,e,)) + log.warning(message) + raise Exception (message) + + try: + f.close() + except Exception, e: + message = _("Error: On close, cannot set reIPL method to %s (%s: %s)" % (reipl_type,filename,e,)) + log.warning(message) + raise Exception (message) + +def reIPLonCCW(iplsubdev, reipl_path): + device = "<unknown>" + + try: + iplbits = re.split ('([0-9]+)', iplsubdev) + if len (iplbits) != 3: + message = _("Error: %s splits into %s but not like we expect" % (iplsubdev,iplbits,)) + log.warning(message) + raise Exception (message) + + device = os.readlink("/sys/block/" + iplbits[0] + "/device").split('/')[-1] + + writeReiplMethod(reipl_path, 'ccw') + + try: + f = open("%s/ccw/device" % (reipl_path,), "w") + f.write(device) + f.close() + except Exception, e: + message = _("Error: Could not set %s as reIPL device (%s)" % (device,e,)) + log.warning(message) + raise Exception (message) + + try: + f = open("%s/ccw/loadparm" % (reipl_path,), "w") + f.write("\n") + f.close() + except Exception, e: + message = _("Error: Could not reset loadparm (%s)" % (e,)) + log.warning(message) + raise Exception (message) + + try: + f = open("%s/ccw/parm" % (reipl_path,), "w") + f.write("\n") + f.close() + except Exception, e: + message = _("Warning: Could not reset parm (%s)" % (e,)) + log.warning(message) + # do NOT raise an exception since this might not exist or not be writable + + except Exception, e: + try: + message = e.args[0] + except: + message = e.__str__ () + return (message, + (_("After shutdown, please perform a manual IPL from DASD device %s to continue " + "installation") % (device,))) + + return None + +def reIPLonFCP(iplsubdev, reipl_path): + fcpvalue = { "device": "<unknown>", "wwpn": "<unknown>", "lun": "<unknown>" } + + try: + iplbits = re.split ('([0-9]+)', iplsubdev) + if len (iplbits) != 3: + message = _("Error: %s splits into %s but not like we expect" % (iplsubdev,iplbits,)) + log.warning(message) + raise Exception (message) + + syspath = "/sys/block/" + iplbits[0] + "/device" + + fcpprops = [ ("hba_id", "device"), ("wwpn", "wwpn"), ("fcp_lun", "lun") ] + + # Read in values to change. + # This way, if we can't set FCP mode, we can tell the user what to manually reboot to. + for (syspath_property, reipl_property) in fcpprops: + try: + f = open(syspath + "/" + syspath_property, "r") + value = f.read().strip() + fcpvalue[reipl_property] = value + f.close() + except Exception, e: + message = _("Error: reading FCP property %s for reIPL (%s)" % (syspath_property,e,)) + log.warning(message) + raise Exception (message) + + writeReiplMethod(reipl_path, 'fcp') + + # Write out necessary parameters. + for (syspath_property, reipl_property) in fcpprops: + try: + f = open("%s/fcp/%s" % (reipl_path, reipl_property,), "w") + f.write(fcpvalue[reipl_property]) + f.close() + except Exception, e: + message = _("Error: writing FCP property %s for reIPL (%s)" % (reipl_property,e,)) + log.warning(message) + raise Exception (message) + + defaultprops = [ ("bootprog", "0"), ("br_lba", "0") ] + + # Write out default parameters. + for (reipl_property, default_value) in defaultprops: + try: + f = open("%s/fcp/%s" % (reipl_path, reipl_property,), "w") + f.write (default_value) + f.close() + except Exception, e: + message = _("Error: writing default FCP property %s for reIPL (%s)" % (reipl_property,e,)) + log.warning(message) + raise Exception (message) + + except Exception, e: + try: + message = e.args[0] + except: + message = e.__str__ () + return (message, + (_("After shutdown, please perform a manual IPL from FCP %(device)s with WWPN %(wwpn)s " + "and LUN %(lun)s to continue installation") % (fcpvalue))) + + return None + + +def reIPL(anaconda, loader_pid): + instruction = _("After shutdown, please perform a manual IPL from the device " + "now containing /boot to continue installation") + + reipl_path = "/sys/firmware/reipl" + + iplfs = anaconda.id.fsset.getEntryByMountPoint("/boot") + if iplfs is None: + iplfs = anaconda.id.fsset.getEntryByMountPoint("/") + + if iplfs is None: + message = _("Could not get information for mount point /boot or /") + log.warning(message) + return (message, instruction) + + try: + ipldev = iplfs.device.device + except: + ipldev = None + + if ipldev is None: + message = _("Error determining mount point type") + log.warning(message) + return (message, instruction) + + message = (_("The mount point /boot or / is on a disk that we are not familiar with"), instruction) + if ipldev.startswith("dasd"): + message = reIPLonCCW(ipldev, reipl_path) + elif ipldev.startswith("sd"): + message = reIPLonFCP(ipldev, reipl_path) + + # the final return is either None if reipl configuration worked (=> reboot), + # or a two-item list with errorMessage and rebootInstr (=> shutdown) + return message diff --git a/iw/congrats_gui.py b/iw/congrats_gui.py index ee16b0e63..b5f0101cf 100644 --- a/iw/congrats_gui.py +++ b/iw/congrats_gui.py @@ -39,6 +39,8 @@ class CongratulationWindow (InstallWindow): # force buttonbar on in case release notes viewer is running ics.cw.mainxml.get_widget("buttonBar").set_sensitive(True) + self.rebootButton = ics.cw.mainxml.get_widget("rebootButton") + # this mucks around a bit, but it's the weird case and it's # better than adding a lot of complication to the normal ics.cw.mainxml.get_widget("nextButton").hide() @@ -46,6 +48,8 @@ class CongratulationWindow (InstallWindow): ics.cw.mainxml.get_widget("closeButton").show() ics.cw.mainxml.get_widget("closeButton").grab_focus() else: + self.rebootButton.show() + self.rebootButton.grab_focus() ics.cw.mainxml.get_widget("rebootButton").show() ics.cw.mainxml.get_widget("rebootButton").grab_focus() @@ -65,11 +69,29 @@ class CongratulationWindow (InstallWindow): a.set_size_request(200, -1) hbox.pack_start (a, False, False, 36) - txt = _("Congratulations, your %s installation is complete.\n\n" - "Please reboot to use the installed system. " - "Note that updates may be available to ensure the proper " - "functioning of your system and installation of these " - "updates is recommended after the reboot.") %(productName,) + if iutil.isS390(): + txt = _("Congratulations, your %s installation is complete.\n\n") % (productName,) + + if not anaconda.canReIPL: + self.rebootButton.set_label(_("Shutdown")) + + txt = txt + _("Please shutdown to use the installed system.\n") + else: + txt = txt + _("Please reboot to use the installed system.\n") + + if not anaconda.reIPLMessage is None: + txt = txt + "\n" + anaconda.reIPLMessage + "\n\n" + + txt = txt + _("Note that updates may be available to ensure the proper " + "functioning of your system and installation of these " + "updates is recommended after the reboot.") + else: + txt = _("Congratulations, your %s installation is complete.\n\n" + "Please reboot to use the installed system. " + "Note that updates may be available to ensure the proper " + "functioning of your system and installation of these " + "updates is recommended after the reboot.") %(productName,) + label = gui.WrappingLabel(txt) label.set_size_request(250, -1) diff --git a/loader/linuxrc.s390 b/loader/linuxrc.s390 index 9acab9b97..af2d43956 100644 --- a/loader/linuxrc.s390 +++ b/loader/linuxrc.s390 @@ -61,35 +61,13 @@ checkipv4() doshutdown() { - exec /sbin/shutdown - exit 0 + echo $"about to exec shutdown" + exec /sbin/shutdown + exit 0 } doreboot() { - # find out the location of /boot and use it to re-ipl - boot="$(cat /proc/mounts | grep " /mnt/sysimage/boot " | awk -F" " '{print $1}')" - if [ -z $boot ]; then - # use root if /boot not used - boot="$(cat /proc/mounts | grep " /mnt/sysimage " | awk -F" " '{print $1}')" - fi - - # lookup dasd disk - echo $boot | grep "dasd" > /dev/null - if [ $? -eq 0 ]; then - type="ccw" - boot="$(basename $boot)" - # strip partition number from dasd device - boot="$(echo ${boot%[0-9]})" - id="$(basename $(readlink /sys/block/$boot/device))" - echo $type > /sys/firmware/reipl/reipl_type - echo $id > /sys/firmware/reipl/$type/device - else - # scsi re-ipl only supported on newer machines - doshutdown - exit 0 - fi - echo $"about to exec shutdown -r" exec /sbin/shutdown -r exit 0 @@ -670,7 +648,9 @@ if [ -n "$RUNKS" ]; then /sbin/loader fi -doreboot +# A shutdown needs to be performed here to avoid a loop booting back into the installer +echo $"Finishing up with doshutdown" +doshutdown # ;;; Local Variables: *** # ;;; mode: sh *** diff --git a/loader/loader.c b/loader/loader.c index 10ac30756..98ea24cba 100644 --- a/loader/loader.c +++ b/loader/loader.c @@ -121,6 +121,8 @@ uint64_t flags = LOADER_FLAGS_SELINUX; int num_link_checks = 5; int post_link_sleep = 0; +static pid_t init_pid = 1; + static struct installMethod installMethods[] = { { N_("Local CD/DVD"), 0, DEVICE_CDROM, mountCdromImage }, { N_("Hard drive"), 0, DEVICE_DISK, mountHardDrive }, @@ -1716,6 +1718,11 @@ void loaderSegvHandler(int signum) { exit(1); } +void loaderUsrXHandler(int signum) { + logMessage(INFO, "Sending signal %d to process %d\n", signum, init_pid); + kill(init_pid, signum); +} + static int anaconda_trace_init(void) { #ifdef USE_MTRACE setenv("MALLOC_TRACE","/malloc",1); @@ -1798,6 +1805,26 @@ int main(int argc, char ** argv) { { 0, 0, 0, 0, 0, 0, 0 } }; + /* get init PID if we have it */ + if ((f = fopen("/var/run/init.pid", "r")) != NULL) { + char linebuf[256]; + memset(linebuf, '\0', sizeof(linebuf)); + + while (fgets(linebuf, sizeof(linebuf) - 1, f) != NULL) { + errno = 0; + init_pid = strtol((const char *) &linebuf, NULL, 10); + if (errno == EINVAL || errno == ERANGE) { + logMessage(ERROR, "%s (%d): %m", __func__, __LINE__); + init_pid = 1; + } + } + + fclose(f); + } + + signal(SIGUSR1, loaderUsrXHandler); + signal(SIGUSR2, loaderUsrXHandler); + /* Make sure sort order is right. */ setenv ("LC_COLLATE", "C", 1); @@ -2228,34 +2255,6 @@ int main(int argc, char ** argv) { waitpid(pid, &status, 0); } -#if defined(__s390__) || defined(__s390x__) - /* FIXME: we have to send a signal to linuxrc on s390 so that shutdown - * can happen. this is ugly */ - FILE * f; - f = fopen("/var/run/init.pid", "r"); - if (!f) { - logMessage(WARNING, "can't find init.pid, guessing that init is pid 1"); - pid = 1; - } else { - char * buf = malloc(256); - char *ret; - - ret = fgets(buf, 256, f); - errno = 0; - pid = strtol(buf, NULL, 10); - - if ((errno == ERANGE && (pid == LONG_MIN || pid == LONG_MAX)) || - (errno != 0 && pid == 0)) { - logMessage(ERROR, "%s: %d: %m", __func__, __LINE__); - abort(); - } - - free(buf); - fclose(f); - } - - kill(pid, SIGUSR2); -#endif stop_fw_loader(&loaderData); return rc; } diff --git a/packages.py b/packages.py index f871c49f8..12d98b76a 100644 --- a/packages.py +++ b/packages.py @@ -422,3 +422,26 @@ def betaNagScreen(anaconda): sys.exit(0) else: break + +def doReIPL(anaconda): +# # This is here as an example to fix the screen during the TUI debugging path +# anaconda.intf.screen.suspend () +# import pdb +# pdb.set_trace () + + if not iutil.isS390(): + return DISPATCH_NOOP + + messageInfo = iutil.reIPL(anaconda, os.getppid()) + + if messageInfo is None: + anaconda.canReIPL = True + else: + anaconda.canReIPL = False + + (errorMessage, rebootInstr) = messageInfo + + # errorMessage intentionally not shown in UI + anaconda.reIPLMessage = rebootInstr + + return DISPATCH_FORWARD diff --git a/textw/complete_text.py b/textw/complete_text.py index df735547f..1793cab10 100644 --- a/textw/complete_text.py +++ b/textw/complete_text.py @@ -28,17 +28,37 @@ class FinishedWindow: def __call__ (self, screen, anaconda): bootstr = "" + buttonstr = _("Reboot") bottomstr = _("<Enter> to exit") screen.pushHelpLine (string.center(bottomstr, screen.width)) - txt = _("Congratulations, your %s installation is complete.\n\n" - "Please reboot to use the installed system. " - "Note that updates may be available to ensure the proper " - "functioning of your system and installation of these " - "updates is recommended after the reboot.") %(productName,) + if iutil.isS390(): + txt = _("Congratulations, your %s installation is complete.\n\n") % (productName,) + + if not anaconda.canReIPL: + buttonstr = _("Shutdown") + + txt = txt + _("Please shutdown to use the installed system.\n") + else: + txt = txt + _("Please reboot to use the installed system.\n") + + if not anaconda.reIPLMessage is None: + txt = txt + "\n" + anaconda.reIPLMessage + "\n\n" + + txt = txt + _("Note that updates may be available to ensure the proper " + "functioning of your system and installation of these " + "updates is recommended after the reboot.") + else: + txt = _("Congratulations, your %s installation is complete.\n\n" + "Please reboot to use the installed system. " + "Note that updates may be available to ensure the proper " + "functioning of your system and installation of these " + "updates is recommended after the reboot.") %(productName,) + + rc = ButtonChoiceWindow (screen, _("Complete"), txt, - [ _("Reboot") ], help = "finished", width=60) + [ buttonstr ], help = "finished", width=60) return INSTALL_OK diff --git a/upgrade.py b/upgrade.py index a554d3bbe..c1b7b83e7 100644 --- a/upgrade.py +++ b/upgrade.py @@ -472,6 +472,7 @@ def setSteps(anaconda): "dependencies", "confirmupgrade", "postselection", + "reipl", "install", "migratefilesystems", "preinstallconfig", |