Skip to content

Commit

Permalink
add the before_start_hook
Browse files Browse the repository at this point in the history
this will executed after the vm is configured, but before its started

this receives the vm configuration as a json in stdin

the hook is expected to return a json with the modified configuration
  • Loading branch information
rgl committed Feb 1, 2024
1 parent 31386f5 commit 9957253
Show file tree
Hide file tree
Showing 9 changed files with 85 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .web-docs/components/builder/clone/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,8 @@ boot time.
For example `-no-reboot -smbios type=0,vendor=FOO`.
Note: this option is for experts only.

- `before_start_hook` ([]string) - Before Start Hook

<!-- End of code generated from the comments of the Config struct in builder/proxmox/common/config.go; -->


Expand Down
2 changes: 2 additions & 0 deletions .web-docs/components/builder/iso/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,8 @@ in the image's Cloud-Init settings for provisioning.
For example `-no-reboot -smbios type=0,vendor=FOO`.
Note: this option is for experts only.

- `before_start_hook` ([]string) - Before Start Hook

<!-- End of code generated from the comments of the Config struct in builder/proxmox/common/config.go; -->


Expand Down
2 changes: 2 additions & 0 deletions builder/proxmox/clone/config.hcl2spec.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions builder/proxmox/common/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,8 @@ type Config struct {
// Note: this option is for experts only.
AdditionalArgs string `mapstructure:"qemu_additional_args"`

BeforeStartHook []string `mapstructure:"before_start_hook"`

Ctx interpolate.Context `mapstructure-to-hcl2:",skip"`
}

Expand Down
2 changes: 2 additions & 0 deletions builder/proxmox/common/config.hcl2spec.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

66 changes: 66 additions & 0 deletions builder/proxmox/common/step_start_vm.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,12 @@
package proxmox

import (
"bytes"
"context"
"encoding/json"
"fmt"
"log"
"os/exec"
"strconv"
"strings"

Expand Down Expand Up @@ -243,6 +246,69 @@ func (s *stepStartVM) Run(ctx context.Context, state multistep.StateBag) multist
// info available in the vmref type.
state.Put("instance_id", vmRef.VmId())

// Execute the before_start_hook.
if len(c.BeforeStartHook) > 0 {
ui.Say("Executing the before_start_hook")

cfg, err := client.GetVmConfig(vmRef)
if err != nil {
err := fmt.Errorf("failed to get the VM configuration: %w", err)
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt
}

cfgDoc, err := json.Marshal(cfg)
if err != nil {
err := fmt.Errorf("failed to marshal the VM configuration: %w", err)
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt
}

log.Printf("executing the before_start_hook in VM with ID %d and config %s", vmRef.VmId(), cfgDoc)

var stdout, stderr bytes.Buffer
var cmdArgs []string
if len(c.BeforeStartHook) > 1 {
cmdArgs = c.BeforeStartHook[1:]
}
cmd := exec.Command(c.BeforeStartHook[0], cmdArgs...)
cmd.Stdin = bytes.NewReader(cfgDoc)
cmd.Stdout = &stdout
cmd.Stderr = &stderr
err = cmd.Run()
if err != nil {
log.Printf("failed to execute the before_start_hook in VM with ID %d. stderr=%s stdout=%s", vmRef.VmId(), stderr.Bytes(), stdout.Bytes())
err := fmt.Errorf("failed to execute the before_start_hook: %w", err)
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt
}
newCfgDoc := stdout.Bytes()

log.Printf("executed the before_start_hook in VM with ID %d and returned the config %s", vmRef.VmId(), newCfgDoc)

if bytes.HasPrefix(newCfgDoc, []byte{'{'}) {
var vmConfig map[string]interface{}
err = json.Unmarshal(newCfgDoc, &vmConfig)
if err != nil {
err := fmt.Errorf("failed to unmarshal the before_start_hook output: %w", err)
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt
}

_, err = client.SetVmConfig(vmRef, vmConfig)
if err != nil {
err := fmt.Errorf("failed to set the VM configuration: %w", err)
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt
}
}
}

ui.Say("Starting VM")
_, err := client.StartVm(vmRef)
if err != nil {
Expand Down
2 changes: 2 additions & 0 deletions builder/proxmox/iso/config.hcl2spec.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions docs-partials/builder/proxmox/common/Config-not-required.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -139,4 +139,6 @@
For example `-no-reboot -smbios type=0,vendor=FOO`.
Note: this option is for experts only.

- `before_start_hook` ([]string) - Before Start Hook

<!-- End of code generated from the comments of the Config struct in builder/proxmox/common/config.go; -->
5 changes: 5 additions & 0 deletions docs-partials/builder/proxmox/common/hooks-not-required.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<!-- Code generated from the comments of the hooks struct in builder/proxmox/common/config.go; DO NOT EDIT MANUALLY -->

- `before_start` ([]string) - Before Start

<!-- End of code generated from the comments of the hooks struct in builder/proxmox/common/config.go; -->

0 comments on commit 9957253

Please sign in to comment.