Merge pull request #2568 from pecigonzalo/f-winrm-reboot

Add reboot checks before moving out of the reboot sequence for WinRM
This commit is contained in:
Mark Peek 2015-10-26 16:57:13 -07:00
commit 43cb854b3e
2 changed files with 42 additions and 4 deletions

View File

@ -13,9 +13,11 @@ import (
"github.com/mitchellh/packer/template/interpolate" "github.com/mitchellh/packer/template/interpolate"
) )
var DefaultRestartCommand = "powershell \"& {Restart-Computer -force }\"" var DefaultRestartCommand = "shutdown /r /f /t 0 /c \"packer restart\""
var DefaultRestartCheckCommand = winrm.Powershell(`echo "${env:COMPUTERNAME} restarted."`) var DefaultRestartCheckCommand = winrm.Powershell(`echo "${env:COMPUTERNAME} restarted."`)
var retryableSleep = 5 * time.Second var retryableSleep = 5 * time.Second
var TryCheckReboot = "shutdown.exe -f -r -t 60"
var AbortReboot = "shutdown.exe -a"
type Config struct { type Config struct {
common.PackerConfig `mapstructure:",squash"` common.PackerConfig `mapstructure:",squash"`
@ -94,16 +96,42 @@ func (p *Provisioner) Provision(ui packer.Ui, comm packer.Communicator) error {
return fmt.Errorf("Restart script exited with non-zero exit status: %d", cmd.ExitStatus) return fmt.Errorf("Restart script exited with non-zero exit status: %d", cmd.ExitStatus)
} }
return waitForRestart(p) return waitForRestart(p, comm)
} }
var waitForRestart = func(p *Provisioner) error { var waitForRestart = func(p *Provisioner, comm packer.Communicator) error {
ui := p.ui ui := p.ui
ui.Say("Waiting for machine to restart...") ui.Say("Waiting for machine to restart...")
waitDone := make(chan bool, 1) waitDone := make(chan bool, 1)
timeout := time.After(p.config.RestartTimeout) timeout := time.After(p.config.RestartTimeout)
var err error var err error
p.comm = comm
var cmd *packer.RemoteCmd
trycommand := TryCheckReboot
abortcommand := AbortReboot
// Stolen from Vagrant reboot checker
for {
log.Printf("Check if machine is rebooting...")
cmd = &packer.RemoteCmd{Command: trycommand}
err = cmd.StartWithUi(comm, ui)
if err != nil {
// Couldnt execute, we asume machine is rebooting already
break
}
if cmd.ExitStatus == 1115 || cmd.ExitStatus == 1190 {
// Reboot already in progress but not completed
log.Printf("Reboot already in progress, waiting...")
time.Sleep(10 * time.Second)
}
if cmd.ExitStatus == 0 {
// Cancel reboot we created to test if machine was already rebooting
cmd = &packer.RemoteCmd{Command: abortcommand}
cmd.StartWithUi(comm, ui)
break
}
}
go func() { go func() {
log.Printf("Waiting for machine to become available...") log.Printf("Waiting for machine to become available...")
err = waitForCommunicator(p) err = waitForCommunicator(p)

View File

@ -35,7 +35,7 @@ func TestProvisionerPrepare_Defaults(t *testing.T) {
t.Errorf("unexpected remote path: %s", p.config.RestartTimeout) t.Errorf("unexpected remote path: %s", p.config.RestartTimeout)
} }
if p.config.RestartCommand != "powershell \"& {Restart-Computer -force }\"" { if p.config.RestartCommand != "shutdown /r /f /t 0 /c \"packer restart\"" {
t.Errorf("unexpected remote path: %s", p.config.RestartCommand) t.Errorf("unexpected remote path: %s", p.config.RestartCommand)
} }
} }
@ -100,6 +100,10 @@ func TestProvisionerProvision_Success(t *testing.T) {
waitForCommunicator = func(p *Provisioner) error { waitForCommunicator = func(p *Provisioner) error {
return nil return nil
} }
waitForRestartOld := waitForRestart
waitForRestart = func(p *Provisioner, comm packer.Communicator) error {
return nil
}
err := p.Provision(ui, comm) err := p.Provision(ui, comm)
if err != nil { if err != nil {
t.Fatal("should not have error") t.Fatal("should not have error")
@ -113,6 +117,7 @@ func TestProvisionerProvision_Success(t *testing.T) {
} }
// Set this back! // Set this back!
waitForCommunicator = waitForCommunicatorOld waitForCommunicator = waitForCommunicatorOld
waitForRestart = waitForRestartOld
} }
func TestProvisionerProvision_CustomCommand(t *testing.T) { func TestProvisionerProvision_CustomCommand(t *testing.T) {
@ -131,6 +136,10 @@ func TestProvisionerProvision_CustomCommand(t *testing.T) {
waitForCommunicator = func(p *Provisioner) error { waitForCommunicator = func(p *Provisioner) error {
return nil return nil
} }
waitForRestartOld := waitForRestart
waitForRestart = func(p *Provisioner, comm packer.Communicator) error {
return nil
}
err := p.Provision(ui, comm) err := p.Provision(ui, comm)
if err != nil { if err != nil {
t.Fatal("should not have error") t.Fatal("should not have error")
@ -142,6 +151,7 @@ func TestProvisionerProvision_CustomCommand(t *testing.T) {
} }
// Set this back! // Set this back!
waitForCommunicator = waitForCommunicatorOld waitForCommunicator = waitForCommunicatorOld
waitForRestart = waitForRestartOld
} }
func TestProvisionerProvision_RestartCommandFail(t *testing.T) { func TestProvisionerProvision_RestartCommandFail(t *testing.T) {