1
0
mirror of https://github.com/rancher/os.git synced 2025-07-12 22:27:59 +00:00

Merge pull request #1724 from rancher/docker-container-install-to-partition

Fixed install --partition and added scripts/run-install to use it in …
This commit is contained in:
Sven Dowideit 2017-03-26 22:22:19 +10:00 committed by GitHub
commit 53c88bc505
3 changed files with 150 additions and 64 deletions

View File

@ -51,6 +51,10 @@ var installCommand = cli.Command{
Name: "device, d", Name: "device, d",
Usage: "storage device", Usage: "storage device",
}, },
cli.StringFlag{
Name: "partition, p",
Usage: "partition to install to",
},
cli.BoolFlag{ cli.BoolFlag{
Name: "force, f", Name: "force, f",
Usage: "[ DANGEROUS! Data loss can happen ] partition/format without prompting", Usage: "[ DANGEROUS! Data loss can happen ] partition/format without prompting",
@ -124,6 +128,7 @@ func installAction(c *cli.Context) error {
isoinstallerloaded = true // OMG this flag is aweful - kill it with fire isoinstallerloaded = true // OMG this flag is aweful - kill it with fire
} }
device := c.String("device") device := c.String("device")
partition := c.String("partition")
if installType != "noformat" && if installType != "noformat" &&
installType != "raid" && installType != "raid" &&
installType != "bootstrap" && installType != "bootstrap" &&
@ -141,14 +146,15 @@ func installAction(c *cli.Context) error {
log.Warn("Cloud-config not provided: you might need to provide cloud-config on bootDir with ssh_authorized_keys") log.Warn("Cloud-config not provided: you might need to provide cloud-config on bootDir with ssh_authorized_keys")
} }
} else { } else {
os.MkdirAll("/opt", 0755)
uc := "/opt/user_config.yml" uc := "/opt/user_config.yml"
if err := util.FileCopy(cloudConfig, uc); err != nil { if err := util.FileCopy(cloudConfig, uc); err != nil {
log.WithFields(log.Fields{"cloudConfig": cloudConfig}).Fatal("Failed to copy cloud-config") log.WithFields(log.Fields{"cloudConfig": cloudConfig, "error": err}).Fatal("Failed to copy cloud-config")
} }
cloudConfig = uc cloudConfig = uc
} }
if err := runInstall(image, installType, cloudConfig, device, kappend, force, kexec, isoinstallerloaded); err != nil { if err := runInstall(image, installType, cloudConfig, device, partition, kappend, force, kexec, isoinstallerloaded); err != nil {
log.WithFields(log.Fields{"err": err}).Fatal("Failed to run install") log.WithFields(log.Fields{"err": err}).Fatal("Failed to run install")
return err return err
} }
@ -161,7 +167,7 @@ func installAction(c *cli.Context) error {
return nil return nil
} }
func runInstall(image, installType, cloudConfig, device, kappend string, force, kexec, isoinstallerloaded bool) error { func runInstall(image, installType, cloudConfig, device, partition, kappend string, force, kexec, isoinstallerloaded bool) error {
fmt.Printf("Installing from %s\n", image) fmt.Printf("Installing from %s\n", image)
if !force { if !force {
@ -294,21 +300,29 @@ func runInstall(image, installType, cloudConfig, device, kappend string, force,
log.Debugf("running installation") log.Debugf("running installation")
if installType == "generic" || if partition != "" {
installType == "syslinux" ||
installType == "gptsyslinux" {
diskType := "msdos"
if installType == "gptsyslinux" {
diskType = "gpt"
}
log.Debugf("running setDiskpartitions")
err := setDiskpartitions(device, diskType)
if err != nil {
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 device = "/host" + device
partition = "/host" + partition
} else {
if installType == "generic" ||
installType == "syslinux" ||
installType == "gptsyslinux" {
diskType := "msdos"
if installType == "gptsyslinux" {
diskType = "gpt"
}
log.Debugf("running setDiskpartitions")
err := setDiskpartitions(device, diskType)
if err != nil {
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
//# 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}
}
} }
if installType == "upgrade" { if installType == "upgrade" {
@ -320,11 +334,11 @@ func runInstall(image, installType, cloudConfig, device, kappend string, force,
// TODO: detect if its not mounted and then optionally mount? // TODO: detect if its not mounted and then optionally mount?
if err := mountBootIso(); err != nil { if err := mountBootIso(); err != nil {
log.Errorf("error mountBootIso %s", err) log.Errorf("error mountBootIso %s", err)
return err //return err
} }
} }
err := layDownOS(image, installType, cloudConfig, device, kappend, kexec) err := layDownOS(image, installType, cloudConfig, device, partition, kappend, kexec)
if err != nil { if err != nil {
log.Errorf("error layDownOS %s", err) log.Errorf("error layDownOS %s", err)
return err return err
@ -366,7 +380,7 @@ func mountBootIso() error {
return err return err
} }
func layDownOS(image, installType, cloudConfig, device, kappend string, kexec bool) error { func layDownOS(image, installType, cloudConfig, device, partition, kappend string, kexec bool) error {
// ENV == installType // ENV == installType
//[[ "$ARCH" == "arm" && "$ENV" != "upgrade" ]] && ENV=arm //[[ "$ARCH" == "arm" && "$ENV" != "upgrade" ]] && ENV=arm
@ -380,9 +394,6 @@ func layDownOS(image, installType, cloudConfig, device, kappend string, kexec bo
CONSOLE := "tty0" CONSOLE := "tty0"
baseName := "/mnt/new_img" baseName := "/mnt/new_img"
bootDir := "boot/" 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}
kernelArgs := "rancher.state.dev=LABEL=RANCHER_STATE rancher.state.wait" // console="+CONSOLE kernelArgs := "rancher.state.dev=LABEL=RANCHER_STATE rancher.state.wait" // console="+CONSOLE
// unmount on trap // unmount on trap
@ -448,14 +459,14 @@ func layDownOS(image, installType, cloudConfig, device, kappend string, kexec bo
seedData(baseName, cloudConfig, FILES) seedData(baseName, cloudConfig, FILES)
case "noformat": case "noformat":
var err error var err error
device, partition, err = mountdevice(baseName, bootDir, partition, false) device, partition, err = mountdevice(baseName, bootDir, device, partition, false)
if err != nil { if err != nil {
return err return err
} }
installSyslinux(device, baseName, bootDir, diskType) installSyslinux(device, baseName, bootDir, diskType)
case "raid": case "raid":
var err error var err error
device, partition, err = mountdevice(baseName, bootDir, partition, false) device, partition, err = mountdevice(baseName, bootDir, device, partition, false)
if err != nil { if err != nil {
return err return err
} }
@ -463,7 +474,7 @@ func layDownOS(image, installType, cloudConfig, device, kappend string, kexec bo
case "bootstrap": case "bootstrap":
CONSOLE = "ttyS0" CONSOLE = "ttyS0"
var err error var err error
device, partition, err = mountdevice(baseName, bootDir, partition, true) device, partition, err = mountdevice(baseName, bootDir, device, partition, true)
if err != nil { if err != nil {
return err return err
} }
@ -473,7 +484,7 @@ func layDownOS(image, installType, cloudConfig, device, kappend string, kexec bo
fallthrough fallthrough
case "upgrade": case "upgrade":
var err error var err error
device, partition, err = mountdevice(baseName, bootDir, partition, false) device, partition, err = mountdevice(baseName, bootDir, device, partition, false)
if err != nil { if err != nil {
return err return err
} }
@ -706,53 +717,55 @@ func formatdevice(device, partition string) error {
return nil return nil
} }
func mountdevice(baseName, bootDir, partition string, raw bool) (string, string, error) { func mountdevice(baseName, bootDir, device, partition string, raw bool) (string, string, error) {
log.Debugf("mountdevice %s, raw %v", partition, raw) log.Debugf("mountdevice %s, raw %v", partition, raw)
if raw { if partition == "" {
log.Debugf("util.Mount (raw) %s, %s", partition, baseName) if raw {
log.Debugf("util.Mount (raw) %s, %s", partition, baseName)
cmd := exec.Command("lsblk", "-no", "pkname", partition)
log.Debugf("Run(%v)", cmd)
cmd.Stderr = os.Stderr
device := ""
// TODO: out can == "" - this is used to "detect software RAID" which is terrible
if out, err := cmd.Output(); err == nil {
device = "/dev/" + strings.TrimSpace(string(out))
}
log.Debugf("mountdevice return -> d: %s, p: %s", device, partition)
return device, partition, util.Mount(partition, baseName, "", "")
}
//rootfs := partition
// Don't use ResolveDevice - it can fail, whereas `blkid -L LABEL` works more often
cfg := config.LoadConfig()
if d, _ := util.Blkid("RANCHER_BOOT"); d != "" {
partition = d
baseName = filepath.Join(baseName, "boot")
} else {
if dev := util.ResolveDevice(cfg.Rancher.State.Dev); dev != "" {
// try the rancher.state.dev setting
partition = dev
} else {
if d, _ := util.Blkid("RANCHER_STATE"); d != "" {
partition = d
}
}
}
cmd := exec.Command("lsblk", "-no", "pkname", partition) cmd := exec.Command("lsblk", "-no", "pkname", partition)
log.Debugf("Run(%v)", cmd) log.Debugf("Run(%v)", cmd)
cmd.Stderr = os.Stderr cmd.Stderr = os.Stderr
device := "" // TODO: out can == "" - this is used to "detect software RAID" which is terrible
if out, err := cmd.Output(); err == nil { if out, err := cmd.Output(); err == nil {
device = "/dev/" + strings.TrimSpace(string(out)) device = "/dev/" + strings.TrimSpace(string(out))
} }
return device, partition, util.Mount(partition, baseName, "", "")
} }
//rootfs := partition
// Don't use ResolveDevice - it can fail, whereas `blkid -L LABEL` works more often
cfg := config.LoadConfig()
if d, _ := util.Blkid("RANCHER_BOOT"); d != "" {
partition = d
baseName = filepath.Join(baseName, "boot")
} else {
if dev := util.ResolveDevice(cfg.Rancher.State.Dev); dev != "" {
// try the rancher.state.dev setting
partition = dev
} else {
if d, _ := util.Blkid("RANCHER_STATE"); d != "" {
partition = d
}
}
}
device := ""
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", partition, baseName)
os.MkdirAll(baseName, 0755) os.MkdirAll(baseName, 0755)
cmd = exec.Command("mount", partition, baseName) cmd := exec.Command("mount", partition, baseName)
log.Debugf("Run(%v)", cmd)
//cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr //cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr
log.Debugf("mountdevice return2 -> d: %s, p: %s", device, partition)
return device, partition, cmd.Run() return device, partition, cmd.Run()
} }
@ -764,7 +777,7 @@ func formatAndMount(baseName, bootDir, device, partition string) (string, string
log.Errorf("formatdevice %s", err) log.Errorf("formatdevice %s", err)
return device, partition, err return device, partition, err
} }
device, partition, err = mountdevice(baseName, bootDir, partition, false) device, partition, err = mountdevice(baseName, bootDir, device, partition, false)
if err != nil { if err != nil {
log.Errorf("mountdevice %s", err) log.Errorf("mountdevice %s", err)
return device, partition, err return device, partition, err
@ -874,6 +887,7 @@ func upgradeBootloader(device, baseName, bootDir, diskType string) error {
} }
func installSyslinux(device, baseName, bootDir, diskType string) error { func installSyslinux(device, baseName, bootDir, diskType string) error {
log.Debugf("installSyslinux(%s)", device)
mbrFile := "mbr.bin" mbrFile := "mbr.bin"
if diskType == "gpt" { if diskType == "gpt" {

72
scripts/run-install Executable file
View File

@ -0,0 +1,72 @@
#!/bin/bash
# see https://forums.rancher.com/t/proposal-to-install-on-qemu/1236
set -x -e
cd $(dirname $0)/..
source ./scripts/version
BASE=$(pwd)
STATE=/tmp
DISK=${STATE}/rancheros.img
CONFIG=${STATE}/cloud-config.yml
export LOOPBACK=$(losetup -f)
PARTITION=$(echo "${LOOPBACK}p1" | sed 's/dev/dev\/mapper/')
DISPLAY_OPTS="-curses"
# default
#DISPLAY_OPTS="-nographic -serial stdio -display none"
function clean_up {
sudo umount mount || true
sudo kpartx -d ${DISK} || true
sudo losetup -d ${LOOPBACK} || true
sudo rm ${DISK} || true
}
trap "clean_up; exit" SIGHUP SIGINT SIGTERM EXIT
echo "writing to ${CONFIG} in ${STATE}"
echo "#cloud-config" > ${CONFIG}
echo "ssh_authorized_keys:" >> ${CONFIG}
echo "- $(<${BASE}/assets/rancher.key.pub)" >> ${CONFIG}
qemu-img create ${DISK} 1G
sudo losetup ${LOOPBACK} ${DISK}
echo "n
p
1
a
w" | sudo fdisk ${LOOPBACK} || true
sudo kpartx -a ${DISK}
docker run --privileged -it --rm \
-v /dev/mapper:/dev/mapper \
-v /:/host \
-v ${STATE}:/cluster \
rancher/os:${VERSION} \
--isoinstallerloaded=1 \
--force \
--no-reboot \
--debug \
-c /cluster/cloud-config.yml \
-t generic \
-d ${LOOPBACK} \
-p ${PARTITION} \
--append "rancher.autologin=tty1"
#-f /cluster/images.tar.xz:var/lib/system-docker/preload/images.tar.xz
sync
qemu-system-x86_64 -enable-kvm \
${DISPLAY_OPTS} \
-m 1024 \
-net nic,model=virtio \
-net user,hostfwd=tcp::2222-:22 \
-drive if=virtio,file=${DISK},format=raw

View File

@ -62,7 +62,7 @@ func Blkid(label string) (deviceName, deviceType string) {
s := bufio.NewScanner(r) s := bufio.NewScanner(r)
for s.Scan() { for s.Scan() {
line := s.Text() line := s.Text()
log.Debugf("blkid: %s", cmd, line) //log.Debugf("blkid: %s", cmd, line)
if !strings.Contains(line, `LABEL="`+label+`"`) { if !strings.Contains(line, `LABEL="`+label+`"`) {
continue continue
} }