func CreateExternalVirtualSwitch(vmName string, switchName string) error { var script = ` param([string]$vmName,[string]$switchName) $switch = $null $names = @('ethernet','wi-fi','lan') $adapters = foreach ($name in $names) { Get-NetAdapter -Physical -Name $name -ErrorAction SilentlyContinue | where status -eq 'up' } foreach ($adapter in $adapters) { $switch = Get-VMSwitch -SwitchType External | where { $_.NetAdapterInterfaceDescription -eq $adapter.InterfaceDescription } if ($switch -eq $null) { $switch = New-VMSwitch -Name $switchName -NetAdapterName $adapter.Name -AllowManagementOS $true -Notes 'Parent OS, VMs, WiFi' } if ($switch -ne $null) { break } } if($switch -ne $null) { Get-VMNetworkAdapter -VMName $vmName | Connect-VMNetworkAdapter -VMSwitch $switch } else { Write-Error 'No internet adapters found' } ` var ps powershell.PowerShellCmd err := ps.Run(script, vmName, switchName) return err }
func MountFloppyDrive(vmName string, path string) error { var script = ` param([string]$vmName, [string]$path) Set-VMFloppyDiskDrive -VMName $vmName -Path $path ` var ps powershell.PowerShellCmd err := ps.Run(script, vmName, path) return err }
func UnmountDvdDrive(vmName string) error { var script = ` param([string]$vmName) Get-VMDvdDrive -VMName $vmName | Set-VMDvdDrive -Path $null ` var ps powershell.PowerShellCmd err := ps.Run(script, vmName) return err }
func SetVirtualMachineVlanId(vmName string, vlanId string) error { var script = ` param([string]$vmName,[string]$vlanId) Set-VMNetworkAdapterVlan -VMName $vmName -Access -VlanId $vlanId ` var ps powershell.PowerShellCmd err := ps.Run(script, vmName, vlanId) return err }
func ExportVirtualMachine(vmName string, path string) error { var script = ` param([string]$vmName, [string]$path) Export-VM -Name $vmName -Path $path ` var ps powershell.PowerShellCmd err := ps.Run(script, vmName, path) return err }
func RestartVirtualMachine(vmName string) error { var script = ` param([string]$vmName) Restart-VM $vmName -Force -Confirm:$false ` var ps powershell.PowerShellCmd err := ps.Run(script, vmName) return err }
func SetNetworkAdapterVlanId(switchName string, vlanId string) error { var script = ` param([string]$networkAdapterName,[string]$vlanId) Set-VMNetworkAdapterVlan -ManagementOS -VMNetworkAdapterName $networkAdapterName -Access -VlanId $vlanId ` var ps powershell.PowerShellCmd err := ps.Run(script, switchName, vlanId) return err }
func ConnectVirtualMachineNetworkAdapterToSwitch(vmName string, switchName string) error { var script = ` param([string]$vmName,[string]$switchName) Get-VMNetworkAdapter -VMName $vmName | Connect-VMNetworkAdapter -SwitchName $switchName ` var ps powershell.PowerShellCmd err := ps.Run(script, vmName, switchName) return err }
func SetVirtualMachineCpu(vmName string, cpu string) error { var script = ` param([string]$vmName, [int]$cpu) Set-VMProcessor -VMName $vmName -Count $cpu ` var ps powershell.PowerShellCmd err := ps.Run(script, vmName, cpu) return err }
func EnableVirtualMachineIntegrationService(vmName string, integrationServiceName string) error { var script = ` param([string]$vmName,[string]$integrationServiceName) Enable-VMIntegrationService -VMName $vmName -Name $integrationServiceName ` var ps powershell.PowerShellCmd err := ps.Run(script, vmName, integrationServiceName) return err }
func UntagVirtualMachineNetworkAdapterVlan(vmName string, switchName string) error { var script = ` param([string]$vmName,[string]$switchName) Set-VMNetworkAdapterVlan -VMName $vmName -Untagged Set-VMNetworkAdapterVlan -ManagementOS -VMNetworkAdapterName $switchName -Untagged ` var ps powershell.PowerShellCmd err := ps.Run(script, vmName, switchName) return err }
func CompactDisks(expPath string, vhdDir string) error { var script = ` param([string]$srcPath, [string]$vhdDirName) Get-ChildItem "$srcPath/$vhdDirName" -Filter *.vhd* | %{ Optimize-VHD -Path $_.FullName -Mode Full } ` var ps powershell.PowerShellCmd err := ps.Run(script, expPath, vhdDir) return err }
func CopyExportedVirtualMachine(expPath string, outputPath string, vhdDir string, vmDir string) error { var script = ` param([string]$srcPath, [string]$dstPath, [string]$vhdDirName, [string]$vmDir) Move-Item -Path $srcPath/*.* -Destination $dstPath Move-Item -Path $srcPath/$vhdDirName -Destination $dstPath Move-Item -Path $srcPath/$vmDir -Destination $dstPath ` var ps powershell.PowerShellCmd err := ps.Run(script, expPath, outputPath, vhdDir, vmDir) return err }
func ShutDown(vmName string) error { var script = ` param([string]$vmName) $vm = Get-VM -Name $vmName -ErrorAction SilentlyContinue if ($vm.State -eq [Microsoft.HyperV.PowerShell.VMState]::Running) { Stop-VM -Name $vmName -Confirm:$false } ` var ps powershell.PowerShellCmd err := ps.Run(script, vmName) return err }
func StopVirtualMachine(vmName string) error { var script = ` param([string]$vmName) $vm = Get-VM -Name $vmName if ($vm.State -eq [Microsoft.HyperV.PowerShell.VMState]::Running) { Stop-VM -VM $vm -Confirm:$false } ` var ps powershell.PowerShellCmd err := ps.Run(script, vmName) return err }
func DeleteVirtualSwitch(switchName string) error { var script = ` param([string]$switchName) $switch = Get-VMSwitch -Name $switchName -ErrorAction SilentlyContinue if ($switch -ne $null) { $switch | Remove-VMSwitch -Force -Confirm:$false } ` var ps powershell.PowerShellCmd err := ps.Run(script, switchName) return err }
func SetSecureBoot(vmName string, enable bool) error { var script = ` param([string]$vmName, $enableSecureBoot) Set-VMFirmware -VMName $vmName -EnableSecureBoot $enableSecureBoot ` var ps powershell.PowerShellCmd enableSecureBoot := "Off" if enable { enableSecureBoot = "On" } err := ps.Run(script, vmName, enableSecureBoot) return err }
func (s *StepUnmountSecondaryDvdImages) Run(state multistep.StateBag) multistep.StepAction { ui := state.Get("ui").(packer.Ui) ui.Say("Unmounting Integration Services Setup Disk...") vmName := state.Get("vmName").(string) // todo: should this message say removing the dvd? dvdProperties := state.Get("secondary.dvd.properties").([]DvdControllerProperties) log.Println(fmt.Sprintf("Found DVD properties %s", len(dvdProperties))) for _, dvdProperty := range dvdProperties { controllerNumber := dvdProperty.ControllerNumber controllerLocation := dvdProperty.ControllerLocation var script powershell.ScriptBuilder powershell := new(powershell.PowerShellCmd) script.WriteLine("param([string]$vmName,[int]$controllerNumber,[int]$controllerLocation)") script.WriteLine("$vmDvdDrive = Get-VMDvdDrive -VMName $vmName -ControllerNumber $controllerNumber -ControllerLocation $controllerLocation") script.WriteLine("if (!$vmDvdDrive) {throw 'unable to find dvd drive'}") script.WriteLine("Remove-VMDvdDrive -VMName $vmName -ControllerNumber $controllerNumber -ControllerLocation $controllerLocation") err := powershell.Run(script.String(), vmName, controllerNumber, controllerLocation) if err != nil { state.Put("error", err) ui.Error(err.Error()) return multistep.ActionHalt } } return multistep.ActionContinue }
func (s *StepUpdateIntegrationServices) mountIntegrationServicesSetupDisk(vmName string) (dvdDriveProperties, error) { var dvdProperties dvdDriveProperties var script powershell.ScriptBuilder script.WriteLine("param([string]$vmName)") script.WriteLine("Add-VMDvdDrive -VMName $vmName") powershell := new(powershell.PowerShellCmd) err := powershell.Run(script.String(), vmName) if err != nil { return dvdProperties, err } script.Reset() script.WriteLine("param([string]$vmName)") script.WriteLine("(Get-VMDvdDrive -VMName $vmName | Where-Object {$_.Path -eq $null}).ControllerLocation") controllerLocation, err := powershell.Output(script.String(), vmName) if err != nil { return dvdProperties, err } script.Reset() script.WriteLine("param([string]$vmName)") script.WriteLine("(Get-VMDvdDrive -VMName $vmName | Where-Object {$_.Path -eq $null}).ControllerNumber") controllerNumber, err := powershell.Output(script.String(), vmName) if err != nil { return dvdProperties, err } isoPath := os.Getenv("WINDIR") + "\\system32\\vmguest.iso" script.Reset() script.WriteLine("param([string]$vmName,[string]$path,[string]$controllerNumber,[string]$controllerLocation)") script.WriteLine("Set-VMDvdDrive -VMName $vmName -Path $path -ControllerNumber $controllerNumber -ControllerLocation $controllerLocation") err = powershell.Run(script.String(), vmName, isoPath, controllerNumber, controllerLocation) if err != nil { return dvdProperties, err } dvdProperties.ControllerNumber = controllerNumber dvdProperties.ControllerLocation = controllerLocation return dvdProperties, err }
func DeleteVirtualMachine(vmName string) error { var script = ` param([string]$vmName) $vm = Get-VM -Name $vmName if (($vm.State -ne [Microsoft.HyperV.PowerShell.VMState]::Off) -and ($vm.State -ne [Microsoft.HyperV.PowerShell.VMState]::OffCritical)) { Stop-VM -VM $vm -TurnOff -Force -Confirm:$false } Remove-VM -Name $vmName -Force -Confirm:$false ` var ps powershell.PowerShellCmd err := ps.Run(script, vmName) return err }
func (s *StepUpdateIntegrationServices) Cleanup(state multistep.StateBag) { vmName := state.Get("vmName").(string) var script powershell.ScriptBuilder script.WriteLine("param([string]$vmName)") script.WriteLine("Set-VMDvdDrive -VMName $vmName -Path $null") powershell := new(powershell.PowerShellCmd) _ = powershell.Run(script.String(), vmName) }
func (s *StepMountDvdDrive) Run(state multistep.StateBag) multistep.StepAction { //driver := state.Get("driver").(Driver) ui := state.Get("ui").(packer.Ui) errorMsg := "Error mounting dvd drive: %s" vmName := state.Get("vmName").(string) isoPath := s.RawSingleISOUrl // Check that there is a virtual dvd drive var script powershell.ScriptBuilder powershell := new(powershell.PowerShellCmd) script.Reset() script.WriteLine("param([string]$vmName)") script.WriteLine("(Get-VMDvdDrive -VMName $vmName).ControllerNumber") controllerNumber, err := powershell.Output(script.String(), vmName) if err != nil { state.Put("error", err) ui.Error(err.Error()) return multistep.ActionHalt } if controllerNumber == "" { // Add a virtual dvd drive as there is none script.Reset() script.WriteLine("param([string]$vmName)") script.WriteLine("Add-VMDvdDrive -VMName $vmName") script.WriteLine("$dvdDrive = Get-VMDvdDrive -VMName $vmName | Select-Object -first 1") script.WriteLine("Set-VMFirmware -VMName $vmName -FirstBootDevice $dvdDrive") err = powershell.Run(script.String(), vmName) if err != nil { state.Put("error", err) ui.Error(err.Error()) return multistep.ActionHalt } } ui.Say("Mounting dvd drive...") err = hyperv.MountDvdDrive(vmName, isoPath) if err != nil { err := fmt.Errorf(errorMsg, err) state.Put("error", err) ui.Error(err.Error()) return multistep.ActionHalt } s.path = isoPath return multistep.ActionContinue }
func CreateVirtualMachine(vmName string, path string, ram string, diskSize string, switchName string, generation string) error { if generation == "2" { var script = ` param([string]$vmName, [string]$path, [long]$memoryStartupBytes, [long]$newVHDSizeBytes, [string]$switchName, [int]$generation) $vhdx = $vmName + '.vhdx' $vhdPath = Join-Path -Path $path -ChildPath $vhdx New-VM -Name $vmName -Path $path -MemoryStartupBytes $memoryStartupBytes -NewVHDPath $vhdPath -NewVHDSizeBytes $newVHDSizeBytes -SwitchName $switchName -Generation $generation ` var ps powershell.PowerShellCmd err := ps.Run(script, vmName, path, ram, diskSize, switchName, generation) return err } else { var script = ` param([string]$vmName, [string]$path, [long]$memoryStartupBytes, [long]$newVHDSizeBytes, [string]$switchName) $vhdx = $vmName + '.vhdx' $vhdPath = Join-Path -Path $path -ChildPath $vhdx New-VM -Name $vmName -Path $path -MemoryStartupBytes $memoryStartupBytes -NewVHDPath $vhdPath -NewVHDSizeBytes $newVHDSizeBytes -SwitchName $switchName ` var ps powershell.PowerShellCmd err := ps.Run(script, vmName, path, ram, diskSize, switchName) return err } }
func (s *StepMountSecondaryDvdImages) addAndMountDvdDisk(vmName string, isoPath string) (DvdControllerProperties, error) { var properties DvdControllerProperties var script powershell.ScriptBuilder powershell := new(powershell.PowerShellCmd) controllerNumber := "0" if s.Generation < 2 { // get the controller number that the OS install disk is mounted on // generation 1 requires dvd to be added to ide controller, generation 2 uses scsi for dvd drives script.Reset() script.WriteLine("param([string]$vmName)") script.WriteLine("$dvdDrives = (Get-VMDvdDrive -VMName $vmName)") script.WriteLine("$lastControllerNumber = $dvdDrives | Sort-Object ControllerNumber | Select-Object -Last 1 | %{$_.ControllerNumber}") script.WriteLine("if (!$lastControllerNumber) {") script.WriteLine(" $lastControllerNumber = 0") script.WriteLine("} elseif (!$lastControllerNumber -or ($dvdDrives | ?{ $_.ControllerNumber -eq $lastControllerNumber} | measure).count -gt 1) {") script.WriteLine(" $lastControllerNumber += 1") script.WriteLine("}") script.WriteLine("$lastControllerNumber") controllerNumber, err := powershell.Output(script.String(), vmName) if err != nil { return properties, err } if controllerNumber != "0" || controllerNumber != "1" { //There are only 2 ide controllers, try to use the one the hdd is attached too controllerNumber = "0" } } script.Reset() script.WriteLine("param([string]$vmName,[int]$controllerNumber)") script.WriteLine("Add-VMDvdDrive -VMName $vmName -ControllerNumber $controllerNumber") err := powershell.Run(script.String(), vmName, controllerNumber) if err != nil { return properties, err } // we could try to get the controller location and number in one call, but this way we do not // need to parse the output script.Reset() script.WriteLine("param([string]$vmName)") script.WriteLine("(Get-VMDvdDrive -VMName $vmName | Where-Object {$_.Path -eq $null}).ControllerLocation") controllerLocation, err := powershell.Output(script.String(), vmName) if err != nil { return properties, err } script.Reset() script.WriteLine("param([string]$vmName,[string]$path,[string]$controllerNumber,[string]$controllerLocation)") script.WriteLine("Set-VMDvdDrive -VMName $vmName -Path $path -ControllerNumber $controllerNumber -ControllerLocation $controllerLocation") err = powershell.Run(script.String(), vmName, isoPath, controllerNumber, controllerLocation) if err != nil { return properties, err } log.Println(fmt.Sprintf("ISO %s mounted on DVD controller %v, location %v", isoPath, controllerNumber, controllerLocation)) properties.ControllerNumber = controllerNumber properties.ControllerLocation = controllerLocation return properties, nil }
func TypeScanCodes(vmName string, scanCodes string) error { var script = ` param([string]$vmName, [string]$scanCodes) #Requires -Version 3 #Requires -RunAsAdministrator function Get-VMConsole { [CmdletBinding()] param ( [Parameter(Mandatory)] [string] $VMName ) $ErrorActionPreference = "Stop" $vm = Get-CimInstance -ComputerName localhost -Namespace "root\virtualization\v2" -ClassName Msvm_ComputerSystem -ErrorAction Ignore -Verbose:$false | where ElementName -eq $VMName | select -first 1 if ($vm -eq $null){ Write-Error ("VirtualMachine({0}) is not found!" -f $VMName) } $vmKeyboard = $vm | Get-CimAssociatedInstance -ResultClassName "Msvm_Keyboard" -ErrorAction Ignore -Verbose:$false if ($vmKeyboard -eq $null){ Write-Error ("VirtualMachine({0}) keyboard class is not found!" -f $VMName) } #TODO: It may be better using New-Module -AsCustomObject to return console object? #Console object to return $console = [pscustomobject] @{ Msvm_ComputerSystem = $vm Msvm_Keyboard = $vmKeyboard } #Need to import assembly to use System.Windows.Input.Key Add-Type -AssemblyName WindowsBase #region Add Console Members $console | Add-Member -MemberType ScriptMethod -Name TypeText -Value { [OutputType([bool])] param ( [ValidateNotNullOrEmpty()] [Parameter(Mandatory)] [string] $AsciiText ) $result = $this.Msvm_Keyboard | Invoke-CimMethod -MethodName "TypeText" -Arguments @{ asciiText = $AsciiText } return (0 -eq $result.ReturnValue) } #Define method:TypeCtrlAltDel $console | Add-Member -MemberType ScriptMethod -Name TypeCtrlAltDel -Value { $result = $this.Msvm_Keyboard | Invoke-CimMethod -MethodName "TypeCtrlAltDel" return (0 -eq $result.ReturnValue) } #Define method:TypeKey $console | Add-Member -MemberType ScriptMethod -Name TypeKey -Value { [OutputType([bool])] param ( [Parameter(Mandatory)] [Windows.Input.Key] $Key, [Windows.Input.ModifierKeys] $ModifierKey = [Windows.Input.ModifierKeys]::None ) $keyCode = [Windows.Input.KeyInterop]::VirtualKeyFromKey($Key) switch ($ModifierKey) { ([Windows.Input.ModifierKeys]::Control){ $modifierKeyCode = [Windows.Input.KeyInterop]::VirtualKeyFromKey([Windows.Input.Key]::LeftCtrl)} ([Windows.Input.ModifierKeys]::Alt){ $modifierKeyCode = [Windows.Input.KeyInterop]::VirtualKeyFromKey([Windows.Input.Key]::LeftAlt)} ([Windows.Input.ModifierKeys]::Shift){ $modifierKeyCode = [Windows.Input.KeyInterop]::VirtualKeyFromKey([Windows.Input.Key]::LeftShift)} ([Windows.Input.ModifierKeys]::Windows){ $modifierKeyCode = [Windows.Input.KeyInterop]::VirtualKeyFromKey([Windows.Input.Key]::LWin)} } if ($ModifierKey -eq [Windows.Input.ModifierKeys]::None) { $result = $this.Msvm_Keyboard | Invoke-CimMethod -MethodName "TypeKey" -Arguments @{ keyCode = $keyCode } } else { $this.Msvm_Keyboard | Invoke-CimMethod -MethodName "PressKey" -Arguments @{ keyCode = $modifierKeyCode } $result = $this.Msvm_Keyboard | Invoke-CimMethod -MethodName "TypeKey" -Arguments @{ keyCode = $keyCode } $this.Msvm_Keyboard | Invoke-CimMethod -MethodName "ReleaseKey" -Arguments @{ keyCode = $modifierKeyCode } } $result = return (0 -eq $result.ReturnValue) } #Define method:Scancodes $console | Add-Member -MemberType ScriptMethod -Name TypeScancodes -Value { [OutputType([bool])] param ( [Parameter(Mandatory)] [byte[]] $ScanCodes ) $result = $this.Msvm_Keyboard | Invoke-CimMethod -MethodName "TypeScancodes" -Arguments @{ ScanCodes = $ScanCodes } return (0 -eq $result.ReturnValue) } #Define method:ExecCommand $console | Add-Member -MemberType ScriptMethod -Name ExecCommand -Value { param ( [Parameter(Mandatory)] [string] $Command ) if ([String]::IsNullOrEmpty($Command)){ return } $console.TypeText($Command) > $null $console.TypeKey([Windows.Input.Key]::Enter) > $null #sleep -Milliseconds 100 } #Define method:Dispose $console | Add-Member -MemberType ScriptMethod -Name Dispose -Value { $this.Msvm_ComputerSystem.Dispose() $this.Msvm_Keyboard.Dispose() } #endregion return $console } $vmConsole = Get-VMConsole -VMName $vmName $scanCodesToSend = '' $scanCodes.Split(' ') | %{ $scanCode = $_ if ($scanCode.StartsWith('wait')){ $timeToWait = $scanCode.Substring(4) if (!$timeToWait){ $timeToWait = "10" } Start-Sleep -s $timeToWait if ($scanCodesToSend){ $scanCodesToSendByteArray = [byte[]]@($scanCodesToSend.Split(' ') | %{"0x$_"}) $scanCodesToSendByteArray | %{ $vmConsole.TypeScancodes($_) } } $scanCodesToSend = '' } else { if ($scanCodesToSend){ $scanCodesToSend = "$scanCodesToSend $scanCode" } else { $scanCodesToSend = "$scanCode" } } } if ($scanCodesToSend){ $scanCodesToSendByteArray = [byte[]]@($scanCodesToSend.Split(' ') | %{"0x$_"}) $scanCodesToSendByteArray | %{ $vmConsole.TypeScancodes($_) } } ` var ps powershell.PowerShellCmd err := ps.Run(script, vmName, scanCodes) return err }