Merge pull request #5563 from hashicorp/fix_5483

make restart command work correctly even if user has their own check …
This commit is contained in:
SwampDragons 2017-11-09 16:16:47 -08:00 committed by GitHub
commit ce1f2457fd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 52 additions and 17 deletions

View File

@ -3,7 +3,7 @@ package restart
import ( import (
"bytes" "bytes"
"fmt" "fmt"
"io"
"log" "log"
"strings" "strings"
"sync" "sync"
@ -17,7 +17,7 @@ import (
) )
var DefaultRestartCommand = "shutdown /r /f /t 0 /c \"packer restart\"" var DefaultRestartCommand = "shutdown /r /f /t 0 /c \"packer restart\""
var DefaultRestartCheckCommand = winrm.Powershell(`if (Test-Path variable:global:ProgressPreference){$ProgressPreference='SilentlyContinue'}; 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 TryCheckReboot = "shutdown.exe -f -r -t 60"
var AbortReboot = "shutdown.exe -a" var AbortReboot = "shutdown.exe -a"
@ -174,30 +174,58 @@ WaitLoop:
} }
var waitForCommunicator = func(p *Provisioner) error { var waitForCommunicator = func(p *Provisioner) error {
runCustomRestartCheck := true
if p.config.RestartCheckCommand == DefaultRestartCheckCommand {
runCustomRestartCheck = false
}
// This command is configurable by the user to make sure that the
// vm has met their necessary criteria for having restarted. If the
// user doesn't set a special restart command, we just run the
// default as cmdModuleLoad below.
cmdRestartCheck := &packer.RemoteCmd{Command: p.config.RestartCheckCommand}
log.Printf("Checking that communicator is connected with: '%s'",
cmdRestartCheck.Command)
for { for {
cmd := &packer.RemoteCmd{Command: p.config.RestartCheckCommand}
var buf, buf2 bytes.Buffer
cmd.Stdout = &buf
cmd.Stdout = io.MultiWriter(cmd.Stdout, &buf2)
select { select {
case <-p.cancel: case <-p.cancel:
log.Println("Communicator wait canceled, exiting loop") log.Println("Communicator wait canceled, exiting loop")
return fmt.Errorf("Communicator wait canceled") return fmt.Errorf("Communicator wait canceled")
case <-time.After(retryableSleep): case <-time.After(retryableSleep):
} }
if runCustomRestartCheck {
log.Printf("Checking that communicator is connected with: '%s'", cmd.Command) // run user-configured restart check
err := cmdRestartCheck.StartWithUi(p.comm, p.ui)
err := cmd.StartWithUi(p.comm, p.ui)
if err != nil { if err != nil {
log.Printf("Communication connection err: %s", err) log.Printf("Communication connection err: %s", err)
continue continue
} }
log.Printf("Connected to machine") log.Printf("Connected to machine")
stdoutToRead := buf2.String() runCustomRestartCheck = false
}
// This is the non-user-configurable check that powershell
// modules have loaded.
// If we catch the restart in just the right place, we will be able
// to run the restart check but the output will be an error message
// about how it needs powershell modules to load, and we will start
// provisioning before powershell is actually ready.
// In this next check, we parse stdout to make sure that the command is
// actually running as expected.
var stdout, stderr bytes.Buffer
cmdModuleLoad := &packer.RemoteCmd{
Command: DefaultRestartCheckCommand,
Stdin: nil,
Stdout: &stdout,
Stderr: &stderr}
p.comm.Start(cmdModuleLoad)
cmdModuleLoad.Wait()
stdoutToRead := stdout.String()
stderrToRead := stderr.String()
if !strings.Contains(stdoutToRead, "restarted.") { if !strings.Contains(stdoutToRead, "restarted.") {
log.Printf("Stderr is %s", stderrToRead)
log.Printf("echo didn't succeed; retrying...") log.Printf("echo didn't succeed; retrying...")
continue continue
} }

View File

@ -42,7 +42,14 @@ Optional parameters:
detect it is rebooting. detect it is rebooting.
- `restart_check_command` (string) - A command to execute to check if the - `restart_check_command` (string) - A command to execute to check if the
restart succeeded. This will be done in a loop. restart succeeded. This will be done in a loop. Example usage:
``` json
{
"type": "windows-restart",
"restart_check_command": "powershell -command \"& {Write-Output 'restarted.'}\""
},
```
- `restart_timeout` (string) - The timeout to wait for the restart. By - `restart_timeout` (string) - The timeout to wait for the restart. By
default this is 5 minutes. Example value: `5m`. If you are installing default this is 5 minutes. Example value: `5m`. If you are installing