2019-02-01 16:20:47 -05:00
|
|
|
package common
|
|
|
|
|
|
|
|
import (
|
2020-08-20 21:37:09 -04:00
|
|
|
"context"
|
2019-02-01 16:20:47 -05:00
|
|
|
"fmt"
|
|
|
|
"log"
|
|
|
|
|
2020-08-20 21:37:09 -04:00
|
|
|
"github.com/antihax/optional"
|
2020-11-11 18:52:06 -05:00
|
|
|
"github.com/hashicorp/packer/builder/osc/common/retry"
|
2020-08-20 21:37:09 -04:00
|
|
|
"github.com/outscale/osc-sdk-go/osc"
|
2019-02-01 16:20:47 -05:00
|
|
|
)
|
|
|
|
|
|
|
|
type stateRefreshFunc func() (string, error)
|
|
|
|
|
2020-08-20 21:37:09 -04:00
|
|
|
func waitUntilForOscVmRunning(conn *osc.APIClient, vmID string) error {
|
|
|
|
errCh := make(chan error, 1)
|
|
|
|
go waitForState(errCh, "running", waitUntilOscVmStateFunc(conn, vmID))
|
|
|
|
err := <-errCh
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
func waitUntilOscVmDeleted(conn *osc.APIClient, vmID string) error {
|
|
|
|
errCh := make(chan error, 1)
|
|
|
|
go waitForState(errCh, "terminated", waitUntilOscVmStateFunc(conn, vmID))
|
|
|
|
return <-errCh
|
|
|
|
}
|
|
|
|
|
2020-08-21 11:40:14 -04:00
|
|
|
func waitUntilOscVmStopped(conn *osc.APIClient, vmID string) error {
|
|
|
|
errCh := make(chan error, 1)
|
|
|
|
go waitForState(errCh, "stopped", waitUntilOscVmStateFunc(conn, vmID))
|
|
|
|
return <-errCh
|
|
|
|
}
|
|
|
|
|
2020-09-11 10:44:22 -04:00
|
|
|
func WaitUntilOscSnapshotCompleted(conn *osc.APIClient, id string) error {
|
|
|
|
errCh := make(chan error, 1)
|
|
|
|
go waitForState(errCh, "completed", waitUntilOscSnapshotStateFunc(conn, id))
|
|
|
|
return <-errCh
|
|
|
|
}
|
|
|
|
|
2020-08-25 19:02:11 -04:00
|
|
|
func WaitUntilOscImageAvailable(conn *osc.APIClient, imageID string) error {
|
|
|
|
errCh := make(chan error, 1)
|
|
|
|
go waitForState(errCh, "available", waitUntilOscImageStateFunc(conn, imageID))
|
|
|
|
return <-errCh
|
|
|
|
}
|
|
|
|
|
2020-09-30 11:37:09 -04:00
|
|
|
func WaitUntilOscVolumeAvailable(conn *osc.APIClient, volumeID string) error {
|
2019-02-23 21:49:51 -05:00
|
|
|
errCh := make(chan error, 1)
|
2020-09-30 11:37:09 -04:00
|
|
|
go waitForState(errCh, "available", volumeOscWaitFunc(conn, volumeID))
|
2019-02-23 21:49:51 -05:00
|
|
|
return <-errCh
|
|
|
|
}
|
|
|
|
|
2020-09-30 11:37:09 -04:00
|
|
|
func WaitUntilOscVolumeIsLinked(conn *osc.APIClient, volumeID string) error {
|
2019-02-25 16:37:06 -05:00
|
|
|
errCh := make(chan error, 1)
|
2020-09-30 11:37:09 -04:00
|
|
|
go waitForState(errCh, "attached", waitUntilOscVolumeLinkedStateFunc(conn, volumeID))
|
2019-02-25 16:37:06 -05:00
|
|
|
return <-errCh
|
|
|
|
}
|
|
|
|
|
2020-09-30 11:37:09 -04:00
|
|
|
func WaitUntilOscVolumeIsUnlinked(conn *osc.APIClient, volumeID string) error {
|
2019-02-25 16:37:06 -05:00
|
|
|
errCh := make(chan error, 1)
|
2020-09-30 11:37:09 -04:00
|
|
|
go waitForState(errCh, "dettached", waitUntilOscVolumeUnLinkedStateFunc(conn, volumeID))
|
2019-02-25 16:37:06 -05:00
|
|
|
return <-errCh
|
|
|
|
}
|
|
|
|
|
2020-09-30 11:37:09 -04:00
|
|
|
func WaitUntilOscSnapshotDone(conn *osc.APIClient, snapshotID string) error {
|
2019-02-28 16:42:04 -05:00
|
|
|
errCh := make(chan error, 1)
|
2020-09-30 11:37:09 -04:00
|
|
|
go waitForState(errCh, "completed", waitUntilOscSnapshotDoneStateFunc(conn, snapshotID))
|
2019-02-28 16:42:04 -05:00
|
|
|
return <-errCh
|
|
|
|
}
|
|
|
|
|
2020-10-13 11:45:32 -04:00
|
|
|
func waitForState(errCh chan<- error, target string, refresh stateRefreshFunc) {
|
2020-11-11 18:52:06 -05:00
|
|
|
err := retry.Retry(2, 2, 0, func(_ uint) (bool, error) {
|
2019-02-01 16:20:47 -05:00
|
|
|
state, err := refresh()
|
|
|
|
if err != nil {
|
|
|
|
return false, err
|
|
|
|
} else if state == target {
|
|
|
|
return true, nil
|
|
|
|
}
|
|
|
|
return false, nil
|
|
|
|
})
|
|
|
|
errCh <- err
|
|
|
|
}
|
|
|
|
|
2020-08-20 21:37:09 -04:00
|
|
|
func waitUntilOscVmStateFunc(conn *osc.APIClient, id string) stateRefreshFunc {
|
|
|
|
return func() (string, error) {
|
|
|
|
log.Printf("[Debug] Retrieving state for VM with id %s", id)
|
|
|
|
resp, _, err := conn.VmApi.ReadVms(context.Background(), &osc.ReadVmsOpts{
|
|
|
|
ReadVmsRequest: optional.NewInterface(osc.ReadVmsRequest{
|
|
|
|
Filters: osc.FiltersVm{
|
|
|
|
VmIds: []string{id},
|
|
|
|
},
|
|
|
|
}),
|
|
|
|
})
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
|
|
|
|
//TODO: check if needed
|
|
|
|
// if resp == nil {
|
|
|
|
// return "", fmt.Errorf("Vm with ID %s not Found", id)
|
|
|
|
// }
|
|
|
|
|
|
|
|
if len(resp.Vms) == 0 {
|
|
|
|
return "pending", nil
|
|
|
|
}
|
|
|
|
|
|
|
|
return resp.Vms[0].State, nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-09-30 11:37:09 -04:00
|
|
|
func waitUntilOscVolumeLinkedStateFunc(conn *osc.APIClient, id string) stateRefreshFunc {
|
2019-02-25 16:37:06 -05:00
|
|
|
return func() (string, error) {
|
|
|
|
log.Printf("[Debug] Check if volume with id %s exists", id)
|
2020-09-30 11:37:09 -04:00
|
|
|
resp, _, err := conn.VolumeApi.ReadVolumes(context.Background(), &osc.ReadVolumesOpts{
|
|
|
|
ReadVolumesRequest: optional.NewInterface(osc.ReadVolumesRequest{
|
|
|
|
Filters: osc.FiltersVolume{
|
|
|
|
VolumeIds: []string{id},
|
|
|
|
},
|
|
|
|
}),
|
2019-02-25 16:37:06 -05:00
|
|
|
})
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
|
2020-09-30 11:37:09 -04:00
|
|
|
if len(resp.Volumes) == 0 {
|
2019-02-25 16:37:06 -05:00
|
|
|
return "pending", nil
|
|
|
|
}
|
|
|
|
|
2020-09-30 11:37:09 -04:00
|
|
|
if len(resp.Volumes[0].LinkedVolumes) == 0 {
|
2019-02-25 16:37:06 -05:00
|
|
|
return "pending", nil
|
|
|
|
}
|
|
|
|
|
2020-09-30 11:37:09 -04:00
|
|
|
return resp.Volumes[0].LinkedVolumes[0].State, nil
|
2019-02-25 16:37:06 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-09-30 11:37:09 -04:00
|
|
|
func waitUntilOscVolumeUnLinkedStateFunc(conn *osc.APIClient, id string) stateRefreshFunc {
|
2019-02-25 16:37:06 -05:00
|
|
|
return func() (string, error) {
|
|
|
|
log.Printf("[Debug] Check if volume with id %s exists", id)
|
2020-09-30 11:37:09 -04:00
|
|
|
resp, _, err := conn.VolumeApi.ReadVolumes(context.Background(), &osc.ReadVolumesOpts{
|
|
|
|
ReadVolumesRequest: optional.NewInterface(osc.ReadVolumesRequest{
|
|
|
|
Filters: osc.FiltersVolume{
|
|
|
|
VolumeIds: []string{id},
|
|
|
|
},
|
|
|
|
}),
|
2019-02-25 16:37:06 -05:00
|
|
|
})
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
|
2020-09-30 11:37:09 -04:00
|
|
|
if len(resp.Volumes) == 0 {
|
2019-02-25 16:37:06 -05:00
|
|
|
return "pending", nil
|
|
|
|
}
|
|
|
|
|
2020-09-30 11:37:09 -04:00
|
|
|
if len(resp.Volumes[0].LinkedVolumes) == 0 {
|
2019-02-25 16:37:06 -05:00
|
|
|
return "dettached", nil
|
|
|
|
}
|
|
|
|
|
|
|
|
return "failed", nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-09-11 10:44:22 -04:00
|
|
|
func waitUntilOscSnapshotStateFunc(conn *osc.APIClient, id string) stateRefreshFunc {
|
|
|
|
return func() (string, error) {
|
|
|
|
log.Printf("[Debug] Check if Snapshot with id %s exists", id)
|
|
|
|
resp, _, err := conn.SnapshotApi.ReadSnapshots(context.Background(), &osc.ReadSnapshotsOpts{
|
|
|
|
ReadSnapshotsRequest: optional.NewInterface(osc.ReadSnapshotsRequest{
|
|
|
|
Filters: osc.FiltersSnapshot{
|
|
|
|
SnapshotIds: []string{id},
|
|
|
|
},
|
|
|
|
}),
|
|
|
|
})
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(resp.Snapshots) == 0 {
|
|
|
|
return "pending", nil
|
|
|
|
}
|
|
|
|
|
|
|
|
return resp.Snapshots[0].State, nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-08-25 19:02:11 -04:00
|
|
|
func waitUntilOscImageStateFunc(conn *osc.APIClient, id string) stateRefreshFunc {
|
|
|
|
return func() (string, error) {
|
|
|
|
log.Printf("[Debug] Check if Image with id %s exists", id)
|
|
|
|
resp, _, err := conn.ImageApi.ReadImages(context.Background(), &osc.ReadImagesOpts{
|
|
|
|
ReadImagesRequest: optional.NewInterface(osc.ReadImagesRequest{
|
|
|
|
Filters: osc.FiltersImage{
|
|
|
|
ImageIds: []string{id},
|
|
|
|
},
|
|
|
|
}),
|
|
|
|
})
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(resp.Images) == 0 {
|
|
|
|
return "pending", nil
|
|
|
|
}
|
|
|
|
|
|
|
|
if resp.Images[0].State == "failed" {
|
|
|
|
return resp.Images[0].State, fmt.Errorf("Image (%s) creation is failed", id)
|
|
|
|
}
|
|
|
|
|
|
|
|
return resp.Images[0].State, nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-09-30 11:37:09 -04:00
|
|
|
func waitUntilOscSnapshotDoneStateFunc(conn *osc.APIClient, id string) stateRefreshFunc {
|
2019-02-28 16:42:04 -05:00
|
|
|
return func() (string, error) {
|
|
|
|
log.Printf("[Debug] Check if Snapshot with id %s exists", id)
|
2020-09-30 11:37:09 -04:00
|
|
|
resp, _, err := conn.SnapshotApi.ReadSnapshots(context.Background(), &osc.ReadSnapshotsOpts{
|
|
|
|
ReadSnapshotsRequest: optional.NewInterface(osc.ReadSnapshotsRequest{
|
|
|
|
Filters: osc.FiltersSnapshot{
|
|
|
|
SnapshotIds: []string{id},
|
|
|
|
},
|
|
|
|
}),
|
2019-02-28 16:42:04 -05:00
|
|
|
})
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
|
2020-09-30 11:37:09 -04:00
|
|
|
if len(resp.Snapshots) == 0 {
|
2019-02-28 16:42:04 -05:00
|
|
|
return "", fmt.Errorf("Snapshot with ID %s. Not Found", id)
|
|
|
|
}
|
|
|
|
|
2020-09-30 11:37:09 -04:00
|
|
|
if resp.Snapshots[0].State == "error" {
|
|
|
|
return resp.Snapshots[0].State, fmt.Errorf("Snapshot (%s) creation is failed", id)
|
2019-02-28 16:42:04 -05:00
|
|
|
}
|
|
|
|
|
2020-09-30 11:37:09 -04:00
|
|
|
return resp.Snapshots[0].State, nil
|
2019-02-28 16:42:04 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-09-30 11:37:09 -04:00
|
|
|
func volumeOscWaitFunc(conn *osc.APIClient, id string) stateRefreshFunc {
|
2019-02-23 21:49:51 -05:00
|
|
|
return func() (string, error) {
|
|
|
|
log.Printf("[Debug] Check if SvolumeG with id %s exists", id)
|
2020-09-30 11:37:09 -04:00
|
|
|
resp, _, err := conn.VolumeApi.ReadVolumes(context.Background(), &osc.ReadVolumesOpts{
|
|
|
|
ReadVolumesRequest: optional.NewInterface(osc.ReadVolumesRequest{
|
|
|
|
Filters: osc.FiltersVolume{
|
|
|
|
VolumeIds: []string{id},
|
|
|
|
},
|
|
|
|
}),
|
2019-02-23 21:49:51 -05:00
|
|
|
})
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
|
2020-09-30 11:37:09 -04:00
|
|
|
if len(resp.Volumes) == 0 {
|
2019-02-23 21:49:51 -05:00
|
|
|
return "waiting", nil
|
|
|
|
}
|
|
|
|
|
2020-09-30 11:37:09 -04:00
|
|
|
if resp.Volumes[0].State == "error" {
|
|
|
|
return resp.Volumes[0].State, fmt.Errorf("Volume (%s) creation is failed", id)
|
2019-02-23 21:49:51 -05:00
|
|
|
}
|
|
|
|
|
2020-09-30 11:37:09 -04:00
|
|
|
return resp.Volumes[0].State, nil
|
2019-02-23 21:49:51 -05:00
|
|
|
}
|
|
|
|
}
|