From bb4ad618e1bfb637fd700b9a2f222ce79f4c0814 Mon Sep 17 00:00:00 2001 From: Josh Curl Date: Thu, 3 Nov 2016 15:06:20 -0700 Subject: [PATCH] Implement bootcmd --- cmd/cloudinitexecute/cloudinitexecute.go | 13 +------------ cmd/control/bootstrap.go | 2 ++ config/types.go | 1 + docs/os/configuration/running-commands/index.md | 15 ++++++++++++++- init/bootstrap.go | 2 +- util/util.go | 15 +++++++++++++++ 6 files changed, 34 insertions(+), 14 deletions(-) diff --git a/cmd/cloudinitexecute/cloudinitexecute.go b/cmd/cloudinitexecute/cloudinitexecute.go index fd924d84..5a557028 100644 --- a/cmd/cloudinitexecute/cloudinitexecute.go +++ b/cmd/cloudinitexecute/cloudinitexecute.go @@ -94,18 +94,7 @@ func ApplyConsole(cfg *rancherConfig.CloudConfig) { } } - for _, runcmd := range cfg.Runcmd { - if len(runcmd) == 0 { - continue - } - - cmd := exec.Command(runcmd[0], runcmd[1:]...) - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - if err := cmd.Run(); err != nil { - log.Errorf("Failed to run %s: %v", runcmd, err) - } - } + util.RunCommandSequence(cfg.Runcmd) } func WriteFiles(cfg *rancherConfig.CloudConfig, container string) { diff --git a/cmd/control/bootstrap.go b/cmd/control/bootstrap.go index 5051a506..b8b6cbb9 100644 --- a/cmd/control/bootstrap.go +++ b/cmd/control/bootstrap.go @@ -34,6 +34,8 @@ func bootstrapAction(c *cli.Context) error { } } + util.RunCommandSequence(cfg.Bootcmd) + if cfg.Rancher.State.Dev != "" && cfg.Rancher.State.Wait { waitForRoot(cfg) } diff --git a/config/types.go b/config/types.go index 33700668..2039daed 100644 --- a/config/types.go +++ b/config/types.go @@ -89,6 +89,7 @@ type CloudConfig struct { Mounts [][]string `yaml:"mounts,omitempty"` Rancher RancherConfig `yaml:"rancher,omitempty"` Runcmd [][]string `yaml:"runcmd,omitempty"` + Bootcmd [][]string `yaml:"bootcmd,omitempty"` } type File struct { diff --git a/docs/os/configuration/running-commands/index.md b/docs/os/configuration/running-commands/index.md index 3cb5f402..70177f61 100644 --- a/docs/os/configuration/running-commands/index.md +++ b/docs/os/configuration/running-commands/index.md @@ -21,7 +21,7 @@ Commands specified using `runcmd` will be executed within the context of the `co When using `runcmd`, RancherOS will wait for all commands to complete before starting Docker. As a result, any `docker run` command should not be placed under `runcmd`. Instead, the `/etc/rc.local` script can be used. RancherOS will not wait for commands in this script to complete, so you can use the `wait-for-docker` command to ensure that the Docker daemon is running before performing any `docker run` commands. -``` +```yaml #cloud-config rancher: write_files: @@ -35,3 +35,16 @@ write_files: ``` Running Docker commands in this manner is useful when pieces of the `docker run` command are dynamically generated. For services whose configuration is static, [adding a system service]({{site.baseurl}}/os/system-services/adding-system-services/) is recommended. + +## Running Commands Early in the Boot Process +--- + +The `bootcmd` parameter can be used to run commands earlier in the boot process. In particular, `bootcmd` will be executed while RancherOS is still running from memory and before System Docker and any system services are started. + +The syntax for bootcmd is the same as `runcmd`. + +```yaml +#cloud-config +bootcmd: +- [ mdadm, --assemble, --scan ] +``` diff --git a/init/bootstrap.go b/init/bootstrap.go index 026197bc..191da138 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) != "" { + if (len(cfg.Rancher.State.Autoformat) == 0 || util.ResolveDevice(cfg.Rancher.State.Dev) != "") && len(cfg.Bootcmd) == 0 { return cfg, nil } log.Info("Running Bootstrap") diff --git a/util/util.go b/util/util.go index a58ef358..e89064f8 100644 --- a/util/util.go +++ b/util/util.go @@ -268,3 +268,18 @@ func RunScript(path string) error { return cmd.Run() } + +func RunCommandSequence(commandSequence [][]string) { + for _, command := range commandSequence { + if len(command) == 0 { + continue + } + + cmd := exec.Command(command[0], command[1:]...) + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + if err := cmd.Run(); err != nil { + log.Errorf("Failed to run %s: %v", command, err) + } + } +}