From 2a575837b2862568d7bd2d6542eefacc68ae6624 Mon Sep 17 00:00:00 2001 From: Sven Dowideit Date: Tue, 20 Dec 2016 22:49:34 +1000 Subject: [PATCH] Installing 0.7.1, and then rebooting, and doing a ros upgrade to a faked up latest works \o/ Signed-off-by: Sven Dowideit --- Dockerfile.dapper | 2 +- cmd/control/install.go | 475 ++++++++++++------------- cmd/control/install/grub.go | 102 ++++++ cmd/control/install/install.go | 11 + cmd/control/install/syslinux.go | 45 +++ log/log.go | 4 +- os-config.tpl.yml | 1 - scripts/installer/BaseDockerfile.amd64 | 7 +- scripts/installer/Dockerfile.amd64 | 4 +- scripts/installer/lay-down-os | 7 +- scripts/package-installer | 15 +- scripts/package-iso | 1 + scripts/run | 21 +- tests/common_test.go | 22 +- tests/installer_test.go | 107 +++++- 15 files changed, 528 insertions(+), 296 deletions(-) create mode 100644 cmd/control/install/grub.go create mode 100644 cmd/control/install/install.go create mode 100644 cmd/control/install/syslinux.go diff --git a/Dockerfile.dapper b/Dockerfile.dapper index 6866c21a..236117e9 100644 --- a/Dockerfile.dapper +++ b/Dockerfile.dapper @@ -10,7 +10,7 @@ RUN apt-get update && \ dosfstools \ gccgo \ genisoimage \ - gettext \ + gettext \ git \ isolinux \ less \ diff --git a/cmd/control/install.go b/cmd/control/install.go index 06dcda8e..31435838 100755 --- a/cmd/control/install.go +++ b/cmd/control/install.go @@ -11,27 +11,17 @@ import ( "path/filepath" "strconv" "strings" - "text/template" "github.com/rancher/os/log" "github.com/codegangsta/cli" + "github.com/rancher/os/cmd/control/install" "github.com/rancher/os/cmd/power" "github.com/rancher/os/config" "github.com/rancher/os/dfs" // TODO: move CopyFile into util or something. "github.com/rancher/os/util" ) -type MenuEntry struct { - Name, bootDir, Version, KernelArgs, Append string -} -type bootVars struct { - baseName, bootDir string - Timeout uint - Fallback int - Entries []MenuEntry -} - var installCommand = cli.Command{ Name: "install", Usage: "install RancherOS to disk", @@ -71,9 +61,18 @@ var installCommand = cli.Command{ Name: "append, a", Usage: "append additional kernel parameters", }, + cli.StringFlag{ // TODO: hide.. + Name: "rollback, r", + Usage: "rollback version", + }, + cli.BoolFlag{ // TODO: this should be hidden and internal only + Name: "isoinstallerloaded", + Usage: "INTERNAL use only: mount the iso to get kernel and initrd", + Hidden: true, + }, cli.BoolFlag{ - Name: "mountiso", - Usage: "mount the iso to get kernel and initrd", + Name: "kexec", + Usage: "reboot using kexec", }, }, } @@ -82,10 +81,11 @@ func installAction(c *cli.Context) error { if c.Args().Present() { log.Fatalf("invalid arguments %v", c.Args()) } - device := c.String("device") - if device == "" { - log.Fatal("Can not proceed without -d specified") - } + kappend := strings.TrimSpace(c.String("append")) + force := c.Bool("force") + kexec := c.Bool("kexec") + reboot := !c.Bool("no-reboot") + isoinstallerloaded := c.Bool("isoinstallerloaded") image := c.String("image") cfg := config.LoadConfig() @@ -98,6 +98,23 @@ func installAction(c *cli.Context) error { log.Info("No install type specified...defaulting to generic") installType = "generic" } + if installType == "rancher-upgrade" || + installType == "upgrade" { + force = true // the os.go upgrade code already asks + reboot = false + isoinstallerloaded = true // OMG this flag is aweful - kill it with fire + } + device := c.String("device") + if installType != "noformat" && + installType != "raid" && + installType != "bootstrap" && + installType != "upgrade" && + installType != "rancher-upgrade" { + // These can use RANCHER_BOOT or RANCHER_STATE labels.. + if device == "" { + log.Fatal("Can not proceed without -d specified") + } + } cloudConfig := c.String("cloud-config") if cloudConfig == "" { @@ -110,19 +127,14 @@ func installAction(c *cli.Context) error { cloudConfig = uc } - kappend := strings.TrimSpace(c.String("append")) - force := c.Bool("force") - reboot := !c.Bool("no-reboot") - mountiso := c.Bool("mountiso") - - if err := runInstall(image, installType, cloudConfig, device, kappend, force, reboot, mountiso); err != nil { + if err := runInstall(image, installType, cloudConfig, device, kappend, force, reboot, kexec, isoinstallerloaded); err != nil { log.WithFields(log.Fields{"err": err}).Fatal("Failed to run install") } return nil } -func runInstall(image, installType, cloudConfig, device, kappend string, force, reboot, mountiso bool) error { +func runInstall(image, installType, cloudConfig, device, kappend string, force, reboot, kexec, isoinstallerloaded bool) error { fmt.Printf("Installing from %s\n", image) if !force { @@ -132,6 +144,7 @@ func runInstall(image, installType, cloudConfig, device, kappend string, force, } } diskType := "msdos" + if installType == "gptsyslinux" { diskType = "gpt" } @@ -139,7 +152,7 @@ func runInstall(image, installType, cloudConfig, device, kappend string, force, // Versions before 0.8.0-rc2 use the old calling convention (from the lay-down-os shell script) imageVersion := strings.TrimPrefix(image, "rancher/os:v") if image != imageVersion { - log.Infof("user spcified different install image: %s != %s", image, imageVersion) + log.Infof("user specified different install image: %s != %s", image, imageVersion) imageVersion = strings.Replace(imageVersion, "-", ".", -1) vArray := strings.Split(imageVersion, ".") v, _ := strconv.ParseFloat(vArray[0]+"."+vArray[1], 32) @@ -166,10 +179,19 @@ func runInstall(image, installType, cloudConfig, device, kappend string, force, } } + if _, err := os.Stat("/usr/bin/system-docker"); os.IsNotExist(err) { + if err := os.Symlink("/usr/bin/ros", "/usr/bin/system-docker"); err != nil { + log.Errorf("ln error %s", err) + } + } + useIso := false - if !mountiso { + // --isoinstallerloaded is used if the ros has created the installer container from and image that was on the booted iso + if !isoinstallerloaded { if _, err := os.Stat("/dist/initrd"); os.IsNotExist(err) { - if err = mountBootIso(); err == nil { + if err = mountBootIso(); err != nil { + log.Debugf("mountBootIso error %s", err) + } else { if _, err := os.Stat("/bootiso/rancheros/"); err == nil { cmd := exec.Command("system-docker", "load", "-i", "/bootiso/rancheros/installer.tar.gz") cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr @@ -196,7 +218,7 @@ func runInstall(image, installType, cloudConfig, device, kappend string, force, "-v", "/:/host", "--volumes-from=all-volumes", image, - "install", + // "install", "-t", installType, "-d", device, } @@ -213,7 +235,10 @@ func runInstall(image, installType, cloudConfig, device, kappend string, force, installerCmd = append(installerCmd, "-a", kappend) } if useIso { - installerCmd = append(installerCmd, "--mountiso") + installerCmd = append(installerCmd, "--isoinstallerloaded=1") + } + if kexec { + installerCmd = append(installerCmd, "--kexec") } cmd := exec.Command("system-docker", installerCmd...) @@ -255,8 +280,13 @@ func runInstall(image, installType, cloudConfig, device, kappend string, force, device = "/host" + device } - log.Debugf("running mountiso?") - if mountiso { + if installType == "rancher-upgrade" || + installType == "upgrade" { + isoinstallerloaded = false + } + + if isoinstallerloaded { + log.Debugf("running isoinstallerloaded...") // TODO: I hope to remove this from here later. if err := mountBootIso(); err != nil { log.Errorf("error mountBootIso %s", err) @@ -264,13 +294,13 @@ func runInstall(image, installType, cloudConfig, device, kappend string, force, } } - err := layDownOS(image, installType, cloudConfig, device, kappend) + err := layDownOS(image, installType, cloudConfig, device, kappend, kexec) if err != nil { log.Errorf("error layDownOS %s", err) return err } - if reboot && (force || yes("Continue with reboot")) { + if !kexec && reboot && (force || yes("Continue with reboot")) { log.Info("Rebooting") power.Reboot() } @@ -334,7 +364,7 @@ func mountBootIso() error { return err } -func layDownOS(image, installType, cloudConfig, device, kappend string) error { +func layDownOS(image, installType, cloudConfig, device, kappend string, kexec bool) error { // ENV == installType //[[ "$ARCH" == "arm" && "$ENV" != "rancher-upgrade" ]] && ENV=arm @@ -347,7 +377,7 @@ func layDownOS(image, installType, cloudConfig, device, kappend string) error { //cloudConfig := SCRIPTS_DIR + "/conf/empty.yml" //${cloudConfig:-"${SCRIPTS_DIR}/conf/empty.yml"} CONSOLE := "tty0" baseName := "/mnt/new_img" - bootDir := "boot/" // set by mountdevice + bootDir := "boot/" //# TODO: Change this to a number so that users can specify. //# Will need to make it so that our builds and packer APIs remain consistent. partition := device + "1" //${partition:=${device}1} @@ -369,30 +399,24 @@ func layDownOS(image, installType, cloudConfig, device, kappend string) error { case "generic": log.Debugf("formatAndMount") var err error - bootDir, err = formatAndMount(baseName, bootDir, device, partition) + device, partition, err = formatAndMount(baseName, bootDir, device, partition) if err != nil { log.Errorf("formatAndMount %s", err) return err } - //log.Infof("installGrub") - //err = installGrub(baseName, device) - log.Debugf("installSyslinux") err = installSyslinux(device, baseName, bootDir, diskType) - if err != nil { log.Errorf("installSyslinux %s", err) return err } - log.Debugf("seedData") err = seedData(baseName, cloudConfig, FILES) if err != nil { log.Errorf("seedData %s", err) return err } - log.Debugf("seedData done") case "arm": var err error - bootDir, err = formatAndMount(baseName, bootDir, device, partition) + device, partition, err = formatAndMount(baseName, bootDir, device, partition) if err != nil { return err } @@ -402,56 +426,56 @@ func layDownOS(image, installType, cloudConfig, device, kappend string) error { case "amazon-ebs-hvm": CONSOLE = "ttyS0" var err error - bootDir, err = formatAndMount(baseName, bootDir, device, partition) + device, partition, err = formatAndMount(baseName, bootDir, device, partition) if err != nil { return err } if installType == "amazon-ebs-hvm" { - installGrub(baseName, device) + installSyslinux(device, baseName, bootDir, diskType) } //# AWS Networking recommends disabling. seedData(baseName, cloudConfig, FILES) case "googlecompute": CONSOLE = "ttyS0" var err error - bootDir, err = formatAndMount(baseName, bootDir, device, partition) + device, partition, err = formatAndMount(baseName, bootDir, device, partition) if err != nil { return err } - installGrub(baseName, device) + installSyslinux(device, baseName, bootDir, diskType) seedData(baseName, cloudConfig, FILES) case "noformat": var err error - bootDir, err = mountdevice(baseName, bootDir, partition, false) + device, partition, err = mountdevice(baseName, bootDir, partition, false) if err != nil { return err } - createbootDirs(baseName, bootDir) installSyslinux(device, baseName, bootDir, diskType) case "raid": var err error - bootDir, err = mountdevice(baseName, bootDir, partition, false) + device, partition, err = mountdevice(baseName, bootDir, partition, false) if err != nil { return err } - createbootDirs(baseName, bootDir) installSyslinuxRaid(baseName, bootDir, diskType) case "bootstrap": CONSOLE = "ttyS0" var err error - bootDir, err = mountdevice(baseName, bootDir, partition, true) + device, partition, err = mountdevice(baseName, bootDir, partition, true) if err != nil { return err } - createbootDirs(baseName, bootDir) kernelArgs = kernelArgs + " rancher.cloud_init.datasources=[ec2,gce]" + case "upgrade": + fallthrough case "rancher-upgrade": var err error - bootDir, err = mountdevice(baseName, bootDir, partition, false) + device, partition, err = mountdevice(baseName, bootDir, partition, false) if err != nil { return err } - createbootDirs(baseName, bootDir) + // TODO: detect pv-grub, and don't kill it with syslinux + upgradeBootloader(device, baseName, bootDir, diskType) default: return fmt.Errorf("unexpected install type %s", installType) } @@ -464,23 +488,18 @@ func layDownOS(image, installType, cloudConfig, device, kappend string) error { ioutil.WriteFile(filepath.Join(baseName, bootDir+"append"), []byte(kappend), 0644) } - //menu := bootVars{ - // baseName: baseName, - // bootDir: bootDir, - // Timeout: 1, - // Fallback: 1, // need to be conditional on there being a 'rollback'? - // Entries: []MenuEntry{ - // MenuEntry{"RancherOS-current", bootDir, VERSION, kernelArgs, kappend}, - // // MenuEntry{"RancherOS-rollback", bootDir, ROLLBACK_VERSION, kernelArgs, kappend}, - // }, - //} - - //log.Debugf("grubConfig") - //grubConfig(menu) - //log.Debugf("syslinuxConfig") - //syslinuxConfig(menu) - //log.Debugf("pvGrubConfig") - //pvGrubConfig(menu) + if installType == "amazon-ebs-pv" { + menu := install.BootVars{ + BaseName: baseName, + BootDir: 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.PvGrubConfig(menu) + } log.Debugf("installRancher") err := installRancher(baseName, bootDir, VERSION, DIST, kernelArgs+" "+kappend) if err != nil { @@ -489,10 +508,22 @@ func layDownOS(image, installType, cloudConfig, device, kappend string) error { } log.Debugf("installRancher done") - //unused by us? :) - //if [ "$KEXEC" = "y" ]; then - // kexec -l ${DIST}/vmlinuz --initrd=${DIST}/initrd --append="${kernelArgs} ${APPEND}" -f - //fi + // Used by upgrade + if kexec { + // kexec -l ${DIST}/vmlinuz --initrd=${DIST}/initrd --append="${kernelArgs} ${APPEND}" -f + cmd := exec.Command("kexec", "-l "+DIST+"/vmlinuz", + "--initrd="+DIST+"/initrd", + "--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") + } + return nil } @@ -508,7 +539,7 @@ func seedData(baseName, cloudData string, files []string) error { return err } - if strings.HasSuffix(cloudData, "empty.yml") { + if !strings.HasSuffix(cloudData, "empty.yml") { if err = dfs.CopyFile(cloudData, baseName+"/var/lib/rancher/conf/cloud-config.d/", filepath.Base(cloudData)); err != nil { return err } @@ -576,11 +607,6 @@ func setDiskpartitions(device, diskType string) error { return err } - // TODO: work out where to do this - it is a so-so place for it - if err := os.Symlink("/usr/bin/ros", "/usr/bin/system-docker"); err != nil { - log.Errorf("ln error %s", err) - } - cmd := exec.Command("system-docker", "ps", "-q") var outb bytes.Buffer cmd.Stdout = &outb @@ -626,20 +652,18 @@ func setDiskpartitions(device, diskType string) error { return err } - bootflag := "boot" - if diskType == "gpt" { - bootflag = "legacy_boot" - } - log.Debugf("running parted") + log.Debugf("making single RANCHER_STATE partition") cmd = exec.Command("parted", "-s", "-a", "optimal", device, "mklabel "+diskType, "--", - "mkpart primary ext4 1 -1", - "set 1 "+bootflag+" on") + "mkpart primary ext4 1 -1") cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr if err := cmd.Run(); err != nil { log.Errorf("parted: %s", err) return err } + if err := setBootable(device, diskType); err != nil { + return err + } return nil } @@ -678,64 +702,76 @@ func formatdevice(device, partition string) error { return nil } -func mountdevice(baseName, bootDir, partition string, raw bool) (string, error) { +func mountdevice(baseName, bootDir, partition string, raw bool) (string, string, error) { log.Debugf("mountdevice %s, raw %v", partition, raw) + device := "" if raw { log.Debugf("util.Mount (raw) %s, %s", partition, baseName) - return bootDir, util.Mount(partition, baseName, "", "") + + cmd := exec.Command("lsblk", "-no", "pkname", partition) + log.Debugf("Run(%v)", cmd) + cmd.Stderr = os.Stderr + if out, err := cmd.Output(); err == nil { + device = "/dev/" + strings.TrimSpace(string(out)) + } + + return device, partition, util.Mount(partition, baseName, "", "") } - rootfs := partition + //rootfs := partition // Don't use ResolveDevice - it can fail, whereas `blkid -L LABEL` works more often //if dev := util.ResolveDevice("LABEL=RANCHER_BOOT"); dev != "" { cmd := exec.Command("blkid", "-L", "RANCHER_BOOT") log.Debugf("Run(%v)", cmd) cmd.Stderr = os.Stderr if out, err := cmd.Output(); err == nil { - rootfs = string(out) + partition = strings.TrimSpace(string(out)) } else { cmd := exec.Command("blkid", "-L", "RANCHER_STATE") log.Debugf("Run(%v)", cmd) cmd.Stderr = os.Stderr if out, err := cmd.Output(); err == nil { - rootfs = string(out) + partition = strings.TrimSpace(string(out)) } } - rootfs = strings.TrimSpace(rootfs) + cmd = exec.Command("lsblk", "-no", "pkname", partition) + log.Debugf("Run(%v)", cmd) + cmd.Stderr = os.Stderr + if out, err := cmd.Output(); err == nil { + device = "/dev/" + strings.TrimSpace(string(out)) + } - log.Debugf("util.Mount %s, %s", rootfs, baseName) - // return bootDir, util.Mount(rootfs, baseName, "", "") + log.Debugf("util.Mount %s, %s", partition, baseName) os.MkdirAll(baseName, 0755) - cmd = exec.Command("mount", rootfs, baseName) + cmd = exec.Command("mount", partition, baseName) log.Debugf("Run(%v)", cmd) //cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr - return bootDir, cmd.Run() - + return device, partition, cmd.Run() } -func formatAndMount(baseName, bootDir, device, partition string) (string, error) { +func formatAndMount(baseName, bootDir, device, partition string) (string, string, error) { log.Debugf("formatAndMount") err := formatdevice(device, partition) if err != nil { log.Errorf("formatdevice %s", err) - return bootDir, err + return device, partition, err } - bootDir, err = mountdevice(baseName, bootDir, partition, false) + device, partition, err = mountdevice(baseName, bootDir, partition, false) if err != nil { log.Errorf("mountdevice %s", err) - return bootDir, err + return device, partition, err } - err = createbootDirs(baseName, bootDir) - if err != nil { - log.Errorf("createbootDirs %s", err) - return bootDir, err - } - return bootDir, nil + //err = createbootDirs(baseName, bootDir) + //if err != nil { + // log.Errorf("createbootDirs %s", err) + // return bootDir, err + //} + return device, partition, nil } -func createbootDirs(baseName, bootDir string) error { +func NOPEcreatebootDir(baseName, bootDir string) error { log.Debugf("createbootDirs") if err := os.MkdirAll(filepath.Join(baseName, bootDir+"grub"), 0755); err != nil { @@ -747,6 +783,71 @@ func createbootDirs(baseName, bootDir string) error { 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 + + bootflag := "boot" + if diskType == "gpt" { + bootflag = "legacy_boot" + } + log.Debugf("making device 1 on %s bootable as %s", device, diskType) + cmd := exec.Command("parted", "-s", "-a", "optimal", device, "set 1 "+bootflag+" on") + cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr + if err := cmd.Run(); err != nil { + log.Errorf("parted: %s", err) + return err + } + return nil +} + +func upgradeBootloader(device, baseName, bootDir, diskType string) error { + log.Debugf("start upgradeBootloader") + + grubDir := filepath.Join(baseName, 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 + // TODO: in v0.9.0, need to detect what version syslinux we have + return nil + } + if err := setBootable(device, diskType); err != nil { + log.Debugf("setBootable(%s, %s): %s", device, diskType, err) + //return err + } + if err := os.Rename(grubDir, filepath.Join(baseName, bootDir+"grub_backup")); err != nil { + log.Debugf("Rename(%s): %s", grubDir, err) + return err + } + + syslinuxDir := filepath.Join(baseName, bootDir+"syslinux") + backupSyslinuxDir := filepath.Join(baseName, bootDir+"syslinux_backup") + if err := os.Rename(syslinuxDir, backupSyslinuxDir); err != nil { + log.Debugf("Rename(%s, %s): %s", syslinuxDir, backupSyslinuxDir, err) + return err + } + //mv the old syslinux into linux-previous.cfg + oldSyslinux, err := ioutil.ReadFile(filepath.Join(backupSyslinuxDir, "syslinux.cfg")) + if err != nil { + log.Debugf("read(%s / syslinux.cfg): %s", backupSyslinuxDir, err) + + return err + } + cfg := string(oldSyslinux) + //DEFAULT RancherOS-current + // + //LABEL RancherOS-current + // LINUX ../vmlinuz-v0.7.1-rancheros + // APPEND rancher.state.dev=LABEL=RANCHER_STATE rancher.state.wait console=tty0 rancher.password=rancher + // INITRD ../initrd-v0.7.1-rancheros + cfg = strings.Replace(cfg, "current", "previous", -1) + cfg = strings.Replace(cfg, "../", "/boot/", -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) + + return installSyslinux(device, baseName, bootDir, diskType) +} + func installSyslinux(device, baseName, bootDir, diskType string) error { log.Debugf("installSyslinux") @@ -765,6 +866,10 @@ func installSyslinux(device, baseName, bootDir, diskType string) error { log.Errorf("dd: %s", err) return err } + if err := os.MkdirAll(filepath.Join(baseName, bootDir+"syslinux"), 0755); err != nil { + return err + } + //cp /usr/lib/syslinux/modules/bios/* ${baseName}/${bootDir}syslinux files, _ := ioutil.ReadDir("/usr/share/syslinux/") for _, file := range files { @@ -810,6 +915,9 @@ func installSyslinuxRaid(baseName, bootDir, diskType string) error { log.Errorf("%s", err) return err } + if err := os.MkdirAll(filepath.Join(baseName, bootDir+"syslinux"), 0755); err != nil { + return err + } //cp /usr/lib/syslinux/modules/bios/* ${baseName}/${bootDir}syslinux files, _ := ioutil.ReadDir("/usr/share/syslinux/") for _, file := range files { @@ -821,7 +929,7 @@ func installSyslinuxRaid(baseName, bootDir, diskType string) error { return err } } - cmd = exec.Command("extlinux", "--install", filepath.Join(baseName, bootDir+"syslinux")) + cmd = exec.Command("extlinux", "--install", "--raid", filepath.Join(baseName, bootDir+"syslinux")) if err := cmd.Run(); err != nil { log.Errorf("%s", err) return err @@ -829,96 +937,20 @@ func installSyslinuxRaid(baseName, bootDir, diskType string) error { return nil } -func installGrub(baseName, device string) error { - log.Debugf("installGrub") - - //grub-install --boot-directory=${baseName}/boot ${device} - cmd := exec.Command("grub-install", "--boot-directory="+baseName+"/boot", device) - if err := cmd.Run(); err != nil { - log.Errorf("%s", err) - return err - } - return nil -} - -func grubConfig(menu bootVars) error { - log.Debugf("grubConfig") - - filetmpl, err := template.New("grub2config").Parse(`{{define "grub2menu"}}menuentry "{{.Name}}" { - set root=(hd0,msdos1) - linux /{{.bootDir}}vmlinuz-{{.Version}}-rancheros {{.KernelArgs}} {{.Append}} - initrd /{{.bootDir}}initrd-{{.Version}}-rancheros -} - -{{end}} -set default="0" -set timeout="{{.Timeout}}" -{{if .Fallback}}set fallback={{.Fallback}}{{end}} - -{{- range .Entries}} -{{template "grub2menu" .}} -{{- end}} - -`) - if err != nil { - log.Errorf("grub2config %s", err) - return err - } - - cfgFile := filepath.Join(menu.baseName, menu.bootDir+"grub/grub.cfg") - log.Debugf("grubConfig written to %s", cfgFile) - - f, err := os.Create(cfgFile) - if err != nil { - return err - } - err = filetmpl.Execute(f, menu) - if err != nil { - return err - } - return nil -} - -func syslinuxConfig(menu bootVars) error { - log.Debugf("syslinuxConfig") - - filetmpl, err := template.New("syslinuxconfig").Parse(`{{define "syslinuxmenu"}} -LABEL {{.Name}} - LINUX ../vmlinuz-{{.Version}}-rancheros - APPEND {{.KernelArgs}} {{.Append}} - INITRD ../initrd-{{.Version}}-rancheros -{{end}} -TIMEOUT 20 #2 seconds -DEFAULT RancherOS-current - -{{- range .Entries}} -{{template "syslinuxmenu" .}} -{{- end}} - -`) - if err != nil { - log.Errorf("syslinuxconfig %s", err) - return err - } - - cfgFile := filepath.Join(menu.baseName, menu.bootDir+"syslinux/syslinux.cfg") - log.Debugf("syslinuxConfig written to %s", cfgFile) - f, err := os.Create(cfgFile) - if err != nil { - log.Errorf("Create(%s) %s", cfgFile, err) - return err - } - err = filetmpl.Execute(f, menu) - if err != nil { - return err - } - return nil -} - func installRancher(baseName, bootDir, VERSION, DIST, kappend string) error { log.Debugf("installRancher") - // TODO detect if there already is a linux-current.cfg, if so, move it to linux-previous.cfg, and replace only current with the one in the image/iso + // 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") + if _, err := os.Stat(currentCfg); !os.IsNotExist(err) { + previousCfg := filepath.Join(baseName, bootDir, "linux-previous.cfg") + if _, err := os.Stat(previousCfg); !os.IsNotExist(err) { + if err := os.Remove(previousCfg); err != nil { + return err + } + } + os.Rename(currentCfg, previousCfg) + } // The image/ISO have all the files in it - the syslinux cfg's and the kernel&initrd, so we can copy them all from there files, _ := ioutil.ReadDir(DIST) @@ -931,11 +963,12 @@ func installRancher(baseName, bootDir, VERSION, DIST, kappend string) error { return err } } - // the main syslinuxcfg + // the general INCLUDE syslinuxcfg if err := dfs.CopyFile(filepath.Join(DIST, "isolinux", "isolinux.cfg"), filepath.Join(baseName, bootDir, "syslinux"), "syslinux.cfg"); err != nil { log.Errorf("copy %s: %s", "syslinux.cfg", err) return err } + // The global.cfg INCLUDE - useful for over-riding the APPEND line err := ioutil.WriteFile(filepath.Join(filepath.Join(baseName, bootDir), "global.cfg"), []byte("APPEND "+kappend), 0644) if err != nil { @@ -944,45 +977,3 @@ func installRancher(baseName, bootDir, VERSION, DIST, kappend string) error { } return nil } - -func pvGrubConfig(menu bootVars) error { - log.Debugf("pvGrubConfig") - - filetmpl, err := template.New("grublst").Parse(`{{define "grubmenu"}} -title RancherOS {{.Version}}-({{.Name}}) -root (hd0) -kernel /${bootDir}vmlinuz-{{.Version}}-rancheros {{.KernelArgs}} {{.Append}} -initrd /${bootDir}initrd-{{.Version}}-rancheros - -{{end}} -default 0 -timeout {{.Timeout}} -{{if .Fallback}}fallback {{.Fallback}}{{end}} -hiddenmenu - -{{- range .Entries}} -{{template "grubmenu" .}} -{{- end}} - -`) - if err != nil { - log.Errorf("pv grublst: %s", err) - - return err - } - - cfgFile := filepath.Join(menu.baseName, menu.bootDir+"grub/menu.lst") - log.Debugf("grubMenu written to %s", cfgFile) - f, err := os.Create(cfgFile) - if err != nil { - log.Errorf("Create(%s) %s", cfgFile, err) - - return err - } - err = filetmpl.Execute(f, menu) - if err != nil { - log.Errorf("execute %s", err) - return err - } - return nil -} diff --git a/cmd/control/install/grub.go b/cmd/control/install/grub.go new file mode 100644 index 00000000..79ffbc58 --- /dev/null +++ b/cmd/control/install/grub.go @@ -0,0 +1,102 @@ +package install + +import ( + "html/template" + "os" + "os/exec" + "path/filepath" + + "github.com/rancher/os/log" +) + +func RunGrub(baseName, device string) error { + log.Debugf("installGrub") + + //grub-install --boot-directory=${baseName}/boot ${device} + cmd := exec.Command("grub-install", "--boot-directory="+baseName+"/boot", device) + if err := cmd.Run(); err != nil { + log.Errorf("%s", err) + return err + } + return nil +} + +func grubConfig(menu BootVars) error { + log.Debugf("grubConfig") + + filetmpl, err := template.New("grub2config").Parse(`{{define "grub2menu"}}menuentry "{{.Name}}" { + set root=(hd0,msdos1) + linux /{{.bootDir}}vmlinuz-{{.Version}}-rancheros {{.KernelArgs}} {{.Append}} + initrd /{{.bootDir}}initrd-{{.Version}}-rancheros +} + +{{end}} +set default="0" +set timeout="{{.Timeout}}" +{{if .Fallback}}set fallback={{.Fallback}}{{end}} + +{{- range .Entries}} +{{template "grub2menu" .}} +{{- end}} + +`) + if err != nil { + log.Errorf("grub2config %s", err) + return err + } + + cfgFile := filepath.Join(menu.BaseName, menu.BootDir+"grub/grub.cfg") + log.Debugf("grubConfig written to %s", cfgFile) + + f, err := os.Create(cfgFile) + if err != nil { + return err + } + err = filetmpl.Execute(f, menu) + if err != nil { + return err + } + return nil +} + +func PvGrubConfig(menu BootVars) error { + log.Debugf("pvGrubConfig") + + filetmpl, err := template.New("grublst").Parse(`{{define "grubmenu"}} +title RancherOS {{.Version}}-({{.Name}}) +root (hd0) +kernel /${bootDir}vmlinuz-{{.Version}}-rancheros {{.KernelArgs}} {{.Append}} +initrd /${bootDir}initrd-{{.Version}}-rancheros + +{{end}} +default 0 +timeout {{.Timeout}} +{{if .Fallback}}fallback {{.Fallback}}{{end}} +hiddenmenu + +{{- range .Entries}} +{{template "grubmenu" .}} +{{- end}} + +`) + if err != nil { + log.Errorf("pv grublst: %s", err) + + return err + } + + cfgFile := filepath.Join(menu.BaseName, menu.BootDir+"grub/menu.lst") + log.Debugf("grubMenu written to %s", cfgFile) + f, err := os.Create(cfgFile) + if err != nil { + log.Errorf("Create(%s) %s", cfgFile, err) + + return err + } + err = filetmpl.Execute(f, menu) + if err != nil { + log.Errorf("execute %s", err) + return err + } + return nil +} diff --git a/cmd/control/install/install.go b/cmd/control/install/install.go new file mode 100644 index 00000000..0cb50e29 --- /dev/null +++ b/cmd/control/install/install.go @@ -0,0 +1,11 @@ +package install + +type MenuEntry struct { + Name, BootDir, Version, KernelArgs, Append string +} +type BootVars struct { + BaseName, BootDir string + Timeout uint + Fallback int + Entries []MenuEntry +} diff --git a/cmd/control/install/syslinux.go b/cmd/control/install/syslinux.go new file mode 100644 index 00000000..9895a702 --- /dev/null +++ b/cmd/control/install/syslinux.go @@ -0,0 +1,45 @@ +package install + +import ( + "html/template" + "os" + "path/filepath" + + "github.com/rancher/os/log" +) + +func syslinuxConfig(menu BootVars) error { + log.Debugf("syslinuxConfig") + + filetmpl, err := template.New("syslinuxconfig").Parse(`{{define "syslinuxmenu"}} +LABEL {{.Name}} + LINUX ../vmlinuz-{{.Version}}-rancheros + APPEND {{.KernelArgs}} {{.Append}} + INITRD ../initrd-{{.Version}}-rancheros +{{end}} +TIMEOUT 20 #2 seconds +DEFAULT RancherOS-current + +{{- range .Entries}} +{{template "syslinuxmenu" .}} +{{- end}} + +`) + if err != nil { + log.Errorf("syslinuxconfig %s", err) + return err + } + + cfgFile := filepath.Join(menu.BaseName, menu.BootDir+"syslinux/syslinux.cfg") + log.Debugf("syslinuxConfig written to %s", cfgFile) + f, err := os.Create(cfgFile) + if err != nil { + log.Errorf("Create(%s) %s", cfgFile, err) + return err + } + err = filetmpl.Execute(f, menu) + if err != nil { + return err + } + return nil +} diff --git a/log/log.go b/log/log.go index 92603c9e..aea5108e 100644 --- a/log/log.go +++ b/log/log.go @@ -117,9 +117,7 @@ func InitLogger() { return } - // TODO: look into containerized syslog - //filename := "/dev/kmsg" - filename := "/var/log/log" + filename := "/dev/kmsg" f, err := os.OpenFile(filename, os.O_WRONLY, 0644) if err != nil { logrus.Debugf("error opening %s: %s", filename, err) diff --git a/os-config.tpl.yml b/os-config.tpl.yml index e2c58e50..7ad2606e 100644 --- a/os-config.tpl.yml +++ b/os-config.tpl.yml @@ -150,7 +150,6 @@ rancher: - /usr/bin/iptables:/sbin/iptables:ro - /media:/media:shared - /mnt:/mnt:shared - - /:/host container-data-volumes: image: {{.OS_REPO}}/os-base:{{.VERSION}}{{.SUFFIX}} command: echo diff --git a/scripts/installer/BaseDockerfile.amd64 b/scripts/installer/BaseDockerfile.amd64 index d293930c..2bfd7198 100644 --- a/scripts/installer/BaseDockerfile.amd64 +++ b/scripts/installer/BaseDockerfile.amd64 @@ -6,17 +6,18 @@ ARG KERNEL_VERSION ENV VERSION=${VERSION} ENV KERNEL_VERSION=${KERNEL_VERSION} -# not installed atm udev, grub2, kexe-toos +# not installed atm udev, grub2, kexe-tools # parted: partprobe, e2fsprogs: mkfs.ext4, syslinux: extlinux&syslinux -RUN apk --no-cache add syslinux parted e2fsprogs +RUN apk --no-cache add syslinux parted e2fsprogs util-linux COPY conf /scripts/ COPY ./build/ros /bin/ +#RUN cd /bin && ln -s ./ros ./system-docker #OR softlink in the host one - this image should only be used when installing from ISO.. # (except its useful for testing) # && ln -s /host/usr/bin/ros /bin/ RUN ln -s /bootiso/boot/ /dist -ENTRYPOINT ["/bin/ros"] +ENTRYPOINT ["/bin/ros", "install"] diff --git a/scripts/installer/Dockerfile.amd64 b/scripts/installer/Dockerfile.amd64 index 05145e6f..ddd1fbfa 100755 --- a/scripts/installer/Dockerfile.amd64 +++ b/scripts/installer/Dockerfile.amd64 @@ -4,8 +4,6 @@ FROM rancher/os-installer RUN rm /dist/ \ && mkdir -p /dist/ -# Run docker build in the `./build/` dir #COPY ./ros /bin/ -#needs to be a recursive copy -COPY ./ /dist/ +COPY ./boot/ /dist/ diff --git a/scripts/installer/lay-down-os b/scripts/installer/lay-down-os index 5a7f5de5..40ef566c 100755 --- a/scripts/installer/lay-down-os +++ b/scripts/installer/lay-down-os @@ -16,10 +16,11 @@ do c) CLOUD_CONFIG="$OPTARG" ;; a) APPEND="$OPTARG" ;; g) MBR_FILE=gptmbr.bin ;; - # used for testing? - k) KEXEC=y ;; - p) PARTITION="$OPTARG" ;; + # upgrade! r) ROLLBACK_VERSION="$OPTARG" ;; + k) KEXEC=y ;; + # used for testing? + p) PARTITION="$OPTARG" ;; # notused? i) DIST="$OPTARG" ;; f) FILES="$OPTARG" ;; diff --git a/scripts/package-installer b/scripts/package-installer index cb9695c6..9f9ad785 100755 --- a/scripts/package-installer +++ b/scripts/package-installer @@ -12,7 +12,7 @@ if [ ! -f $DOCKERFILE ] || [ ! -f dist/artifacts/vmlinuz-${KERNEL_VERSION} ] || exit 0 fi -# TODO maybe extract the cration of the syslinux cfg files +# TODO maybe extract the creation of the syslinux cfg files mkdir -p ${DIST}/boot/isolinux/ cat scripts/isolinux.cfg | envsubst > ${DIST}/boot/isolinux/isolinux.cfg cat scripts/isolinux_label.cfg | LABEL=${VERSION} envsubst > ${DIST}/boot/linux-current.cfg @@ -20,11 +20,8 @@ cat scripts/isolinux_label.cfg | LABEL=${VERSION} envsubst > ${DIST}/boot/linu cat scripts/global.cfg | LABEL=${VERSION} envsubst > ${DIST}/boot/global.cfg -mkdir -p ./scripts/installer/build -cp ./dist/artifacts/initrd ./scripts/installer/build -cp ./dist/artifacts/vmlinuz-${KERNEL_VERSION} ./scripts/installer/build +mkdir -p ./scripts/installer/build/boot cp ./bin/ros ./scripts/installer/build -cp -r ${DIST}/boot/* ./scripts/installer/build/ trap "rm -rf ./scripts/installer/build" EXIT # installer base image - can be included in iso @@ -36,12 +33,16 @@ docker build \ -f $BASEDOCKERFILE \ ./scripts/installer docker save -o dist/artifacts/installer.tar ${OS_REPO}/os-installer +cp $DOCKERFILE dist/artifacts/ +cp ./dist/artifacts/initrd ./scripts/installer/build/boot +cp ./dist/artifacts/vmlinuz-${KERNEL_VERSION} ./scripts/installer/build/boot +cp -r ${DIST}/boot/* ./scripts/installer/build/boot +cp $DOCKERFILE ./scripts/installer/build/Dockerfile # Full installer image with initrd - used for pulling from network docker build \ -t ${OS_REPO}/os:${VERSION}${SUFFIX} \ - -f $DOCKERFILE \ - ./scripts/installer + ./scripts/installer/build docker save -o dist/artifacts/fullinstaller.tar ${OS_REPO}/os:${VERSION}${SUFFIX} echo ${OS_REPO}/os:${VERSION}${SUFFIX} >> dist/images diff --git a/scripts/package-iso b/scripts/package-iso index 66a23ab6..c549eb24 100755 --- a/scripts/package-iso +++ b/scripts/package-iso @@ -32,6 +32,7 @@ cp /usr/lib/ISOLINUX/isolinux.bin ${CD}/boot/isolinux/ cp /usr/lib/syslinux/modules/bios/ldlinux.c32 ${CD}/boot/isolinux/ # add the installer image to the iso for non-network / dev/test cp ${ARTIFACTS}/installer.tar ${CD}/rancheros/ +cp ${ARTIFACTS}/Dockerfile.amd64 ${CD}/rancheros/ gzip ${CD}/rancheros/installer.tar cd ${CD} && xorriso \ -as mkisofs \ diff --git a/scripts/run b/scripts/run index 5452ca5c..b5abe8a9 100755 --- a/scripts/run +++ b/scripts/run @@ -65,8 +65,9 @@ while [ "$#" -gt 0 ]; do --fresh) FRESH=1 ;; - --nodisplay) - NODISPLAY=1 + --console) + # use the bios console, not serial (lets you see syslinux) + CONSOLEDISPLAY=1 ;; --installed) INSTALLED=1 @@ -154,6 +155,13 @@ if [ "$QIND" != "1" ]; then HOME=${HOME:-/} fi +if [ "$CONSOLEDISPLAY" == "1" ]; then + DISPLAY_OPTS="-curses" +else + # default + DISPLAY_OPTS="-nographic -serial stdio -display none" +fi + if [ "$QEMU" == "1" ]; then if [ "$INSTALLED" == "1" ]; then @@ -164,7 +172,7 @@ if [ "$QEMU" == "1" ]; then fi set -x exec qemu-system-${QEMUARCH} \ - -serial stdio \ + ${DISPLAY_OPTS} \ -rtc base=utc,clock=host \ ${INSTALLED_ARGS} \ -append "${KERNEL_ARGS}" \ @@ -176,8 +184,6 @@ if [ "$QEMU" == "1" ]; then $(eval "${hd["$ARCH"]} ${HD}") \ ${SECOND_DRIVE_ENABLE} \ -smp 1 \ - -nographic \ - -display none \ -fsdev local,security_model=passthrough,readonly,id=fsdev0,path=${CCROOT} \ -device virtio-9p-pci,id=fs0,fsdev=fsdev0,mount_tag=config-2 \ -fsdev local,security_model=none,id=fsdev1,path=${HOME} \ @@ -195,11 +201,6 @@ elif [ "$BOOT_ISO" == "1" ] || -device virtio-9p-pci,id=fs1,fsdev=fsdev1,mount_tag=home " echo "----- $ISO_OPTS" fi - if [ "$NODISPLAY" == "1" ]; then - DISPLAY_OPTS="-nographic -serial stdio -display none" - else - DISPLAY_OPTS="-curses" - fi set -x exec qemu-system-${QEMUARCH} \ ${DISPLAY_OPTS} \ diff --git a/tests/common_test.go b/tests/common_test.go index 8233ae66..a2305878 100644 --- a/tests/common_test.go +++ b/tests/common_test.go @@ -17,6 +17,7 @@ func init() { Suite(&QemuSuite{ runCommand: "../scripts/run", sshCommand: "../scripts/ssh", + qemuCmd: nil, }) } @@ -42,14 +43,15 @@ type QemuSuite struct { } func (s *QemuSuite) TearDownTest(c *C) { - c.Assert(s.qemuCmd.Process.Kill(), IsNil) - time.Sleep(time.Millisecond * 1000) + if s.qemuCmd != nil { + s.Stop(c) + } } // RunQemuWith requires user to specify all the `scripts/run` arguments func (s *QemuSuite) RunQemuWith(c *C, additionalArgs ...string) error { - err := s.runQemu(additionalArgs...) + err := s.runQemu(c, additionalArgs...) c.Assert(err, IsNil) return err } @@ -79,13 +81,15 @@ func (s *QemuSuite) RunQemuInstalled(c *C, additionalArgs ...string) error { return err } -func (s *QemuSuite) runQemu(args ...string) error { +func (s *QemuSuite) runQemu(c *C, args ...string) error { + c.Assert(s.qemuCmd, IsNil) // can't run 2 qemu's at once (yet) s.qemuCmd = exec.Command(s.runCommand, args...) - s.qemuCmd.Stdout = os.Stdout + //s.qemuCmd.Stdout = os.Stdout s.qemuCmd.Stderr = os.Stderr if err := s.qemuCmd.Start(); err != nil { return err } + fmt.Printf("--- %s: starting qemu %s, %v\n", c.TestName(), s.runCommand, args) return s.WaitForSSH() } @@ -148,11 +152,17 @@ func (s *QemuSuite) Stop(c *C) { //s.MakeCall("sudo halt") //time.Sleep(2000 * time.Millisecond) //c.Assert(s.WaitForSSH(), IsNil) + + //fmt.Println("%s: stopping qemu", c.TestName()) c.Assert(s.qemuCmd.Process.Kill(), IsNil) - time.Sleep(time.Millisecond * 1000) + s.qemuCmd.Process.Wait() + //time.Sleep(time.Millisecond * 1000) + s.qemuCmd = nil + fmt.Printf("--- %s: qemu stopped", c.TestName()) } func (s *QemuSuite) Reboot(c *C) { + fmt.Printf("--- %s: qemu reboot", c.TestName()) s.MakeCall("sudo reboot") time.Sleep(3000 * time.Millisecond) c.Assert(s.WaitForSSH(), IsNil) diff --git a/tests/installer_test.go b/tests/installer_test.go index 7a3c330e..1bfdb364 100644 --- a/tests/installer_test.go +++ b/tests/installer_test.go @@ -1,20 +1,19 @@ package integration -import . "gopkg.in/check.v1" +import ( + "time" -// TODO: separate out into different tests - there's something that makes one pass and one fail. + . "gopkg.in/check.v1" +) -//func (s *QemuSuite) TestInstallMsDosMbr(c *C) { -func (s *QemuSuite) TestInstall(c *C) { +func (s *QemuSuite) TestInstallMsDosMbr(c *C) { // ./scripts/run --no-format --append "rancher.debug=true" --iso --fresh runArgs := []string{ "--iso", "--fresh", - "--nodisplay", } { s.RunQemuWith(c, runArgs...) - defer s.Stop(c) s.CheckCall(c, ` echo "---------------------------------- generic" @@ -22,30 +21,33 @@ set -ex sudo parted /dev/vda print echo "ssh_authorized_keys:" > config.yml echo " - $(cat /home/rancher/.ssh/authorized_keys)" >> config.yml -sudo ros install --force --no-reboot --device /dev/vda -c config.yml`) +sudo ros install --force --no-reboot --device /dev/vda -c config.yml --append rancher.password=rancher +sync +`) + time.Sleep(500 * time.Millisecond) + s.Stop(c) } // ./scripts/run --no-format --append "rancher.debug=true" runArgs = []string{ "--boothd", - "--nodisplay", } s.RunQemuWith(c, runArgs...) - defer s.Stop(c) s.CheckCall(c, "sudo ros -v") - //} + s.Stop(c) +} - //func (s *QemuSuite) TestInstallGptMbr(c *C) { +func (s *QemuSuite) TestInstallGptMbr(c *C) { // ./scripts/run --no-format --append "rancher.debug=true" --iso --fresh - runArgs = []string{ + runArgs := []string{ "--iso", "--fresh", - "--nodisplay", } { s.RunQemuWith(c, runArgs...) - defer s.Stop(c) + + s.CheckCall(c, "sudo ros -v") // sha from latest. s.CheckCall(c, ` echo "---------------------------------- gptsyslinux" @@ -53,17 +55,88 @@ set -ex sudo parted /dev/vda print echo "ssh_authorized_keys:" > config.yml echo " - $(cat /home/rancher/.ssh/authorized_keys)" >> config.yml -sudo ros install --force --no-reboot --device /dev/vda -t gptsyslinux -c config.yml`) +sudo ros install --force --no-reboot --device /dev/vda -t gptsyslinux -c config.yml +sync +`) + time.Sleep(500 * time.Millisecond) + s.Stop(c) } // ./scripts/run --no-format --append "rancher.debug=true" runArgs = []string{ "--boothd", - "--nodisplay", } s.RunQemuWith(c, runArgs...) - defer s.Stop(c) s.CheckCall(c, "sudo ros -v") // TEST parted output? (gpt non-uefi == legacy_boot) + s.Stop(c) +} + +func (s *QemuSuite) TestUpgradeFromImage(c *C) { + // ./scripts/run --no-format --append "rancher.debug=true" --iso --fresh + + //TODO: --fresh isn't giving us a new disk why? (that's what the parted print is for atm) + runArgs := []string{ + "--iso", + "--fresh", + } + { + s.RunQemuWith(c, runArgs...) + + s.CheckCall(c, "sudo ros -v") // sha + s.CheckCall(c, "sudo uname -a") + //TODO: detect "last release, and install that + s.CheckCall(c, ` +echo "---------------------------------- generic" +set -ex +sudo parted /dev/vda print +echo "ssh_authorized_keys:" > config.yml +echo " - $(cat /home/rancher/.ssh/authorized_keys)" >> config.yml +sudo ros install --force --no-reboot --device /dev/vda -c config.yml -i rancher/os:v0.7.1 --append "console=ttyS0 rancher.password=rancher" +#TODO copy installer image, new ros, and new kernel to HD, so we can fake things up next time? (or have next boot from HD, but have the iso available..) +sudo mkdir -p /bootiso +sudo mount -t iso9660 /dev/sr0 /bootiso/ +sudo mount /dev/vda1 /mnt/ +sudo mkdir -p /mnt/rancher-installer/build/ +sudo cp /bootiso/rancheros/installer.tar.gz /mnt/rancher-installer/build/ +sudo cp /bootiso/rancheros/Dockerfile.amd64 /mnt/rancher-installer/build/ +sudo cp -r /bootiso/boot /mnt/rancher-installer/build/ +sudo cp /bin/ros /mnt/rancher-installer/build/ +sync +`) + time.Sleep(500 * time.Millisecond) + s.Stop(c) + } + + { + runArgs = []string{ + "--boothd", + } + s.RunQemuWith(c, runArgs...) + + s.CheckCall(c, "sudo ros -v") // v0.7.1 + s.CheckCall(c, "sudo uname -a") + + // load the installer.tar.gz, get the other install files into an image, and runit. + s.CheckCall(c, `sudo system-docker run --name builder -dt --volumes-from system-volumes -v /:/host alpine sh + sudo system-docker exec -t builder ln -s /host/rancher-installer/build/ros /bin/system-docker + sudo system-docker exec -t builder system-docker load -i /host/rancher-installer/build/installer.tar.gz + sudo system-docker exec -t builder system-docker build -t qwer -f /host/rancher-installer/build/Dockerfile.amd64 /host/rancher-installer/build + sudo ros os upgrade -i qwer --no-reboot -f --append "console=tty0 console=ttyS0 rancher.password=rancher" + sync + `) + time.Sleep(500 * time.Millisecond) + s.Stop(c) + } + + // ./scripts/run --no-format --append "rancher.debug=true" + runArgs = []string{ + "--boothd", + } + s.RunQemuWith(c, runArgs...) + + s.CheckCall(c, "sudo ros -v") // whatever sha we had in iso boot + s.CheckCall(c, "sudo uname -a") + s.Stop(c) }