From 83c9a3d4c89a802af1a6ddf69917e8901951f981 Mon Sep 17 00:00:00 2001 From: Marin Salinas Date: Mon, 11 Feb 2019 12:36:04 -0600 Subject: [PATCH] feature: bsu, run implementation add createOMI step --- builder/osc/bsu/builder.go | 1 + builder/osc/bsu/step_create_omi.go | 116 +++++++++++++++++++++++++++++ 2 files changed, 117 insertions(+) create mode 100644 builder/osc/bsu/step_create_omi.go diff --git a/builder/osc/bsu/builder.go b/builder/osc/bsu/builder.go index 550f2ad38..3c534b206 100644 --- a/builder/osc/bsu/builder.go +++ b/builder/osc/bsu/builder.go @@ -188,6 +188,7 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe OMIName: b.config.OMIName, Regions: b.config.OMIRegions, }, + &stepCreateOMI{}, } b.runner = common.NewRunner(steps, b.config.PackerConfig, ui) diff --git a/builder/osc/bsu/step_create_omi.go b/builder/osc/bsu/step_create_omi.go new file mode 100644 index 000000000..102b43a4f --- /dev/null +++ b/builder/osc/bsu/step_create_omi.go @@ -0,0 +1,116 @@ +package bsu + +import ( + "context" + "fmt" + "log" + + osccommon "github.com/hashicorp/packer/builder/osc/common" + "github.com/hashicorp/packer/helper/multistep" + "github.com/hashicorp/packer/packer" + "github.com/outscale/osc-go/oapi" +) + +type stepCreateOMI struct { + image *oapi.Image +} + +func (s *stepCreateOMI) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { + config := state.Get("config").(*Config) + oapiconn := state.Get("oapi").(*oapi.Client) + vm := state.Get("vm").(*oapi.Vm) + ui := state.Get("ui").(packer.Ui) + + // Create the image + omiName := config.OMIName + + ui.Say(fmt.Sprintf("Creating unencrypted OMI %s from vm %s", omiName, vm.VmId)) + createOpts := oapi.CreateImageRequest{ + VmId: vm.VmId, + ImageName: omiName, + BlockDeviceMappings: config.BlockDevices.BuildOMIDevices(), + } + + resp, err := oapiconn.POST_CreateImage(createOpts) + if err != nil || resp.OK == nil { + err := fmt.Errorf("Error creating OMI: %s", err) + state.Put("error", err) + ui.Error(err.Error()) + return multistep.ActionHalt + } + + image := resp.OK.Image + + // Set the OMI ID in the state + ui.Message(fmt.Sprintf("OMI: %s", image.ImageId)) + omis := make(map[string]string) + omis[oapiconn.GetConfig().Region] = image.ImageId + state.Put("omis", omis) + + // Wait for the image to become ready + ui.Say("Waiting for OMI to become ready...") + if err := osccommon.WaitUntilImageAvailable(oapiconn, image.ImageId); err != nil { + log.Printf("Error waiting for OMI: %s", err) + imagesResp, err := oapiconn.POST_ReadImages(oapi.ReadImagesRequest{ + Filters: oapi.FiltersImage{ + ImageIds: []string{image.ImageId}, + }, + }) + if err != nil { + log.Printf("Unable to determine reason waiting for OMI failed: %s", err) + err = fmt.Errorf("Unknown error waiting for OMI.") + } else { + stateReason := imagesResp.OK.Images[0].StateComment + err = fmt.Errorf("Error waiting for OMI. Reason: %s", stateReason) + } + + state.Put("error", err) + ui.Error(err.Error()) + return multistep.ActionHalt + } + + imagesResp, err := oapiconn.POST_ReadImages(oapi.ReadImagesRequest{ + Filters: oapi.FiltersImage{ + ImageIds: []string{image.ImageId}, + }, + }) + if err != nil { + err := fmt.Errorf("Error searching for OMI: %s", err) + state.Put("error", err) + ui.Error(err.Error()) + return multistep.ActionHalt + } + s.image = &imagesResp.OK.Images[0] + + snapshots := make(map[string][]string) + for _, blockDeviceMapping := range imagesResp.OK.Images[0].BlockDeviceMappings { + if blockDeviceMapping.Bsu.SnapshotId != "" { + snapshots[oapiconn.GetConfig().Region] = append(snapshots[oapiconn.GetConfig().Region], blockDeviceMapping.Bsu.SnapshotId) + } + } + state.Put("snapshots", snapshots) + + return multistep.ActionContinue +} + +func (s *stepCreateOMI) Cleanup(state multistep.StateBag) { + if s.image == nil { + return + } + + _, cancelled := state.GetOk(multistep.StateCancelled) + _, halted := state.GetOk(multistep.StateHalted) + if !cancelled && !halted { + return + } + + oapiconn := state.Get("oapi").(*oapi.Client) + ui := state.Get("ui").(packer.Ui) + + ui.Say("Deregistering the OMI because cancellation or error...") + DeleteOpts := oapi.DeleteImageRequest{ImageId: s.image.ImageId} + if _, err := oapiconn.POST_DeleteImage(DeleteOpts); err != nil { + ui.Error(fmt.Sprintf("Error Deleting OMI, may still be around: %s", err)) + return + } +}