summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Hamzy <hamzy@us.ibm.com>2009-02-16 14:19:35 -0600
committerDavid Cantrell <dcantrell@redhat.com>2009-03-02 15:20:53 -1000
commitd00ef216099104c03c400f56fb21e19089df4a7d (patch)
tree7c413e8735cbd86e7fd1a4204778500c3e347f89
parent86eee97f1915c1743d7a2cd91c1b072ccd9bd1e7 (diff)
downloadanaconda-d00ef216099104c03c400f56fb21e19089df4a7d.tar.gz
anaconda-d00ef216099104c03c400f56fb21e19089df4a7d.tar.xz
anaconda-d00ef216099104c03c400f56fb21e19089df4a7d.zip
reIPL support for s390
Signed-off-by: David Cantrell <dcantrell@redhat.com>
-rwxr-xr-xanaconda10
-rw-r--r--dispatch.py3
-rw-r--r--installclass.py1
-rw-r--r--iutil.py181
-rw-r--r--iw/congrats_gui.py32
-rw-r--r--loader/linuxrc.s39032
-rw-r--r--loader/loader.c55
-rw-r--r--packages.py23
-rw-r--r--textw/complete_text.py32
-rw-r--r--upgrade.py1
10 files changed, 305 insertions, 65 deletions
diff --git a/anaconda b/anaconda
index f669ee0e8..312696a32 100755
--- a/anaconda
+++ b/anaconda
@@ -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",
diff --git a/iutil.py b/iutil.py
index f13956f8a..0a04babaf 100644
--- a/iutil.py
+++ b/iutil.py
@@ -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",