diff --git a/cmd/control/install.go b/cmd/control/install.go index 0fbdc9de..188962ca 100755 --- a/cmd/control/install.go +++ b/cmd/control/install.go @@ -538,16 +538,15 @@ func layDownOS(image, installType, cloudConfig, device, partition, statedir, kap install.PvGrubConfig(menu) } log.Debugf("installRancher") - currentCfg, err := installRancher(baseName, VERSION, DIST, kernelArgs+" "+kappend) + _, err := installRancher(baseName, VERSION, DIST, kernelArgs+" "+kappend) if err != nil { log.Errorf("%s", err) return err } log.Debugf("installRancher done") - // Used by upgrade if kexec { - power.Kexec(currentCfg, kernelArgs+" "+kappend) + power.Kexec(false, filepath.Join(baseName, install.BootDir), kernelArgs+" "+kappend) } return nil diff --git a/cmd/power/power.go b/cmd/power/power.go index 1a927c68..560e0e07 100644 --- a/cmd/power/power.go +++ b/cmd/power/power.go @@ -13,6 +13,7 @@ import ( "github.com/docker/engine-api/types" "github.com/docker/engine-api/types/container" "github.com/docker/engine-api/types/filters" + "github.com/rancher/os/cmd/control/install" "github.com/rancher/os/log" "github.com/rancher/os/docker" @@ -108,10 +109,31 @@ func reboot(name string, force bool, code uint) { log.Fatalf("%s: Need to be root", os.Args[0]) } + // reboot -f should work even when system-docker is having problems if !force { + if kexecFlag || previouskexecFlag || kexecAppendFlag != "" { + // pass through the cmdline args + name = "" + } if err := runDocker(name); err != nil { log.Fatal(err) } + } + + if kexecFlag || previouskexecFlag || kexecAppendFlag != "" { + // need to mount boot dir, or `system-docker run -v /:/host -w /host/boot` ? + baseName := "/mnt/new_img" + _, _, err := install.MountDevice(baseName, "", "", false) + if err != nil { + log.Errorf("ERROR: can't Kexec: %s", err) + return + } + defer util.Unmount(baseName) + Kexec(previouskexecFlag, filepath.Join(baseName, install.BootDir), kexecAppendFlag) + return + } + + if !force { err := shutDownContainers() if err != nil { log.Error(err) diff --git a/cmd/power/shutdown.go b/cmd/power/shutdown.go index 9620800e..23a07019 100644 --- a/cmd/power/shutdown.go +++ b/cmd/power/shutdown.go @@ -11,15 +11,16 @@ import ( "github.com/rancher/os/cmd/control/install" "github.com/rancher/os/config" "github.com/rancher/os/log" - "github.com/rancher/os/util" ) var ( - haltFlag bool - poweroffFlag bool - rebootFlag bool - forceFlag bool - kexecFlag bool + haltFlag bool + poweroffFlag bool + rebootFlag bool + forceFlag bool + kexecFlag bool + previouskexecFlag bool + kexecAppendFlag string ) func Shutdown() { @@ -114,9 +115,19 @@ func Shutdown() { // OR? maybe implement it as a `kexec` cli tool? app.Flags = append(app.Flags, cli.BoolFlag{ Name: "kexec", - Usage: "kexec the default kernel", + Usage: "kexec the default RancherOS cfg", Destination: &kexecFlag, }) + app.Flags = append(app.Flags, cli.BoolFlag{ + Name: "kexec-previous", + Usage: "kexec the previous RancherOS cfg", + Destination: &previouskexecFlag, + }) + app.Flags = append(app.Flags, cli.StringFlag{ + Name: "kexec-append", + Usage: "kexec using the specified kernel boot params (ignores global.cfg)", + Destination: &kexecAppendFlag, + }) } else { app.Flags = append(app.Flags, cli.BoolFlag{ Name: "r, reboot", @@ -128,8 +139,12 @@ func Shutdown() { app.Run(os.Args) } -func Kexec(bootDir, append string) error { - cfgFile := filepath.Join(bootDir, "linux-current.cfg") +func Kexec(previous bool, bootDir, append string) error { + cfg := "linux-current.cfg" + if previous { + cfg = "linux-previous.cfg" + } + cfgFile := filepath.Join(bootDir, cfg) vmlinuzFile, initrdFile, err := install.ReadSyslinuxCfg(cfgFile) if err != nil { log.Errorf("%s", err) @@ -149,7 +164,7 @@ func Kexec(bootDir, append string) error { "kexec", "-l", vmlinuzFile, "--initrd", initrdFile, - "--append", "'"+append+"'", + "--append", append, "-f") log.Debugf("Run(%#v)", cmd) cmd.Stderr = os.Stderr @@ -168,21 +183,6 @@ func Reboot() { } func shutdown(c *cli.Context) error { - if kexecFlag { - if os.Geteuid() != 0 { - log.Fatalf("%s: Need to be root", os.Args[0]) - } - - // need to mount boot dir, or `system-docker run -v /:/host -w /host/boot` ? - baseName := "/mnt/new_img" - _, _, err := install.MountDevice(baseName, "", "", false) - if err != nil { - log.Errorf("ERROR: can't Kexec: %s", err) - return nil - } - defer util.Unmount(baseName) - return Kexec(filepath.Join(baseName, install.BootDir), "") - } // the shutdown command's default is poweroff var powerCmd uint powerCmd = syscall.LINUX_REBOOT_CMD_POWER_OFF diff --git a/config/disk.go b/config/disk.go index c367012e..c1458267 100755 --- a/config/disk.go +++ b/config/disk.go @@ -64,6 +64,7 @@ func LoadConfigWithPrefix(dirPrefix string) *CloudConfig { cfg := &CloudConfig{} if err := util.Convert(rawCfg, cfg); err != nil { log.Errorf("Failed to parse configuration: %s", err) + log.Debugf("Bad cfg:\n%v\n", rawCfg) return &CloudConfig{} } cfg = amendNils(cfg)