From 0ad6b169bcc8e092b1d39bb9ba566b60a06bcfbb Mon Sep 17 00:00:00 2001 From: Matthew Hooker Date: Thu, 23 Mar 2017 23:58:15 -0700 Subject: [PATCH] builder/virtualbox: retry removing floppy controller --- .../virtualbox/common/step_remove_devices.go | 30 ++++++++++++++----- common/retry.go | 4 ++- 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/builder/virtualbox/common/step_remove_devices.go b/builder/virtualbox/common/step_remove_devices.go index 54b85bbb4..bcb261bb0 100644 --- a/builder/virtualbox/common/step_remove_devices.go +++ b/builder/virtualbox/common/step_remove_devices.go @@ -2,7 +2,10 @@ package common import ( "fmt" + "log" + "github.com/mitchellh/multistep" + "github.com/mitchellh/packer/common" "github.com/mitchellh/packer/packer" ) @@ -39,14 +42,25 @@ func (s *StepRemoveDevices) Run(state multistep.StateBag) multistep.StepAction { return multistep.ActionHalt } - // Don't forget to remove the floppy controller as well - command = []string{ - "storagectl", vmName, - "--name", "Floppy Controller", - "--remove", - } - if err := driver.VBoxManage(command...); err != nil { - err := fmt.Errorf("Error removing floppy controller: %s", err) + var vboxErr error + // Retry for 10 minutes to remove the floppy controller. + log.Printf("Trying for 10 minutes to remove floppy controller.") + err := common.Retry(15, 15, 40, func() (bool, error) { + // Don't forget to remove the floppy controller as well + command = []string{ + "storagectl", vmName, + "--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) ui.Error(err.Error()) return multistep.ActionHalt diff --git a/common/retry.go b/common/retry.go index a7aa74594..4307af8b4 100644 --- a/common/retry.go +++ b/common/retry.go @@ -8,13 +8,15 @@ import ( 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. // 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. // Intervals are in seconds. // Returns an error if initial > max intervals, if retries are exhausted, or if the passed function returns // 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 { maxInterval = math.Inf(1) } else if initialInterval < 0 || initialInterval > maxInterval {