Commit 717746ce authored by Mitchell Hashimoto's avatar Mitchell Hashimoto

provisioner/shell: retry uploads if reboot [GH-282]

parent faf6eb1c
...@@ -5,6 +5,11 @@ IMPROVEMENTS: ...@@ -5,6 +5,11 @@ IMPROVEMENTS:
* post-processor/vagrant: the file being compressed will be shown * post-processor/vagrant: the file being compressed will be shown
in the UI [GH-314] in the UI [GH-314]
BUG FIXES:
* provisioner/shell: Retry shell script uploads, making reboots more
robust if they happen to fail in this stage. [GH-282]
## 0.3.3 (August 19, 2013) ## 0.3.3 (August 19, 2013)
FEATURES: FEATURES:
......
...@@ -237,7 +237,9 @@ func (p *Provisioner) Provision(ui packer.Ui, comm packer.Communicator) error { ...@@ -237,7 +237,9 @@ func (p *Provisioner) Provision(ui packer.Ui, comm packer.Communicator) error {
defer f.Close() defer f.Close()
log.Printf("Uploading %s => %s", path, p.config.RemotePath) log.Printf("Uploading %s => %s", path, p.config.RemotePath)
err = comm.Upload(p.config.RemotePath, f) err = p.retryable(func() error {
return comm.Upload(p.config.RemotePath, f)
})
if err != nil { if err != nil {
return fmt.Errorf("Error uploading shell script: %s", err) return fmt.Errorf("Error uploading shell script: %s", err)
} }
...@@ -258,15 +260,35 @@ func (p *Provisioner) Provision(ui packer.Ui, comm packer.Communicator) error { ...@@ -258,15 +260,35 @@ func (p *Provisioner) Provision(ui packer.Ui, comm packer.Communicator) error {
} }
cmd := &packer.RemoteCmd{Command: command} cmd := &packer.RemoteCmd{Command: command}
startTimeout := time.After(p.config.startRetryTimeout)
log.Printf("Executing command: %s", cmd.Command) log.Printf("Executing command: %s", cmd.Command)
err = p.retryable(func() error {
return cmd.StartWithUi(comm, ui)
})
if err != nil {
return err
}
if cmd.ExitStatus != 0 {
return fmt.Errorf("Script exited with non-zero exit status: %d", cmd.ExitStatus)
}
}
return nil
}
// retryable will retry the given function over and over until a
// non-error is returned.
func (p *Provisioner) retryable(f func() error) error {
startTimeout := time.After(p.config.startRetryTimeout)
for { for {
if err := cmd.StartWithUi(comm, ui); err == nil { var err error
break if err = f(); err == nil {
return nil
} }
// Create an error and log it // Create an error and log it
err = fmt.Errorf("Error executing command: %s", err) err = fmt.Errorf("Retryable error: %s", err)
log.Printf(err.Error()) log.Printf(err.Error())
// Check if we timed out, otherwise we retry. It is safe to // Check if we timed out, otherwise we retry. It is safe to
...@@ -279,11 +301,4 @@ func (p *Provisioner) Provision(ui packer.Ui, comm packer.Communicator) error { ...@@ -279,11 +301,4 @@ func (p *Provisioner) Provision(ui packer.Ui, comm packer.Communicator) error {
time.Sleep(2 * time.Second) time.Sleep(2 * time.Second)
} }
} }
if cmd.ExitStatus != 0 {
return fmt.Errorf("Script exited with non-zero exit status: %d", cmd.ExitStatus)
}
}
return nil
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment