Merge pull request #4705 from mitchellh/floppyretry

builder/virtualbox: retry removing floppy controller
This commit is contained in:
Matthew Hooker 2017-03-24 00:01:53 -07:00 committed by GitHub
commit ec12b99cde
2 changed files with 25 additions and 9 deletions

View File

@ -2,7 +2,10 @@ package common
import ( import (
"fmt" "fmt"
"log"
"github.com/mitchellh/multistep" "github.com/mitchellh/multistep"
"github.com/mitchellh/packer/common"
"github.com/mitchellh/packer/packer" "github.com/mitchellh/packer/packer"
) )
@ -39,14 +42,25 @@ func (s *StepRemoveDevices) Run(state multistep.StateBag) multistep.StepAction {
return multistep.ActionHalt return multistep.ActionHalt
} }
// Don't forget to remove the floppy controller as well var vboxErr error
command = []string{ // Retry for 10 minutes to remove the floppy controller.
"storagectl", vmName, log.Printf("Trying for 10 minutes to remove floppy controller.")
"--name", "Floppy Controller", err := common.Retry(15, 15, 40, func() (bool, error) {
"--remove", // Don't forget to remove the floppy controller as well
} command = []string{
if err := driver.VBoxManage(command...); err != nil { "storagectl", vmName,
err := fmt.Errorf("Error removing floppy controller: %s", err) "--name", "Floppy Controller",
"--remove",
}
vboxErr = driver.VBoxManage(command...)
if vboxErr != nil {
log.Printf("Error removing floppy controller. Retrying")
return false, nil
}
return true, nil
})
if err == common.RetryExhaustedError {
err := fmt.Errorf("Error removing floppy controller: %s", vboxErr)
state.Put("error", err) state.Put("error", err)
ui.Error(err.Error()) ui.Error(err.Error())
return multistep.ActionHalt return multistep.ActionHalt

View File

@ -8,13 +8,15 @@ import (
var RetryExhaustedError error = fmt.Errorf("Function never succeeded in Retry") var RetryExhaustedError error = fmt.Errorf("Function never succeeded in Retry")
type RetryableFunc func() (bool, error)
// Retry retries a function up to numTries times with exponential backoff. // Retry retries a function up to numTries times with exponential backoff.
// If numTries == 0, retry indefinitely. If interval == 0, Retry will not delay retrying and there will be // If numTries == 0, retry indefinitely. If interval == 0, Retry will not delay retrying and there will be
// no exponential backoff. If maxInterval == 0, maxInterval is set to +Infinity. // no exponential backoff. If maxInterval == 0, maxInterval is set to +Infinity.
// Intervals are in seconds. // Intervals are in seconds.
// Returns an error if initial > max intervals, if retries are exhausted, or if the passed function returns // Returns an error if initial > max intervals, if retries are exhausted, or if the passed function returns
// an error. // an error.
func Retry(initialInterval float64, maxInterval float64, numTries uint, function func() (bool, error)) error { func Retry(initialInterval float64, maxInterval float64, numTries uint, function RetryableFunc) error {
if maxInterval == 0 { if maxInterval == 0 {
maxInterval = math.Inf(1) maxInterval = math.Inf(1)
} else if initialInterval < 0 || initialInterval > maxInterval { } else if initialInterval < 0 || initialInterval > maxInterval {