mirror of
https://github.com/rancher/os.git
synced 2025-07-13 06:34:04 +00:00
commit
ab6cba20ff
@ -59,6 +59,7 @@ func Main() {
|
||||
HideHelp: true,
|
||||
Subcommands: tlsConfCommands(),
|
||||
},
|
||||
installCommand,
|
||||
}
|
||||
|
||||
app.Run(os.Args)
|
||||
|
126
cmd/control/install.go
Normal file
126
cmd/control/install.go
Normal file
@ -0,0 +1,126 @@
|
||||
package control
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
|
||||
log "github.com/Sirupsen/logrus"
|
||||
|
||||
"github.com/codegangsta/cli"
|
||||
"github.com/rancherio/os/cmd/power"
|
||||
"github.com/rancherio/os/config"
|
||||
"github.com/rancherio/os/util"
|
||||
)
|
||||
|
||||
var installCommand = cli.Command{
|
||||
Name: "install",
|
||||
Usage: "install RancherOS to disk",
|
||||
HideHelp: true,
|
||||
Action: installAction,
|
||||
Flags: []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "image, i",
|
||||
Usage: "install from a certain image",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "install-type, t",
|
||||
Usage: `generic: (Default) Creates 1 ext4 partition and installs RancherOS
|
||||
amazon-ebs: Installs RancherOS and sets up PV-GRUB`,
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "cloud-config, c",
|
||||
Usage: "cloud-config yml file - needed for SSH authorized keys",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "device, d",
|
||||
Usage: "storage device",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "force, f",
|
||||
Usage: "[ DANGEROUS! Data loss can happen ] partition/format without prompting",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "no-reboot",
|
||||
Usage: "do not reboot after install",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
func installAction(c *cli.Context) {
|
||||
if c.Args().Present() {
|
||||
log.Fatalf("invalid arguments %v", c.Args())
|
||||
}
|
||||
device := c.String("device")
|
||||
if device == "" {
|
||||
log.Fatal("Can not proceed without -d <dev> specified")
|
||||
}
|
||||
|
||||
image := c.String("image")
|
||||
cfg, err := config.LoadConfig()
|
||||
if err != nil {
|
||||
log.WithFields(log.Fields{"err": err}).Fatal("ros install: failed to load config")
|
||||
}
|
||||
if image == "" {
|
||||
image = cfg.Rancher.Upgrade.Image + ":" + config.VERSION
|
||||
}
|
||||
|
||||
installType := c.String("install-type")
|
||||
if installType == "" {
|
||||
log.Info("No install type specified...defaulting to generic")
|
||||
installType = "generic"
|
||||
}
|
||||
|
||||
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")
|
||||
} else {
|
||||
uc := "/opt/user_config.yml"
|
||||
if err := util.FileCopy(cloudConfig, uc); err != nil {
|
||||
log.WithFields(log.Fields{"cloudConfig": cloudConfig}).Fatal("Failed to copy cloud-config")
|
||||
}
|
||||
cloudConfig = uc
|
||||
}
|
||||
|
||||
force := c.Bool("force")
|
||||
reboot := !c.Bool("no-reboot")
|
||||
|
||||
if err := runInstall(cfg, image, installType, cloudConfig, device, force, reboot); err != nil {
|
||||
log.WithFields(log.Fields{"err": err}).Fatal("Failed to run install")
|
||||
}
|
||||
}
|
||||
|
||||
func runInstall(cfg *config.CloudConfig, image, installType, cloudConfig, device string, force, reboot bool) error {
|
||||
in := bufio.NewReader(os.Stdin)
|
||||
|
||||
fmt.Printf("Installing from %s\n", image)
|
||||
|
||||
if !force {
|
||||
if !yes(in, "Continue") {
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
if installType == "generic" {
|
||||
cmd := exec.Command("system-docker", "run", "--net=host", "--privileged", "--volumes-from=all-volumes",
|
||||
"--entrypoint=/scripts/set-disk-partitions", image, device)
|
||||
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", image,
|
||||
"-d", device, "-t", installType, "-c", cloudConfig)
|
||||
cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr
|
||||
if err := cmd.Run(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if reboot && yes(in, "Continue with reboot") {
|
||||
log.Info("Rebooting")
|
||||
power.Reboot()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
2
scripts/installer/conf/empty.yml
Normal file
2
scripts/installer/conf/empty.yml
Normal file
@ -0,0 +1,2 @@
|
||||
#cloud-config
|
||||
{}
|
@ -19,6 +19,7 @@ do
|
||||
done
|
||||
|
||||
DIST=${DIST:-/dist}
|
||||
CLOUD_CONFIG=${CLOUD_CONFIG:-/scripts/conf/empty.yml}
|
||||
BASE_DIR="/mnt/new_img"
|
||||
# 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.
|
||||
|
@ -12,8 +12,9 @@ if [ -z ${BASE_DIR} ]; then
|
||||
fi
|
||||
|
||||
mkdir -p ${BASE_DIR}/var/lib/rancher/conf/cloud-config.d
|
||||
|
||||
cp ${CLOUD_DATA} ${BASE_DIR}/var/lib/rancher/conf/cloud-config.d/
|
||||
if [ "$CLOUD_DATA" != "/scripts/conf/empty.yml" ]; then
|
||||
cp ${CLOUD_DATA} ${BASE_DIR}/var/lib/rancher/conf/cloud-config.d/
|
||||
fi
|
||||
|
||||
for f in ${FILES[@]}; do
|
||||
IFS=":" read s d <<< "${f}"
|
||||
|
19
util/util.go
19
util/util.go
@ -152,6 +152,25 @@ func RandSeq(n int) string {
|
||||
return string(b)
|
||||
}
|
||||
|
||||
func FileCopy(src, dest string) (err error) {
|
||||
in, err := os.Open(src)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() { err = in.Close() }()
|
||||
|
||||
out, err := os.Create(dest)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() { err = out.Close() }()
|
||||
|
||||
if _, err := io.Copy(out, in); err != nil {
|
||||
return err
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func Convert(from, to interface{}) error {
|
||||
bytes, err := yaml.Marshal(from)
|
||||
if err != nil {
|
||||
|
Loading…
Reference in New Issue
Block a user