From d022c2194a80b007f726b4c2131b37a273df8ca2 Mon Sep 17 00:00:00 2001 From: William Bianchini Date: Thu, 12 Sep 2019 20:35:14 -0300 Subject: [PATCH 1/3] [cloudstack builder] Detach iso step Detach iso file after loading image to cache, allowing OS to boot from volume ater the installation Add eject iso check and wait timeout Closes #7235 --- builder/cloudstack/builder.go | 1 + builder/cloudstack/config.go | 14 ++++--- builder/cloudstack/step_detach_iso.go | 60 +++++++++++++++++++++++++++ 3 files changed, 69 insertions(+), 6 deletions(-) create mode 100644 builder/cloudstack/step_detach_iso.go diff --git a/builder/cloudstack/builder.go b/builder/cloudstack/builder.go index fe376125f..dc1dace69 100644 --- a/builder/cloudstack/builder.go +++ b/builder/cloudstack/builder.go @@ -75,6 +75,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack Debug: b.config.PackerDebug, }, &stepSetupNetworking{}, + &stepDetachIso{}, &communicator.StepConnect{ Config: &b.config.Comm, Host: communicator.CommHost(b.config.Comm.SSHHost, "ipaddress"), diff --git a/builder/cloudstack/config.go b/builder/cloudstack/config.go index 00f79618b..7b975a618 100644 --- a/builder/cloudstack/config.go +++ b/builder/cloudstack/config.go @@ -20,12 +20,14 @@ type Config struct { common.HTTPConfig `mapstructure:",squash"` Comm communicator.Config `mapstructure:",squash"` - APIURL string `mapstructure:"api_url"` - APIKey string `mapstructure:"api_key"` - SecretKey string `mapstructure:"secret_key"` - AsyncTimeout time.Duration `mapstructure:"async_timeout"` - HTTPGetOnly bool `mapstructure:"http_get_only"` - SSLNoVerify bool `mapstructure:"ssl_no_verify"` + APIURL string `mapstructure:"api_url"` + APIKey string `mapstructure:"api_key"` + SecretKey string `mapstructure:"secret_key"` + AsyncTimeout time.Duration `mapstructure:"async_timeout"` + HTTPGetOnly bool `mapstructure:"http_get_only"` + SSLNoVerify bool `mapstructure:"ssl_no_verify"` + EjectISO bool `mapstructure:"eject_iso"` + EjectISODelay time.Duration `mapstructure:"eject_iso_delay"` CIDRList []string `mapstructure:"cidr_list"` CreateSecurityGroup bool `mapstructure:"create_security_group"` diff --git a/builder/cloudstack/step_detach_iso.go b/builder/cloudstack/step_detach_iso.go new file mode 100644 index 000000000..444293c2c --- /dev/null +++ b/builder/cloudstack/step_detach_iso.go @@ -0,0 +1,60 @@ +package cloudstack + +import ( + "context" + "fmt" + "time" + + "github.com/hashicorp/packer/helper/multistep" + "github.com/hashicorp/packer/packer" + "github.com/xanzy/go-cloudstack/cloudstack" +) + +type stepDetachIso struct{} + +// Detaches currently ISO file attached to a virtual machine if any. +func (s *stepDetachIso) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { + ui := state.Get("ui").(packer.Ui) + config := state.Get("config").(*Config) + + // Check if state uses iso file and has need to eject it + if !config.EjectISO || config.SourceISO == "" { + return multistep.ActionContinue + } + + ui.Say("Checking attached iso...") + + // Wait to make call detachIso + if config.EjectISODelay > 0 { + ui.Message(fmt.Sprintf("Waiting for %v before detaching ISO from virtual machine...", config.EjectISODelay)) + time.Sleep(config.EjectISODelay) + } + + client := state.Get("client").(*cloudstack.CloudStackClient) + + instanceID, ok := state.Get("instance_id").(string) + if !ok || instanceID == "" { + err := fmt.Errorf("Could not retrieve instance_id from state") + state.Put("error", err) + ui.Error(err.Error()) + return multistep.ActionHalt + } + + ui.Message("Detaching iso from virtual machine...") + + // Get a new DetachIsoParams and detaches Iso file from given virtualMachine instance + detachIsoParams := client.ISO.NewDetachIsoParams(instanceID) + response, err := client.ISO.DetachIso(detachIsoParams) + if err != nil || response == nil { + err := fmt.Errorf("Error detaching ISO from virtual machine: %s", err) + state.Put("error", err) + ui.Error(err.Error()) + return multistep.ActionHalt + } + + return multistep.ActionContinue +} + +func (s *stepDetachIso) Cleanup(state multistep.StateBag) { + // Nothing to cleanup for this step. +} From 39a1f64d52d7eecbc7cb473a1dd6e72cdc12f1cc Mon Sep 17 00:00:00 2001 From: William Bianchini Date: Tue, 17 Sep 2019 11:55:31 -0300 Subject: [PATCH 2/3] Add cloudstack.html.md documentation of eject_iso and eject_iso_delay options Usages and behavior. --- website/source/docs/builders/cloudstack.html.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/website/source/docs/builders/cloudstack.html.md b/website/source/docs/builders/cloudstack.html.md index 2ed408d94..1ab0addb2 100644 --- a/website/source/docs/builders/cloudstack.html.md +++ b/website/source/docs/builders/cloudstack.html.md @@ -111,6 +111,16 @@ builder. - `hypervisor` (string) - The target hypervisor (e.g. `XenServer`, `KVM`) for the new template. This option is required when using `source_iso`. +- `eject_iso` (boolean) - If `true`, make a call to the CloudStack API, after + loading image to cache requesting to check and detach ISO file (if any) + currently attached to a virtual machine. Defaults to `false`. This option + is only available when using `source_iso`. + +- `eject_iso_delay` (time.Duration) - Configure the duration time to wait, making + sure virtual machine is able to finish installing OS before it ejects safely. + Requires `eject_iso` set to `true` and this option is only available when + using `source_iso`. + - `keypair` (string) - The name of the SSH key pair that will be used to access the instance. The SSH key pair is assumed to be already available within CloudStack. From 3022576b57709c1e12deee771c1b0974e60b360c Mon Sep 17 00:00:00 2001 From: William Bianchini Date: Tue, 17 Sep 2019 12:15:09 -0300 Subject: [PATCH 3/3] Update cloudstack.html.md --- website/source/docs/builders/cloudstack.html.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/website/source/docs/builders/cloudstack.html.md b/website/source/docs/builders/cloudstack.html.md index 1ab0addb2..07e65bec1 100644 --- a/website/source/docs/builders/cloudstack.html.md +++ b/website/source/docs/builders/cloudstack.html.md @@ -111,8 +111,8 @@ builder. - `hypervisor` (string) - The target hypervisor (e.g. `XenServer`, `KVM`) for the new template. This option is required when using `source_iso`. -- `eject_iso` (boolean) - If `true`, make a call to the CloudStack API, after - loading image to cache requesting to check and detach ISO file (if any) +- `eject_iso` (boolean) - If `true` make a call to the CloudStack API, after + loading image to cache, requesting to check and detach ISO file (if any) currently attached to a virtual machine. Defaults to `false`. This option is only available when using `source_iso`.