Skip to content
This repository has been archived by the owner on Sep 26, 2021. It is now read-only.

Commit

Permalink
Prepend hyper-v module name to fix cmdlet collision with vmware powercli
Browse files Browse the repository at this point in the history
Signed-off-by: Dave May <dave.may@tresta.com>
  • Loading branch information
Dave May committed Feb 23, 2018
1 parent 7c1c8d7 commit 15095c9
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 18 deletions.
34 changes: 17 additions & 17 deletions drivers/hyperv/hyperv.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ func (d *Driver) GetURL() (string, error) {
}

func (d *Driver) GetState() (state.State, error) {
stdout, err := cmdOut("(", "Get-VM", d.MachineName, ").state")
stdout, err := cmdOut("(", "hyper-v\\Get-VM", d.MachineName, ").state")
if err != nil {
return state.None, fmt.Errorf("Failed to find the VM status")
}
Expand Down Expand Up @@ -205,7 +205,7 @@ func (d *Driver) Create() error {
return err
}

if err := cmd("New-VM",
if err := cmd("hyper-v\\New-VM",
d.MachineName,
"-Path", fmt.Sprintf("'%s'", d.ResolveStorePath(".")),
"-SwitchName", quote(virtualSwitch),
Expand All @@ -214,37 +214,37 @@ func (d *Driver) Create() error {
}

if d.CPU > 1 {
if err := cmd("Set-VMProcessor",
if err := cmd("hyper-v\\Set-VMProcessor",
d.MachineName,
"-Count", fmt.Sprintf("%d", d.CPU)); err != nil {
return err
}
}

if d.MacAddr != "" {
if err := cmd("Set-VMNetworkAdapter",
if err := cmd("hyper-v\\Set-VMNetworkAdapter",
"-VMName", d.MachineName,
"-StaticMacAddress", fmt.Sprintf("\"%s\"", d.MacAddr)); err != nil {
return err
}
}

if d.VLanID > 0 {
if err := cmd("Set-VMNetworkAdapterVlan",
if err := cmd("hyper-v\\Set-VMNetworkAdapterVlan",
"-VMName", d.MachineName,
"-Access",
"-VlanId", fmt.Sprintf("%d", d.VLanID)); err != nil {
return err
}
}

if err := cmd("Set-VMDvdDrive",
if err := cmd("hyper-v\\Set-VMDvdDrive",
"-VMName", d.MachineName,
"-Path", quote(d.ResolveStorePath("boot2docker.iso"))); err != nil {
return err
}

if err := cmd("Add-VMHardDiskDrive",
if err := cmd("hyper-v\\Add-VMHardDiskDrive",
"-VMName", d.MachineName,
"-Path", quote(diskImage)); err != nil {
return err
Expand All @@ -257,7 +257,7 @@ func (d *Driver) Create() error {
func (d *Driver) chooseVirtualSwitch() (string, error) {
if d.VSwitch == "" {
// Default to the first external switche and in the process avoid DockerNAT
stdout, err := cmdOut("(Get-VMSwitch -SwitchType External).Name")
stdout, err := cmdOut("(hyper-v\\Get-VMSwitch -SwitchType External).Name")
if err != nil {
return "", err
}
Expand All @@ -271,7 +271,7 @@ func (d *Driver) chooseVirtualSwitch() (string, error) {
return switches[0], nil
}

stdout, err := cmdOut("(Get-VMSwitch).Name")
stdout, err := cmdOut("(hyper-v\\Get-VMSwitch).Name")
if err != nil {
return "", err
}
Expand Down Expand Up @@ -327,7 +327,7 @@ func (d *Driver) waitStopped() error {

// Start starts an host
func (d *Driver) Start() error {
if err := cmd("Start-VM", d.MachineName); err != nil {
if err := cmd("hyper-v\\Start-VM", d.MachineName); err != nil {
return err
}

Expand All @@ -343,7 +343,7 @@ func (d *Driver) Start() error {

// Stop stops an host
func (d *Driver) Stop() error {
if err := cmd("Stop-VM", d.MachineName); err != nil {
if err := cmd("hyper-v\\Stop-VM", d.MachineName); err != nil {
return err
}

Expand All @@ -369,7 +369,7 @@ func (d *Driver) Remove() error {
}
}

return cmd("Remove-VM", d.MachineName, "-Force")
return cmd("hyper-v\\Remove-VM", d.MachineName, "-Force")
}

// Restart stops and starts an host
Expand All @@ -384,7 +384,7 @@ func (d *Driver) Restart() error {

// Kill force stops an host
func (d *Driver) Kill() error {
if err := cmd("Stop-VM", d.MachineName, "-TurnOff"); err != nil {
if err := cmd("hyper-v\\Stop-VM", d.MachineName, "-TurnOff"); err != nil {
return err
}

Expand All @@ -406,7 +406,7 @@ func (d *Driver) GetIP() (string, error) {
return "", drivers.ErrHostIsNotRunning
}

stdout, err := cmdOut("((", "Get-VM", d.MachineName, ").networkadapters[0]).ipaddresses[0]")
stdout, err := cmdOut("((", "hyper-v\\Get-VM", d.MachineName, ").networkadapters[0]).ipaddresses[0]")
if err != nil {
return "", err
}
Expand Down Expand Up @@ -440,7 +440,7 @@ func (d *Driver) generateDiskImage() (string, error) {
}

log.Infof("Creating VHD")
if err := cmd("New-VHD", "-Path", quote(fixed), "-SizeBytes", fixedDiskSize, "-Fixed"); err != nil {
if err := cmd("hyper-v\\New-VHD", "-Path", quote(fixed), "-SizeBytes", fixedDiskSize, "-Fixed"); err != nil {
return "", err
}

Expand All @@ -462,12 +462,12 @@ func (d *Driver) generateDiskImage() (string, error) {
}
file.Close()

if err := cmd("Convert-VHD", "-Path", quote(fixed), "-DestinationPath", quote(diskImage), "-VHDType", "Dynamic", "-DeleteSource"); err != nil {
if err := cmd("hyper-v\\Convert-VHD", "-Path", quote(fixed), "-DestinationPath", quote(diskImage), "-VHDType", "Dynamic", "-DeleteSource"); err != nil {
return "", err
}

if isWindowsAdmin {
if err := cmd("Resize-VHD", "-Path", quote(diskImage), "-SizeBytes", toMb(d.DiskSize)); err != nil {
if err := cmd("hyper-v\\Resize-VHD", "-Path", quote(diskImage), "-SizeBytes", toMb(d.DiskSize)); err != nil {
return "", err
}
}
Expand Down
2 changes: 1 addition & 1 deletion drivers/hyperv/powershell.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ func parseLines(stdout string) []string {
}

func hypervAvailable() error {
stdout, err := cmdOut("@(Get-Command Get-VM).ModuleName")
stdout, err := cmdOut("@(Get-Command hyper-v\\Get-VM).ModuleName")

This comment has been minimized.

Copy link
@ChrislyBear-GH

ChrislyBear-GH Mar 22, 2018

This is wrong. It has to be

stdout, err := cmdOut("@(Get-Command hyper-v\Get-VM).Name")

The command that should be run (or checked) is "Get-VM" (= "Name" probperty) and not "hyper-v" (= "ModuleName" Property).

This comment has been minimized.

Copy link
@davemay99

davemay99 Mar 22, 2018

Contributor

@Chrisly3ear The problem I addressed in the commit is a namespace collision between VMware and Hyper-V commands. You will experience inconsistent results if you have both VMWare and Hyper-V PowerShell modules installed and do not fully qualify the namespace of the commands. This function is testing whether the hyper-v version of Get-VM is installed, so ModuleName is still the correct property to check. In addition the backslash needs to be escaped when encapsulated in the code.

You can test on your system with the following:

  1. Verify that the ModuleName of Get-VM is initially hyper-v
    @(Get-Command Get-VM).ModuleName

  2. Install the VMware module
    Install-Module -Name VMware.PowerCLI -Scope CurrentUser

  3. Verify that the ModuleName of Get-VM is now VMware.VimAutomation.Core
    @(Get-Command Get-VM).ModuleName

  4. Verify that prefacing the command with hyper-v results in the expected behavior
    @(Get-Command hyper-v\Get-VM).ModuleName

This comment has been minimized.

Copy link
@ChrislyBear-GH

ChrislyBear-GH Mar 22, 2018

Hi @davemay99 ,

I read about that, and the solution you implemented is elegant and functional. I think I couldn't express the problem properly.

I was using "minikube" (v0.25.1) to run Kubernetes locally. Upon the command minikube start --vm-driver=hyperv a docker-machine is being created, so this code will be executed.
The problem I stumbled upon is that cmdOut() executes the following command:

C:\Windows\system32\WindowsPowerShell\v1.0\powershell.exe -NoProfile -NonInteractive @(Get-Command hyper-v\\Get-VM).ModuleName

Now, If you run minikube or docker-machine in a PowerShell environment instead of a "regular" cmd.exe environment, like I do then the @(Get-Command hyper-v\\Get-VM).ModuleName part gets resolved to hyper-v, as expected. The command that will be executed by PowerShell will then be:

C:\Windows\system32\WindowsPowerShell\v1.0\powershell.exe -NoProfile -NonInteractive hyper-v

So it tries to start a new PowerShell instance that runs the command hyper-v, which isn't a valid command.
And that's the problem I had.

Maybe it's a problem with minikube 0.25.1 because it was working before. But I'm not sure yet.

The thing is, if you don't run docker-machine or a command that uses it, in a regular cmd.exe session but in a PowerShell session, the code at line 58 will fail.

Maybe a solution to this mess Microsoft created could be to change line 58 so that the resulting command will be

C:\Windows\system32\WindowsPowerShell\v1.0\powershell.exe -NoProfile -NonInteractive "@(Get-Command hyper-v\Get-VM).ModuleName"

Notice the double quotes around @(Get-Command hyper-v\Get-VM).ModuleName. This will work in cmd.exe as well as in powershell.exe!

I can't write Go, so I cannot suggest a fix, but the double quotes should be escaped and added to the parameter of cmdOut().

What do you think?

All the best,
Chris

P.S.: Sorry about the initial tone of my comment. I was at work and after a day of error messages and failiures I didn't have the patience to write a polite message. Sorry about that.

if err != nil {
return err
}
Expand Down

0 comments on commit 15095c9

Please sign in to comment.