mirror of
https://github.com/rancher/os.git
synced 2025-09-02 15:24:32 +00:00
reboot --kexec almost works
Signed-off-by: Sven Dowideit <SvenDowideit@home.org.au>
This commit is contained in:
@@ -152,7 +152,7 @@ func installAction(c *cli.Context) error {
|
||||
if cloudConfig == "" {
|
||||
if installType != "upgrade" {
|
||||
// TODO: I wonder if its plausible to merge a new cloud-config into an existing one on upgrade - so for now, i'm only turning off the warning
|
||||
log.Warn("Cloud-config not provided: you might need to provide cloud-config on bootDir with ssh_authorized_keys")
|
||||
log.Warn("Cloud-config not provided: you might need to provide cloud-config on boot with ssh_authorized_keys")
|
||||
}
|
||||
} else {
|
||||
os.MkdirAll("/opt", 0755)
|
||||
@@ -410,7 +410,6 @@ func layDownOS(image, installType, cloudConfig, device, partition, statedir, kap
|
||||
//cloudConfig := SCRIPTS_DIR + "/conf/empty.yml" //${cloudConfig:-"${SCRIPTS_DIR}/conf/empty.yml"}
|
||||
CONSOLE := "tty0"
|
||||
baseName := "/mnt/new_img"
|
||||
bootDir := "boot/"
|
||||
kernelArgs := "printk.devkmsg=on rancher.state.dev=LABEL=RANCHER_STATE rancher.state.wait" // console="+CONSOLE
|
||||
if statedir != "" {
|
||||
kernelArgs = kernelArgs + " rancher.state.directory=" + statedir
|
||||
@@ -432,12 +431,12 @@ func layDownOS(image, installType, cloudConfig, device, partition, statedir, kap
|
||||
case "generic":
|
||||
log.Debugf("formatAndMount")
|
||||
var err error
|
||||
device, partition, err = formatAndMount(baseName, bootDir, device, partition)
|
||||
device, partition, err = formatAndMount(baseName, device, partition)
|
||||
if err != nil {
|
||||
log.Errorf("formatAndMount %s", err)
|
||||
return err
|
||||
}
|
||||
err = installSyslinux(device, baseName, bootDir, diskType)
|
||||
err = installSyslinux(device, baseName, diskType)
|
||||
if err != nil {
|
||||
log.Errorf("installSyslinux %s", err)
|
||||
return err
|
||||
@@ -449,7 +448,7 @@ func layDownOS(image, installType, cloudConfig, device, partition, statedir, kap
|
||||
}
|
||||
case "arm":
|
||||
var err error
|
||||
device, partition, err = formatAndMount(baseName, bootDir, device, partition)
|
||||
device, partition, err = formatAndMount(baseName, device, partition)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -459,45 +458,45 @@ func layDownOS(image, installType, cloudConfig, device, partition, statedir, kap
|
||||
case "amazon-ebs-hvm":
|
||||
CONSOLE = "ttyS0"
|
||||
var err error
|
||||
device, partition, err = formatAndMount(baseName, bootDir, device, partition)
|
||||
device, partition, err = formatAndMount(baseName, device, partition)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if installType == "amazon-ebs-hvm" {
|
||||
installSyslinux(device, baseName, bootDir, diskType)
|
||||
installSyslinux(device, baseName, diskType)
|
||||
}
|
||||
//# AWS Networking recommends disabling.
|
||||
seedData(baseName, cloudConfig, FILES)
|
||||
case "googlecompute":
|
||||
CONSOLE = "ttyS0"
|
||||
var err error
|
||||
device, partition, err = formatAndMount(baseName, bootDir, device, partition)
|
||||
device, partition, err = formatAndMount(baseName, device, partition)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
installSyslinux(device, baseName, bootDir, diskType)
|
||||
installSyslinux(device, baseName, diskType)
|
||||
seedData(baseName, cloudConfig, FILES)
|
||||
case "noformat":
|
||||
var err error
|
||||
device, partition, err = mountdevice(baseName, bootDir, device, partition, false)
|
||||
device, partition, err = install.MountDevice(baseName, device, partition, false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
installSyslinux(device, baseName, bootDir, diskType)
|
||||
installSyslinux(device, baseName, diskType)
|
||||
if err := os.MkdirAll(filepath.Join(baseName, statedir), 0755); err != nil {
|
||||
return err
|
||||
}
|
||||
case "raid":
|
||||
var err error
|
||||
device, partition, err = mountdevice(baseName, bootDir, device, partition, false)
|
||||
device, partition, err = install.MountDevice(baseName, device, partition, false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
installSyslinux(device, baseName, bootDir, diskType)
|
||||
installSyslinux(device, baseName, diskType)
|
||||
case "bootstrap":
|
||||
CONSOLE = "ttyS0"
|
||||
var err error
|
||||
device, partition, err = mountdevice(baseName, bootDir, device, partition, true)
|
||||
device, partition, err = install.MountDevice(baseName, device, partition, true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -507,39 +506,39 @@ func layDownOS(image, installType, cloudConfig, device, partition, statedir, kap
|
||||
fallthrough
|
||||
case "upgrade":
|
||||
var err error
|
||||
device, partition, err = mountdevice(baseName, bootDir, device, partition, false)
|
||||
device, partition, err = install.MountDevice(baseName, device, partition, false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
log.Debugf("upgrading - %s, %s, %s, %s", device, baseName, bootDir, diskType)
|
||||
log.Debugf("upgrading - %s, %s, %s, %s", device, baseName, diskType)
|
||||
// TODO: detect pv-grub, and don't kill it with syslinux
|
||||
upgradeBootloader(device, baseName, bootDir, diskType)
|
||||
upgradeBootloader(device, baseName, diskType)
|
||||
default:
|
||||
return fmt.Errorf("unexpected install type %s", installType)
|
||||
}
|
||||
kernelArgs = kernelArgs + " console=" + CONSOLE
|
||||
|
||||
if kappend == "" {
|
||||
preservedAppend, _ := ioutil.ReadFile(filepath.Join(baseName, bootDir+"append"))
|
||||
preservedAppend, _ := ioutil.ReadFile(filepath.Join(baseName, install.BootDir+"append"))
|
||||
kappend = string(preservedAppend)
|
||||
} else {
|
||||
ioutil.WriteFile(filepath.Join(baseName, bootDir+"append"), []byte(kappend), 0644)
|
||||
ioutil.WriteFile(filepath.Join(baseName, install.BootDir+"append"), []byte(kappend), 0644)
|
||||
}
|
||||
|
||||
if installType == "amazon-ebs-pv" {
|
||||
menu := install.BootVars{
|
||||
BaseName: baseName,
|
||||
BootDir: bootDir,
|
||||
BootDir: install.BootDir,
|
||||
Timeout: 0,
|
||||
Fallback: 0, // need to be conditional on there being a 'rollback'?
|
||||
Entries: []install.MenuEntry{
|
||||
install.MenuEntry{"RancherOS-current", bootDir, VERSION, kernelArgs, kappend},
|
||||
install.MenuEntry{"RancherOS-current", install.BootDir, VERSION, kernelArgs, kappend},
|
||||
},
|
||||
}
|
||||
install.PvGrubConfig(menu)
|
||||
}
|
||||
log.Debugf("installRancher")
|
||||
currentCfg, err := installRancher(baseName, bootDir, VERSION, DIST, kernelArgs+" "+kappend)
|
||||
currentCfg, err := installRancher(baseName, VERSION, DIST, kernelArgs+" "+kappend)
|
||||
if err != nil {
|
||||
log.Errorf("%s", err)
|
||||
return err
|
||||
@@ -548,55 +547,12 @@ func layDownOS(image, installType, cloudConfig, device, partition, statedir, kap
|
||||
|
||||
// Used by upgrade
|
||||
if kexec {
|
||||
vmlinuzFile, initrdFile, err := readSyslinuxCfg(currentCfg)
|
||||
if err != nil {
|
||||
log.Errorf("%s", err)
|
||||
return err
|
||||
}
|
||||
// kexec -l ${DIST}/vmlinuz --initrd=${DIST}/initrd --append="${kernelArgs} ${APPEND}" -f
|
||||
cmd := exec.Command(
|
||||
"kexec",
|
||||
"-l", DIST+"/"+vmlinuzFile,
|
||||
"--initrd", DIST+"/"+initrdFile,
|
||||
"--append", "'"+kernelArgs+" "+kappend+"'",
|
||||
"-f")
|
||||
log.Debugf("Run(%#v)", cmd)
|
||||
cmd.Stderr = os.Stderr
|
||||
if _, err := cmd.Output(); err != nil {
|
||||
log.Errorf("Failed to kexec: %s", err)
|
||||
return err
|
||||
}
|
||||
log.Infof("kexec'd to new install")
|
||||
power.Kexec(currentCfg, kernelArgs+" "+kappend)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func readSyslinuxCfg(currentCfg string) (string, string, error) {
|
||||
vmlinuzFile := ""
|
||||
initrdFile := ""
|
||||
// Need to parse currentCfg for the lines:
|
||||
// KERNEL ../vmlinuz-4.9.18-rancher^M
|
||||
// INITRD ../initrd-41e02e6-dirty^M
|
||||
buf, err := ioutil.ReadFile(currentCfg)
|
||||
if err != nil {
|
||||
return vmlinuzFile, initrdFile, err
|
||||
}
|
||||
s := bufio.NewScanner(bytes.NewReader(buf))
|
||||
for s.Scan() {
|
||||
line := strings.TrimSpace(s.Text())
|
||||
if strings.HasPrefix(line, "KERNEL") {
|
||||
vmlinuzFile = strings.TrimSpace(strings.TrimPrefix(line, "KERNEL"))
|
||||
vmlinuzFile = filepath.Base(vmlinuzFile)
|
||||
}
|
||||
if strings.HasPrefix(line, "INITRD") {
|
||||
initrdFile = strings.TrimSpace(strings.TrimPrefix(line, "INITRD"))
|
||||
initrdFile = filepath.Base(initrdFile)
|
||||
}
|
||||
}
|
||||
return vmlinuzFile, initrdFile, err
|
||||
}
|
||||
|
||||
// files is an array of 'sourcefile:destination' - but i've not seen any examples of it being used.
|
||||
func seedData(baseName, cloudData string, files []string) error {
|
||||
log.Debugf("seedData")
|
||||
@@ -772,59 +728,7 @@ func formatdevice(device, partition string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func mountdevice(baseName, bootDir, device, partition string, raw bool) (string, string, error) {
|
||||
log.Debugf("mountdevice %s, raw %v", partition, raw)
|
||||
|
||||
if partition == "" {
|
||||
if raw {
|
||||
log.Debugf("util.Mount (raw) %s, %s", partition, baseName)
|
||||
|
||||
cmd := exec.Command("lsblk", "-no", "pkname", partition)
|
||||
log.Debugf("Run(%v)", cmd)
|
||||
cmd.Stderr = os.Stderr
|
||||
device := ""
|
||||
// TODO: out can == "" - this is used to "detect software RAID" which is terrible
|
||||
if out, err := cmd.Output(); err == nil {
|
||||
device = "/dev/" + strings.TrimSpace(string(out))
|
||||
}
|
||||
|
||||
log.Debugf("mountdevice return -> d: %s, p: %s", device, partition)
|
||||
return device, partition, util.Mount(partition, baseName, "", "")
|
||||
}
|
||||
|
||||
//rootfs := partition
|
||||
// Don't use ResolveDevice - it can fail, whereas `blkid -L LABEL` works more often
|
||||
|
||||
cfg := config.LoadConfig()
|
||||
if d, _ := util.Blkid("RANCHER_BOOT"); d != "" {
|
||||
partition = d
|
||||
baseName = filepath.Join(baseName, "boot")
|
||||
} else {
|
||||
if dev := util.ResolveDevice(cfg.Rancher.State.Dev); dev != "" {
|
||||
// try the rancher.state.dev setting
|
||||
partition = dev
|
||||
} else {
|
||||
if d, _ := util.Blkid("RANCHER_STATE"); d != "" {
|
||||
partition = d
|
||||
}
|
||||
}
|
||||
}
|
||||
cmd := exec.Command("lsblk", "-no", "pkname", partition)
|
||||
log.Debugf("Run(%v)", cmd)
|
||||
cmd.Stderr = os.Stderr
|
||||
// TODO: out can == "" - this is used to "detect software RAID" which is terrible
|
||||
if out, err := cmd.Output(); err == nil {
|
||||
device = "/dev/" + strings.TrimSpace(string(out))
|
||||
}
|
||||
}
|
||||
os.MkdirAll(baseName, 0755)
|
||||
cmd := exec.Command("mount", partition, baseName)
|
||||
//cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr
|
||||
log.Debugf("mountdevice return2 -> d: %s, p: %s", device, partition)
|
||||
return device, partition, cmd.Run()
|
||||
}
|
||||
|
||||
func formatAndMount(baseName, bootDir, device, partition string) (string, string, error) {
|
||||
func formatAndMount(baseName, device, partition string) (string, string, error) {
|
||||
log.Debugf("formatAndMount")
|
||||
|
||||
err := formatdevice(device, partition)
|
||||
@@ -832,31 +736,14 @@ func formatAndMount(baseName, bootDir, device, partition string) (string, string
|
||||
log.Errorf("formatdevice %s", err)
|
||||
return device, partition, err
|
||||
}
|
||||
device, partition, err = mountdevice(baseName, bootDir, device, partition, false)
|
||||
device, partition, err = install.MountDevice(baseName, device, partition, false)
|
||||
if err != nil {
|
||||
log.Errorf("mountdevice %s", err)
|
||||
return device, partition, err
|
||||
}
|
||||
//err = createbootDirs(baseName, bootDir)
|
||||
//if err != nil {
|
||||
// log.Errorf("createbootDirs %s", err)
|
||||
// return bootDir, err
|
||||
//}
|
||||
return device, partition, nil
|
||||
}
|
||||
|
||||
func NOPEcreatebootDir(baseName, bootDir string) error {
|
||||
log.Debugf("createbootDirs")
|
||||
|
||||
if err := os.MkdirAll(filepath.Join(baseName, bootDir+"grub"), 0755); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := os.MkdirAll(filepath.Join(baseName, bootDir+"syslinux"), 0755); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func setBootable(device, diskType string) error {
|
||||
// TODO make conditional - if there is a bootable device already, don't break it
|
||||
// TODO: make RANCHER_BOOT bootable - it might not be device 1
|
||||
@@ -875,10 +762,10 @@ func setBootable(device, diskType string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func upgradeBootloader(device, baseName, bootDir, diskType string) error {
|
||||
func upgradeBootloader(device, baseName, diskType string) error {
|
||||
log.Debugf("start upgradeBootloader")
|
||||
|
||||
grubDir := filepath.Join(baseName, bootDir+"grub")
|
||||
grubDir := filepath.Join(baseName, install.BootDir+"grub")
|
||||
if _, err := os.Stat(grubDir); os.IsNotExist(err) {
|
||||
log.Debugf("%s does not exist - no need to upgrade bootloader", grubDir)
|
||||
// we've already upgraded
|
||||
@@ -886,12 +773,12 @@ func upgradeBootloader(device, baseName, bootDir, diskType string) error {
|
||||
return nil
|
||||
}
|
||||
// deal with systems which were previously upgraded, then rolled back, and are now being re-upgraded
|
||||
grubBackup := filepath.Join(baseName, bootDir+"grub_backup")
|
||||
grubBackup := filepath.Join(baseName, install.BootDir+"grub_backup")
|
||||
if err := os.RemoveAll(grubBackup); err != nil {
|
||||
log.Errorf("RemoveAll (%s): %s", grubBackup, err)
|
||||
return err
|
||||
}
|
||||
backupSyslinuxDir := filepath.Join(baseName, bootDir+"syslinux_backup")
|
||||
backupSyslinuxDir := filepath.Join(baseName, install.BootDir+"syslinux_backup")
|
||||
if _, err := os.Stat(backupSyslinuxDir); !os.IsNotExist(err) {
|
||||
backupSyslinuxLdlinuxSys := filepath.Join(backupSyslinuxDir, "ldlinux.sys")
|
||||
if _, err := os.Stat(backupSyslinuxLdlinuxSys); !os.IsNotExist(err) {
|
||||
@@ -914,7 +801,7 @@ func upgradeBootloader(device, baseName, bootDir, diskType string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
syslinuxDir := filepath.Join(baseName, bootDir+"syslinux")
|
||||
syslinuxDir := filepath.Join(baseName, install.BootDir+"syslinux")
|
||||
// it seems that v0.5.0 didn't have a syslinux dir, while 0.7 does
|
||||
if _, err := os.Stat(syslinuxDir); !os.IsNotExist(err) {
|
||||
if err := os.Rename(syslinuxDir, backupSyslinuxDir); err != nil {
|
||||
@@ -935,15 +822,15 @@ func upgradeBootloader(device, baseName, bootDir, diskType string) error {
|
||||
|
||||
cfg = strings.Replace(cfg, "current", "previous", -1)
|
||||
// TODO consider removing the APPEND line - as the global.cfg should have the same result
|
||||
ioutil.WriteFile(filepath.Join(baseName, bootDir, "linux-current.cfg"), []byte(cfg), 0644)
|
||||
ioutil.WriteFile(filepath.Join(baseName, install.BootDir, "linux-current.cfg"), []byte(cfg), 0644)
|
||||
|
||||
lines := strings.Split(cfg, "\n")
|
||||
for _, line := range lines {
|
||||
line = strings.TrimSpace(line)
|
||||
if strings.HasPrefix(line, "APPEND") {
|
||||
log.Errorf("write new (%s) %s", filepath.Join(baseName, bootDir, "global.cfg"), err)
|
||||
log.Errorf("write new (%s) %s", filepath.Join(baseName, install.BootDir, "global.cfg"), err)
|
||||
// TODO: need to append any extra's the user specified
|
||||
ioutil.WriteFile(filepath.Join(baseName, bootDir, "global.cfg"), []byte(cfg), 0644)
|
||||
ioutil.WriteFile(filepath.Join(baseName, install.BootDir, "global.cfg"), []byte(cfg), 0644)
|
||||
break
|
||||
}
|
||||
}
|
||||
@@ -951,10 +838,10 @@ func upgradeBootloader(device, baseName, bootDir, diskType string) error {
|
||||
}
|
||||
}
|
||||
|
||||
return installSyslinux(device, baseName, bootDir, diskType)
|
||||
return installSyslinux(device, baseName, diskType)
|
||||
}
|
||||
|
||||
func installSyslinux(device, baseName, bootDir, diskType string) error {
|
||||
func installSyslinux(device, baseName, diskType string) error {
|
||||
log.Debugf("installSyslinux(%s)", device)
|
||||
|
||||
mbrFile := "mbr.bin"
|
||||
@@ -1004,7 +891,7 @@ func installSyslinux(device, baseName, bootDir, diskType string) error {
|
||||
}
|
||||
}
|
||||
|
||||
sysLinuxDir := filepath.Join(baseName, bootDir, "syslinux")
|
||||
sysLinuxDir := filepath.Join(baseName, install.BootDir, "syslinux")
|
||||
if err := os.MkdirAll(sysLinuxDir, 0755); err != nil {
|
||||
log.Errorf("MkdirAll(%s)): %s", sysLinuxDir, err)
|
||||
//return err
|
||||
@@ -1037,13 +924,13 @@ func installSyslinux(device, baseName, bootDir, diskType string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func installRancher(baseName, bootDir, VERSION, DIST, kappend string) (string, error) {
|
||||
func installRancher(baseName, VERSION, DIST, kappend string) (string, error) {
|
||||
log.Debugf("installRancher")
|
||||
|
||||
// detect if there already is a linux-current.cfg, if so, move it to linux-previous.cfg,
|
||||
currentCfg := filepath.Join(baseName, bootDir, "linux-current.cfg")
|
||||
currentCfg := filepath.Join(baseName, install.BootDir, "linux-current.cfg")
|
||||
if _, err := os.Stat(currentCfg); !os.IsNotExist(err) {
|
||||
previousCfg := filepath.Join(baseName, bootDir, "linux-previous.cfg")
|
||||
previousCfg := filepath.Join(baseName, install.BootDir, "linux-previous.cfg")
|
||||
if _, err := os.Stat(previousCfg); !os.IsNotExist(err) {
|
||||
if err := os.Remove(previousCfg); err != nil {
|
||||
return currentCfg, err
|
||||
@@ -1059,19 +946,19 @@ func installRancher(baseName, bootDir, VERSION, DIST, kappend string) (string, e
|
||||
if file.IsDir() {
|
||||
continue
|
||||
}
|
||||
if err := dfs.CopyFile(filepath.Join(DIST, file.Name()), filepath.Join(baseName, bootDir), file.Name()); err != nil {
|
||||
if err := dfs.CopyFile(filepath.Join(DIST, file.Name()), filepath.Join(baseName, install.BootDir), file.Name()); err != nil {
|
||||
log.Errorf("copy %s: %s", file.Name(), err)
|
||||
//return err
|
||||
}
|
||||
}
|
||||
// the general INCLUDE syslinuxcfg
|
||||
if err := dfs.CopyFile(filepath.Join(DIST, "isolinux", "isolinux.cfg"), filepath.Join(baseName, bootDir, "syslinux"), "syslinux.cfg"); err != nil {
|
||||
if err := dfs.CopyFile(filepath.Join(DIST, "isolinux", "isolinux.cfg"), filepath.Join(baseName, install.BootDir, "syslinux"), "syslinux.cfg"); err != nil {
|
||||
log.Errorf("copy global syslinux.cfgS%s: %s", "syslinux.cfg", err)
|
||||
//return err
|
||||
}
|
||||
|
||||
// The global.cfg INCLUDE - useful for over-riding the APPEND line
|
||||
globalFile := filepath.Join(filepath.Join(baseName, bootDir), "global.cfg")
|
||||
globalFile := filepath.Join(filepath.Join(baseName, install.BootDir), "global.cfg")
|
||||
if _, err := os.Stat(globalFile); !os.IsNotExist(err) {
|
||||
err := ioutil.WriteFile(globalFile, []byte("APPEND "+kappend), 0644)
|
||||
if err != nil {
|
||||
|
Reference in New Issue
Block a user