diff --git a/drivers/openstack/client.go b/drivers/openstack/client.go index e464a5674c..218af191b0 100644 --- a/drivers/openstack/client.go +++ b/drivers/openstack/client.go @@ -4,8 +4,10 @@ import ( "crypto/tls" "fmt" "net/http" + "time" "github.com/docker/machine/log" + "github.com/docker/machine/utils" "github.com/docker/machine/version" "github.com/rackspace/gophercloud" "github.com/rackspace/gophercloud/openstack" @@ -31,7 +33,7 @@ type Client interface { StopInstance(d *Driver) error RestartInstance(d *Driver) error DeleteInstance(d *Driver) error - WaitForInstanceStatus(d *Driver, status string, timeout int) error + WaitForInstanceStatus(d *Driver, status string) error GetInstanceIpAddresses(d *Driver) ([]IpAddress, error) CreateKeyPair(d *Driver, name string, publicKey string) error DeleteKeyPair(d *Driver, name string) error @@ -132,11 +134,23 @@ func (c *GenericClient) DeleteInstance(d *Driver) error { return nil } -func (c *GenericClient) WaitForInstanceStatus(d *Driver, status string, timeout int) error { - if err := servers.WaitForStatus(c.Compute, d.MachineId, status, timeout); err != nil { - return err - } - return nil +func (c *GenericClient) WaitForInstanceStatus(d *Driver, status string) error { + return utils.WaitForSpecificOrError(func() (bool, error) { + current, err := servers.Get(c.Compute, d.MachineId).Extract() + if err != nil { + return true, err + } + + if current.Status == "ERROR" { + return true, fmt.Errorf("Instance creation failed. Instance is in ERROR state") + } + + if current.Status == status { + return true, nil + } + + return false, nil + }, 50, 4*time.Second) } func (c *GenericClient) GetInstanceIpAddresses(d *Driver) ([]IpAddress, error) { diff --git a/drivers/openstack/openstack.go b/drivers/openstack/openstack.go index d6e6bdf862..2bba3e5ed1 100644 --- a/drivers/openstack/openstack.go +++ b/drivers/openstack/openstack.go @@ -664,7 +664,7 @@ func (d *Driver) assignFloatingIp() error { func (d *Driver) waitForInstanceActive() error { log.WithField("MachineId", d.MachineId).Debug("Waiting for the OpenStack instance to be ACTIVE...") - if err := d.client.WaitForInstanceStatus(d, "ACTIVE", 200); err != nil { + if err := d.client.WaitForInstanceStatus(d, "ACTIVE"); err != nil { return err } return nil diff --git a/utils/utils.go b/utils/utils.go index d2d0483b22..e2ec725dae 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -94,9 +94,13 @@ func CopyFile(src, dst string) error { return nil } -func WaitForSpecific(f func() bool, maxAttempts int, waitInterval time.Duration) error { +func WaitForSpecificOrError(f func() (bool, error), maxAttempts int, waitInterval time.Duration) error { for i := 0; i < maxAttempts; i++ { - if f() { + stop, err := f() + if err != nil { + return err + } + if stop { return nil } time.Sleep(waitInterval) @@ -104,6 +108,12 @@ func WaitForSpecific(f func() bool, maxAttempts int, waitInterval time.Duration) return fmt.Errorf("Maximum number of retries (%d) exceeded", maxAttempts) } +func WaitForSpecific(f func() bool, maxAttempts int, waitInterval time.Duration) error { + return WaitForSpecificOrError(func() (bool, error) { + return f(), nil + }, maxAttempts, waitInterval) +} + func WaitFor(f func() bool) error { return WaitForSpecific(f, 60, 3*time.Second) }