diff --git a/engine/resources/virt_builder.go b/engine/resources/virt_builder.go index 7db4a97a..3ce16520 100644 --- a/engine/resources/virt_builder.go +++ b/engine/resources/virt_builder.go @@ -33,6 +33,7 @@ import ( "bytes" "context" "fmt" + "net/url" "os" "os/exec" "path" @@ -146,9 +147,13 @@ type VirtBuilderRes struct { // additional packages to install which are needed to bootstrap mgmt. // This defaults to true. // TODO: This does not yet support multi or cross arch. - // FIXME: This doesn't kick off mgmt runs yet. Bootstrap bool `lang:"bootstrap" yaml:"bootstrap"` + // Seeds is a list of default etcd client endpoints to connect to. If + // you specify this, you must also set Bootstrap to true. These should + // likely be http URL's like: http://127.0.0.1:2379 or similar. + Seeds []string `lang:"seeds" yaml:"seeds"` + // LogOutput logs the output of running this command to a file in the // special $vardir directory. It defaults to true. Keep in mind that if // you let virt-builder choose the password randomly, it will be output @@ -305,6 +310,15 @@ func (obj *VirtBuilderRes) Validate() error { } } + for _, x := range obj.Seeds { + if x == "" { + return fmt.Errorf("empty seed") + } + if _, err := url.Parse(x); err != nil { // it's so rare this fails + return err + } + } + return nil } @@ -501,8 +515,24 @@ func (obj *VirtBuilderRes) CheckApply(ctx context.Context, apply bool) (bool, er // TODO: bootstrap mgmt based on the deploy method this ran with // TODO: --tmp-prefix ? --module-path ? - //args2 := []string{"--firstboot-command", VirtBuilderBinDir+"mgmt", "run", "lang", "?"} - //cmdArgs = append(cmdArgs, args2...) + // TODO: add an alternate handoff method to run a bolus of code? + if len(obj.Seeds) > 0 { + m := filepath.Join(VirtBuilderBinDir, filepath.Base(p)) // mgmt full path + setupSvc := []string{ + m, // mgmt + "setup", // setup command + "svc", // TODO: pull from a const? + "--install", + //"--start", // we're in pre-boot env right now + "--enable", // start on first boot! + fmt.Sprintf("--binary-path=%s", m), + "--no-server", // TODO: hardcode this for now + fmt.Sprintf("--seeds=%s", strings.Join(obj.Seeds, ",")), + } + setupSvcCmd := strings.Join(setupSvc, " ") + args := []string{"--run-command", setupSvcCmd} // cmd must be a single string + cmdArgs = append(cmdArgs, args...) + } } cmd := exec.CommandContext(ctx, cmdName, cmdArgs...) @@ -644,6 +674,15 @@ func (obj *VirtBuilderRes) Cmp(r engine.Res) error { return fmt.Errorf("the Bootstrap value differs") } + if len(obj.Seeds) != len(res.Seeds) { + return fmt.Errorf("the number of Seeds differs") + } + for i, x := range obj.Seeds { + if seed := res.Seeds[i]; x != seed { + return fmt.Errorf("the seed at index %d differs", i) + } + } + if obj.LogOutput != res.LogOutput { return fmt.Errorf("the LogOutput value differs") } diff --git a/modules/virtualization/main.mcl b/modules/virtualization/main.mcl index 8bc7f062..fd3f25be 100644 --- a/modules/virtualization/main.mcl +++ b/modules/virtualization/main.mcl @@ -97,6 +97,7 @@ class vm($name, $config) { } else { # other distros TODO: add a switch or else if? [] } + $seeds = $config->seeds || [] virt:builder "${filename}" { hostname => $name, @@ -115,6 +116,7 @@ class vm($name, $config) { }, ], root_password_selector => $root_password_selector, + seeds => $seeds, # make sure key exists so that's it's available for injection! Depend => File["/root/.ssh/id_rsa"],