diff --git a/builder/hyperv/iso/builder.go b/builder/hyperv/iso/builder.go index 849e7d90a..03c1e3f3f 100644 --- a/builder/hyperv/iso/builder.go +++ b/builder/hyperv/iso/builder.go @@ -7,6 +7,11 @@ package iso import ( "errors" "fmt" + "log" + "os" + "strings" + "time" + "github.com/mitchellh/multistep" hypervcommon "github.com/mitchellh/packer/builder/hyperv/common" "github.com/mitchellh/packer/common" @@ -16,10 +21,6 @@ import ( powershell "github.com/mitchellh/packer/powershell" "github.com/mitchellh/packer/powershell/hyperv" "github.com/mitchellh/packer/template/interpolate" - "log" - "os" - "strings" - "time" ) const ( @@ -148,13 +149,7 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { log.Println(fmt.Sprintf("%s: %v", "VMName", b.config.VMName)) if b.config.SwitchName == "" { - // no switch name, try to get one attached to a online network adapter - onlineSwitchName, err := hyperv.GetExternalOnlineVirtualSwitch() - if onlineSwitchName == "" || err != nil { - b.config.SwitchName = fmt.Sprintf("packer-%s", b.config.PackerBuildName) - } else { - b.config.SwitchName = onlineSwitchName - } + b.config.SwitchName = b.detectSwitchName() } if b.config.Cpu < 1 { @@ -455,11 +450,29 @@ func (b *Builder) checkRamSize() error { } func (b *Builder) checkHostAvailableMemory() string { - freeMB := powershell.GetHostAvailableMemory() + powershellAvailable, _, _ := powershell.IsPowershellAvailable() - if (freeMB - float64(b.config.RamSizeMB)) < LowRam { - return fmt.Sprintf("Hyper-V might fail to create a VM if there is not enough free memory in the system.") + if powershellAvailable { + freeMB := powershell.GetHostAvailableMemory() + + if (freeMB - float64(b.config.RamSizeMB)) < LowRam { + return fmt.Sprintf("Hyper-V might fail to create a VM if there is not enough free memory in the system.") + } } return "" } + +func (b *Builder) detectSwitchName() string { + powershellAvailable, _, _ := powershell.IsPowershellAvailable() + + if powershellAvailable { + // no switch name, try to get one attached to a online network adapter + onlineSwitchName, err := hyperv.GetExternalOnlineVirtualSwitch() + if onlineSwitchName != "" && err == nil { + return onlineSwitchName + } + } + + return fmt.Sprintf("packer-%s", b.config.PackerBuildName) +} diff --git a/builder/hyperv/iso/builder_test.go b/builder/hyperv/iso/builder_test.go index 5cc04163e..4d8f193a0 100644 --- a/builder/hyperv/iso/builder_test.go +++ b/builder/hyperv/iso/builder_test.go @@ -1,9 +1,10 @@ package iso import ( - "github.com/mitchellh/packer/packer" "reflect" "testing" + + "github.com/mitchellh/packer/packer" ) func testConfig() map[string]interface{} { @@ -31,6 +32,7 @@ func TestBuilder_ImplementsBuilder(t *testing.T) { func TestBuilderPrepare_Defaults(t *testing.T) { var b Builder config := testConfig() + warns, err := b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) diff --git a/powershell/powershell.go b/powershell/powershell.go index 28c3d908b..051f03a67 100644 --- a/powershell/powershell.go +++ b/powershell/powershell.go @@ -5,20 +5,20 @@ package powershell import ( + "bytes" "fmt" - "log" "io" + "io/ioutil" + "log" "os" "os/exec" - "strings" - "bytes" - "io/ioutil" "strconv" + "strings" ) const ( powerShellFalse = "False" - powerShellTrue = "True" + powerShellTrue = "True" ) type PowerShellCmd struct { @@ -31,14 +31,14 @@ func (ps *PowerShellCmd) Run(fileContents string, params ...string) error { return err } -// Output runs the PowerShell command and returns its standard output. +// Output runs the PowerShell command and returns its standard output. func (ps *PowerShellCmd) Output(fileContents string, params ...string) (string, error) { - path, err := ps.getPowerShellPath(); + path, err := ps.getPowerShellPath() if err != nil { - return "", nil + return "", err } - filename, err := saveScript(fileContents); + filename, err := saveScript(fileContents) if err != nil { return "", err } @@ -49,7 +49,7 @@ func (ps *PowerShellCmd) Output(fileContents string, params ...string) (string, if !debug { defer os.Remove(filename) } - + args := createArgs(filename, params...) if verbose { @@ -93,13 +93,23 @@ func (ps *PowerShellCmd) Output(fileContents string, params ...string) (string, log.Printf("stderr: %s", stderrString) } - return stdoutString, err; + return stdoutString, err +} + +func IsPowershellAvailable() (bool, string, error) { + path, err := exec.LookPath("powershell") + if err != nil { + return false, "", err + } else { + return false, path, err + } } func (ps *PowerShellCmd) getPowerShellPath() (string, error) { - path, err := exec.LookPath("powershell") - if err != nil { - log.Fatal("Cannot find PowerShell in the path", err) + powershellAvailable, path, err := IsPowershellAvailable() + + if !powershellAvailable { + log.Fatal("Cannot find PowerShell in the path") return "", err } @@ -111,7 +121,7 @@ func saveScript(fileContents string) (string, error) { if err != nil { return "", err } - + _, err = file.Write([]byte(fileContents)) if err != nil { return "", err @@ -132,7 +142,7 @@ func saveScript(fileContents string) (string, error) { } func createArgs(filename string, params ...string) []string { - args := make([]string,len(params)+4) + args := make([]string, len(params)+4) args[0] = "-ExecutionPolicy" args[1] = "Bypass" @@ -141,9 +151,9 @@ func createArgs(filename string, params ...string) []string { for key, value := range params { args[key+4] = value - } + } - return args; + return args } func GetHostAvailableMemory() float64 { @@ -158,7 +168,6 @@ func GetHostAvailableMemory() float64 { return freeMB } - func GetHostName(ip string) (string, error) { var script = ` @@ -174,7 +183,7 @@ try { // var ps PowerShellCmd - cmdOut, err := ps.Output(script, ip); + cmdOut, err := ps.Output(script, ip) if err != nil { return "", err } @@ -190,8 +199,8 @@ $administratorRole = [System.Security.Principal.WindowsBuiltInRole]::Administrat return $principal.IsInRole($administratorRole) ` - var ps PowerShellCmd - cmdOut, err := ps.Output(script); + var ps PowerShellCmd + cmdOut, err := ps.Output(script) if err != nil { return false, err } @@ -200,14 +209,13 @@ return $principal.IsInRole($administratorRole) return res == powerShellTrue, nil } - func ModuleExists(moduleName string) (bool, error) { var script = ` param([string]$moduleName) (Get-Module -Name $moduleName) -ne $null ` - var ps PowerShellCmd + var ps PowerShellCmd cmdOut, err := ps.Output(script) if err != nil { return false, err @@ -215,7 +223,7 @@ param([string]$moduleName) res := strings.TrimSpace(string(cmdOut)) - if(res == powerShellFalse){ + if res == powerShellFalse { err := fmt.Errorf("PowerShell %s module is not loaded. Make sure %s feature is on.", moduleName, moduleName) return false, err } @@ -249,7 +257,7 @@ $productKeyNode.InnerText = $productKey $unattend.Save($path) ` - var ps PowerShellCmd - err := ps.Run(script, path, productKey) - return err + var ps PowerShellCmd + err := ps.Run(script, path, productKey) + return err } diff --git a/powershell/powershell_test.go b/powershell/powershell_test.go index 43943cb69..91c9a83f8 100644 --- a/powershell/powershell_test.go +++ b/powershell/powershell_test.go @@ -6,11 +6,13 @@ import ( ) func TestOutput(t *testing.T) { + var ps PowerShellCmd - powerShellPath, err := ps.getPowerShellPath() - if err != nil { - t.Skipf("powershell not installed: %s", err) + powershellAvailable, _, _ := IsPowershellAvailable() + + if !powershellAvailable { + t.Skipf("powershell not installed") return } @@ -43,17 +45,18 @@ func TestOutput(t *testing.T) { } func TestRunFile(t *testing.T) { + var ps PowerShellCmd + + powershellAvailable, _, _ := IsPowershellAvailable() + + if !powershellAvailable { + t.Skipf("powershell not installed") + return + } + var blockBuffer bytes.Buffer blockBuffer.WriteString(`param([string]$a, [string]$b, [int]$x, [int]$y) if (Test-Path variable:global:ProgressPreference){$ProgressPreference="SilentlyContinue"}; $n = $x + $y; Write-Output "$a $b $n";`) - var ps PowerShellCmd - - powerShellPath, err := ps.getPowerShellPath() - if err != nil { - t.Skipf("powershell not installed: %s", err) - return - } - cmdOut, err := ps.Output(blockBuffer.String(), "a", "b", "5", "10") if err != nil {