package openstack import ( "context" "fmt" "github.com/gophercloud/gophercloud/openstack/blockstorage/extensions/volumeactions" "github.com/hashicorp/packer/helper/multistep" "github.com/hashicorp/packer/packer" ) type StepDetachVolume struct { UseBlockStorageVolume bool } func (s *StepDetachVolume) Run(_ context.Context, state multistep.StateBag) multistep.StepAction { // Proceed only if block storage volume is used. if !s.UseBlockStorageVolume { return multistep.ActionContinue } config := state.Get("config").(Config) ui := state.Get("ui").(packer.Ui) blockStorageClient, err := config.blockStorageV3Client() if err != nil { err = fmt.Errorf("Error initializing block storage client: %s", err) state.Put("error", err) return multistep.ActionHalt } volume := state.Get("volume_id").(string) ui.Say(fmt.Sprintf("Detaching volume %s (volume id: %s)", config.VolumeName, volume)) if err := volumeactions.Detach(blockStorageClient, volume, volumeactions.DetachOpts{}).ExtractErr(); err != nil { err = fmt.Errorf("Error detaching block storage volume: %s", err) state.Put("error", err) return multistep.ActionHalt } // Wait for volume to become available. ui.Say(fmt.Sprintf("Waiting for volume %s (volume id: %s) to become available...", config.VolumeName, volume)) if err := WaitForVolume(blockStorageClient, volume); err != nil { err := fmt.Errorf("Error waiting for volume: %s", err) state.Put("error", err) ui.Error(err.Error()) return multistep.ActionHalt } return multistep.ActionContinue } func (s *StepDetachVolume) Cleanup(multistep.StateBag) { // No cleanup. }