2015-06-21 07:36:07 -04:00
package hyperv
import (
"github.com/mitchellh/packer/powershell"
2015-10-30 04:23:30 -04:00
"strconv"
2015-06-21 07:36:07 -04:00
"strings"
)
2015-06-27 17:36:39 -04:00
func GetHostAdapterIpAddressForSwitch ( switchName string ) ( string , error ) {
var script = `
param ( [ string ] $ switchName , [ int ] $ addressIndex )
$ HostVMAdapter = Get - VMNetworkAdapter - ManagementOS - SwitchName $ switchName
if ( $ HostVMAdapter ) {
$ HostNetAdapter = Get - NetAdapter | ? { $ _ . DeviceID - eq $ HostVMAdapter . DeviceId }
if ( $ HostNetAdapter ) {
$ HostNetAdapterConfiguration = @ ( get - wmiobject win32_networkadapterconfiguration - filter "IPEnabled = 'TRUE' AND InterfaceIndex=$($HostNetAdapter.ifIndex)" )
if ( $ HostNetAdapterConfiguration ) {
2015-10-25 18:28:01 -04:00
return @ ( $ HostNetAdapterConfiguration . IpAddress ) [ $ addressIndex ]
2015-06-27 17:36:39 -04:00
}
}
}
return $ false
`
var ps powershell . PowerShellCmd
cmdOut , err := ps . Output ( script , switchName , "0" )
return cmdOut , err
}
2015-06-21 07:36:07 -04:00
func GetVirtualMachineNetworkAdapterAddress ( vmName string ) ( string , error ) {
var script = `
param ( [ string ] $ vmName , [ int ] $ addressIndex )
try {
$ adapter = Get - VMNetworkAdapter - VMName $ vmName - ErrorAction SilentlyContinue
$ ip = $ adapter . IPAddresses [ $ addressIndex ]
if ( $ ip - eq $ null ) {
return $ false
}
} catch {
return $ false
}
$ ip
`
var ps powershell . PowerShellCmd
cmdOut , err := ps . Output ( script , vmName , "0" )
return cmdOut , err
}
2015-12-05 06:03:33 -05:00
func CreateDvdDrive ( vmName string , isoPath string , generation uint ) ( uint , uint , error ) {
2015-10-30 04:23:30 -04:00
var ps powershell . PowerShellCmd
var script string
var controllerNumber uint
controllerNumber = 0
if 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 = `
param ( [ string ] $ vmName )
2015-11-07 08:19:37 -05:00
$ dvdDrives = @ ( Get - VMDvdDrive - VMName $ vmName )
2015-10-30 04:23:30 -04:00
$ lastControllerNumber = $ dvdDrives | Sort - Object ControllerNumber | Select - Object - Last 1 | % { $ _ . ControllerNumber }
if ( ! $ lastControllerNumber ) {
$ lastControllerNumber = 0
} elseif ( ! $ lastControllerNumber - or ( $ dvdDrives | ? { $ _ . ControllerNumber - eq $ lastControllerNumber } | measure ) . count - gt 1 ) {
$ lastControllerNumber += 1
}
$ lastControllerNumber
`
cmdOut , err := ps . Output ( script , vmName )
if err != nil {
return 0 , 0 , err
}
controllerNumberTemp , err := strconv . ParseUint ( strings . TrimSpace ( cmdOut ) , 10 , 64 )
if err != nil {
return 0 , 0 , err
}
controllerNumber = uint ( controllerNumberTemp )
if controllerNumber != 0 && controllerNumber != 1 {
//There are only 2 ide controllers, try to use the one the hdd is attached too
controllerNumber = 0
}
}
script = `
2015-12-05 06:03:33 -05:00
param ( [ string ] $ vmName , [ string ] $ isoPath , [ int ] $ controllerNumber )
$ dvdController = Add - VMDvdDrive - VMName $ vmName - ControllerNumber $ controllerNumber - path $ isoPath - Passthru
2015-12-05 06:13:38 -05:00
$ dvdController | Set - VMDvdDrive - path $ null
2015-11-07 08:19:37 -05:00
$ dvdController . ControllerLocation
2015-10-30 04:23:30 -04:00
`
2015-12-05 06:03:33 -05:00
cmdOut , err := ps . Output ( script , vmName , isoPath , strconv . FormatInt ( int64 ( controllerNumber ) , 10 ) )
2015-10-30 04:23:30 -04:00
if err != nil {
return controllerNumber , 0 , err
}
controllerLocationTemp , err := strconv . ParseUint ( strings . TrimSpace ( cmdOut ) , 10 , 64 )
if err != nil {
return controllerNumber , 0 , err
}
controllerLocation := uint ( controllerLocationTemp )
return controllerNumber , controllerLocation , err
}
2015-11-01 11:00:56 -05:00
func MountDvdDrive ( vmName string , path string , controllerNumber uint , controllerLocation uint ) error {
2015-10-30 04:23:30 -04:00
var script = `
param ( [ string ] $ vmName , [ string ] $ path , [ string ] $ controllerNumber , [ string ] $ controllerLocation )
2015-11-01 11:00:56 -05:00
$ vmDvdDrive = Get - VMDvdDrive - VMName $ vmName - ControllerNumber $ controllerNumber - ControllerLocation $ controllerLocation
if ( ! $ vmDvdDrive ) { throw ' unable to find dvd drive ' }
Set - VMDvdDrive - VMName $ vmName - ControllerNumber $ controllerNumber - ControllerLocation $ controllerLocation - Path $ path
2015-10-30 04:23:30 -04:00
`
var ps powershell . PowerShellCmd
err := ps . Run ( script , vmName , path , strconv . FormatInt ( int64 ( controllerNumber ) , 10 ) , strconv . FormatInt ( int64 ( controllerLocation ) , 10 ) )
return err
}
2015-11-01 11:00:56 -05:00
func UnmountDvdDrive ( vmName string , controllerNumber uint , controllerLocation uint ) error {
2015-06-21 07:36:07 -04:00
var script = `
2015-11-01 11:00:56 -05:00
param ( [ string ] $ vmName , [ int ] $ controllerNumber , [ int ] $ controllerLocation )
$ vmDvdDrive = Get - VMDvdDrive - VMName $ vmName - ControllerNumber $ controllerNumber - ControllerLocation $ controllerLocation
if ( ! $ vmDvdDrive ) { throw ' unable to find dvd drive ' }
Set - VMDvdDrive - VMName $ vmName - ControllerNumber $ controllerNumber - ControllerLocation $ controllerLocation - Path $ null
2015-06-21 07:36:07 -04:00
`
var ps powershell . PowerShellCmd
2015-11-01 11:00:56 -05:00
err := ps . Run ( script , vmName , strconv . FormatInt ( int64 ( controllerNumber ) , 10 ) , strconv . FormatInt ( int64 ( controllerLocation ) , 10 ) )
2015-06-21 07:36:07 -04:00
return err
}
2015-11-07 08:42:26 -05:00
func SetBootDvdDrive ( vmName string , controllerNumber uint , controllerLocation uint , generation uint ) error {
if generation < 2 {
script := `
param ( [ string ] $ vmName )
Set - VMBios - VMName $ vmName - StartupOrder @ ( "CD" , "IDE" , "LegacyNetworkAdapter" , "Floppy" )
`
var ps powershell . PowerShellCmd
err := ps . Run ( script , vmName )
return err
} else {
script := `
2015-10-30 13:19:25 -04:00
param ( [ string ] $ vmName , [ int ] $ controllerNumber , [ int ] $ controllerLocation )
$ vmDvdDrive = Get - VMDvdDrive - VMName $ vmName - ControllerNumber $ controllerNumber - ControllerLocation $ controllerLocation
if ( ! $ vmDvdDrive ) { throw ' unable to find dvd drive ' }
2015-12-05 06:41:30 -05:00
Set - VMFirmware - VMName $ vmName - FirstBootDevice $ vmDvdDrive - ErrorAction SilentlyContinue
2015-10-30 13:19:25 -04:00
`
2015-11-07 08:42:26 -05:00
var ps powershell . PowerShellCmd
err := ps . Run ( script , vmName , strconv . FormatInt ( int64 ( controllerNumber ) , 10 ) , strconv . FormatInt ( int64 ( controllerLocation ) , 10 ) )
return err
}
2015-10-30 13:19:25 -04:00
}
func DeleteDvdDrive ( vmName string , controllerNumber uint , controllerLocation uint ) error {
2015-10-30 04:23:30 -04:00
var script = `
param ( [ string ] $ vmName , [ int ] $ controllerNumber , [ int ] $ controllerLocation )
$ vmDvdDrive = Get - VMDvdDrive - VMName $ vmName - ControllerNumber $ controllerNumber - ControllerLocation $ controllerLocation
if ( ! $ vmDvdDrive ) { throw ' unable to find dvd drive ' }
Remove - VMDvdDrive - VMName $ vmName - ControllerNumber $ controllerNumber - ControllerLocation $ controllerLocation
`
var ps powershell . PowerShellCmd
2015-10-30 13:19:25 -04:00
err := ps . Run ( script , vmName , strconv . FormatInt ( int64 ( controllerNumber ) , 10 ) , strconv . FormatInt ( int64 ( controllerLocation ) , 10 ) )
2015-10-30 04:23:30 -04:00
return err
}
2015-11-30 08:34:35 -05:00
func DeleteAllDvdDrives ( vmName string ) error {
var script = `
param ( [ string ] $ vmName )
Get - VMDvdDrive - VMName $ vmName | Remove - VMDvdDrive
`
var ps powershell . PowerShellCmd
err := ps . Run ( script , vmName )
return err
}
2015-06-21 07:36:07 -04:00
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 UnmountFloppyDrive ( vmName string ) error {
var script = `
param ( [ string ] $ vmName )
Set - VMFloppyDiskDrive - VMName $ vmName - Path $ null
`
var ps powershell . PowerShellCmd
err := ps . Run ( script , vmName )
return err
}
2015-10-30 04:23:30 -04:00
func CreateVirtualMachine ( vmName string , path string , ram int64 , diskSize int64 , switchName string , generation uint ) error {
2015-06-21 07:36:07 -04:00
2015-10-30 04:23:30 -04:00
if generation == 2 {
2015-06-29 16:18:25 -04:00
var script = `
2015-06-22 17:26:06 -04:00
param ( [ string ] $ vmName , [ string ] $ path , [ long ] $ memoryStartupBytes , [ long ] $ newVHDSizeBytes , [ string ] $ switchName , [ int ] $ generation )
2015-06-21 07:36:07 -04:00
$ vhdx = $ vmName + ' . vhdx '
$ vhdPath = Join - Path - Path $ path - ChildPath $ vhdx
2015-06-21 14:35:32 -04:00
New - VM - Name $ vmName - Path $ path - MemoryStartupBytes $ memoryStartupBytes - NewVHDPath $ vhdPath - NewVHDSizeBytes $ newVHDSizeBytes - SwitchName $ switchName - Generation $ generation
2015-06-21 07:36:07 -04:00
`
2015-06-29 16:18:25 -04:00
var ps powershell . PowerShellCmd
2015-10-30 04:23:30 -04:00
err := ps . Run ( script , vmName , path , strconv . FormatInt ( ram , 10 ) , strconv . FormatInt ( diskSize , 10 ) , switchName , strconv . FormatInt ( int64 ( generation ) , 10 ) )
2015-06-29 16:18:25 -04:00
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
2015-10-30 04:23:30 -04:00
err := ps . Run ( script , vmName , path , strconv . FormatInt ( ram , 10 ) , strconv . FormatInt ( diskSize , 10 ) , switchName )
2015-11-07 11:20:55 -05:00
if err != nil {
return err
}
2015-11-30 08:34:35 -05:00
return DeleteAllDvdDrives ( vmName )
2015-06-29 16:18:25 -04:00
}
2015-06-21 14:35:32 -04:00
}
2015-10-30 04:23:30 -04:00
func SetVirtualMachineCpu ( vmName string , cpu uint ) error {
2015-06-21 14:35:32 -04:00
var script = `
2015-06-22 17:26:06 -04:00
param ( [ string ] $ vmName , [ int ] $ cpu )
Set - VMProcessor - VMName $ vmName - Count $ cpu
2015-06-21 14:35:32 -04:00
`
var ps powershell . PowerShellCmd
2015-10-30 04:23:30 -04:00
err := ps . Run ( script , vmName , strconv . FormatInt ( int64 ( cpu ) , 10 ) )
2015-06-21 07:36:07 -04:00
return err
}
2015-06-29 16:18:25 -04:00
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
}
2015-06-21 07:36:07 -04:00
func DeleteVirtualMachine ( vmName string ) error {
var script = `
param ( [ string ] $ vmName )
2015-06-24 14:52:42 -04:00
$ vm = Get - VM - Name $ vmName
if ( ( $ vm . State - ne [ Microsoft . HyperV . PowerShell . VMState ] : : Off ) - and ( $ vm . State - ne [ Microsoft . HyperV . PowerShell . VMState ] : : OffCritical ) ) {
2015-06-27 17:36:39 -04:00
Stop - VM - VM $ vm - TurnOff - Force - Confirm : $ false
2015-06-24 14:52:42 -04:00
}
2015-07-14 02:51:03 -04:00
Remove - VM - Name $ vmName - Force - Confirm : $ false
2015-06-21 07:36:07 -04:00
`
var ps powershell . PowerShellCmd
err := ps . Run ( script , vmName )
return err
}
func ExportVirtualMachine ( vmName string , path string ) error {
var script = `
param ( [ string ] $ vmName , [ string ] $ path )
Export - VM - Name $ vmName - Path $ path
2015-11-30 23:44:34 -05:00
if ( Test - Path - Path ( [ IO . Path ] : : Combine ( $ path , $ vmName , ' Virtual Machines ' , ' * . VMCX ' ) ) )
{
$ vm = Get - VM - Name $ vmName
$ vm_adapter = Get - VMNetworkAdapter - VM $ vm | Select - First 1
$ config = [ xml ] @ "
< ? xml version = "1.0" ? >
< configuration >
< properties >
< subtype type = "integer" > $ ( $ vm . Generation - 1 ) < / subtype >
< name type = "string" > $ ( $ vm . Name ) < / name >
< / properties >
< settings >
< processors >
< count type = "integer" > $ ( $ vm . ProcessorCount ) < / count >
< / processors >
< memory >
< bank >
< dynamic_memory_enabled type = "bool" > $ ( $ vm . DynamicMemoryEnabled ) < / dynamic_memory_enabled >
< limit type = "integer" > $ ( $ vm . MemoryMaximum / 1 MB ) < / limit >
< reservation type = "integer" > $ ( $ vm . MemoryMinimum / 1 MB ) < / reservation >
< size type = "integer" > $ ( $ vm . MemoryStartup / 1 MB ) < / size >
< / bank >
< / memory >
< / settings >
< AltSwitchName type = "string" > $ ( $ vm_adapter . SwitchName ) < / AltSwitchName >
< boot >
< device0 type = "string" > Optical < / device0 >
< / boot >
< secure_boot_enabled type = "bool" > False < / secure_boot_enabled >
< notes type = "string" > $ ( $ vm . Notes ) < / notes >
< vm - controllers / >
< / configuration >
" @
if ( $ vm . Generation - eq 1 )
{
$ vm_controllers = Get - VMIdeController - VM $ vm
$ controller_type = $ config . SelectSingleNode ( ' / configuration / vm - controllers ' )
# IDE controllers are not stored in a special XML container
}
else
{
$ vm_controllers = Get - VMScsiController - VM $ vm
$ controller_type = $ config . CreateElement ( ' scsi ' )
$ controller_type . SetAttribute ( ' ChannelInstanceGuid ' , 'x' )
# SCSI controllers are stored in the scsi XML container
if ( ( Get - VMFirmware - VM $ vm ) . SecureBoot - eq [ Microsoft . HyperV . PowerShell . OnOffState ] : : On )
{
$ config . configuration . secure_boot_enabled . ' # text ' = ' True '
}
else
{
$ config . configuration . secure_boot_enabled . ' # text ' = ' False '
}
}
$ vm_controllers | ForEach {
$ controller = $ config . CreateElement ( ' controller ' + $ _ . ControllerNumber )
$ _ . Drives | ForEach {
$ drive = $ config . CreateElement ( ' drive ' + ( $ _ . DiskNumber + 0 ) )
$ drive_path = $ config . CreateElement ( ' pathname ' )
$ drive_path . SetAttribute ( ' type ' , ' string ' )
$ drive_path . AppendChild ( $ config . CreateTextNode ( $ _ . Path ) )
$ drive_type = $ config . CreateElement ( ' type ' )
$ drive_type . SetAttribute ( ' type ' , ' string ' )
if ( $ _ - is [ Microsoft . HyperV . PowerShell . HardDiskDrive ] )
{
$ drive_type . AppendChild ( $ config . CreateTextNode ( ' VHD ' ) )
}
elseif ( $ _ - is [ Microsoft . HyperV . PowerShell . DvdDrive ] )
{
$ drive_type . AppendChild ( $ config . CreateTextNode ( ' ISO ' ) )
}
else
{
$ drive_type . AppendChild ( $ config . CreateTextNode ( ' NONE ' ) )
}
$ drive . AppendChild ( $ drive_path )
$ drive . AppendChild ( $ drive_type )
$ controller . AppendChild ( $ drive )
}
$ controller_type . AppendChild ( $ controller )
}
if ( $ controller_type . Name - ne ' vm - controllers ' )
{
$ config . SelectSingleNode ( ' / configuration / vm - controllers ' ) . AppendChild ( $ controller_type )
}
$ config . Save ( [ IO . Path ] : : Combine ( $ path , $ vm . Name , ' Virtual Machines ' , ' box . xml ' ) )
}
2015-06-21 07:36:07 -04:00
`
var ps powershell . PowerShellCmd
err := ps . Run ( script , vmName , path )
return err
}
2015-06-27 17:36:39 -04:00
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
}
2015-06-21 07:36:07 -04:00
func CopyExportedVirtualMachine ( expPath string , outputPath string , vhdDir string , vmDir string ) error {
var script = `
param ( [ string ] $ srcPath , [ string ] $ dstPath , [ string ] $ vhdDirName , [ string ] $ vmDir )
2015-07-16 15:48:08 -04:00
Move - Item - Path $ srcPath / * . * - Destination $ dstPath
Move - Item - Path $ srcPath / $ vhdDirName - Destination $ dstPath
Move - Item - Path $ srcPath / $ vmDir - Destination $ dstPath
2015-06-21 07:36:07 -04:00
`
var ps powershell . PowerShellCmd
err := ps . Run ( script , expPath , outputPath , vhdDir , vmDir )
return err
}
func CreateVirtualSwitch ( switchName string , switchType string ) ( bool , error ) {
var script = `
param ( [ string ] $ switchName , [ string ] $ switchType )
$ switches = Get - VMSwitch - Name $ switchName - ErrorAction SilentlyContinue
if ( $ switches . Count - eq 0 ) {
New - VMSwitch - Name $ switchName - SwitchType $ switchType
return $ true
}
return $ false
`
var ps powershell . PowerShellCmd
cmdOut , err := ps . Output ( script , switchName , switchType )
var created = strings . TrimSpace ( cmdOut ) == "True"
return created , err
}
func DeleteVirtualSwitch ( switchName string ) error {
var script = `
param ( [ string ] $ switchName )
$ switch = Get - VMSwitch - Name $ switchName - ErrorAction SilentlyContinue
if ( $ switch - ne $ null ) {
2015-07-14 02:51:03 -04:00
$ switch | Remove - VMSwitch - Force - Confirm : $ false
2015-06-21 07:36:07 -04:00
}
`
var ps powershell . PowerShellCmd
err := ps . Run ( script , switchName )
return err
}
func StartVirtualMachine ( vmName string ) error {
var script = `
param ( [ string ] $ vmName )
2015-06-27 17:36:39 -04:00
$ vm = Get - VM - Name $ vmName - ErrorAction SilentlyContinue
if ( $ vm . State - eq [ Microsoft . HyperV . PowerShell . VMState ] : : Off ) {
2015-07-14 02:51:03 -04:00
Start - VM - Name $ vmName - Confirm : $ false
2015-06-27 17:36:39 -04:00
}
2015-06-21 07:36:07 -04:00
`
var ps powershell . PowerShellCmd
err := ps . Run ( script , vmName )
return err
}
func RestartVirtualMachine ( vmName string ) error {
var script = `
param ( [ string ] $ vmName )
2015-07-14 02:51:03 -04:00
Restart - VM $ vmName - Force - Confirm : $ false
2015-06-21 07:36:07 -04:00
`
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 ) {
2015-10-26 20:12:41 -04:00
Stop - VM - VM $ vm - Force - Confirm : $ false
2015-06-21 07:36:07 -04:00
}
`
var ps powershell . PowerShellCmd
err := ps . Run ( script , vmName )
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 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 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 GetExternalOnlineVirtualSwitch ( ) ( string , error ) {
var script = `
$ adapters = Get - NetAdapter - Physical - ErrorAction SilentlyContinue | Where - Object { $ _ . Status - eq ' Up ' } | Sort - Object - Descending - Property Speed
foreach ( $ adapter in $ adapters ) {
$ switch = Get - VMSwitch - SwitchType External | Where - Object { $ _ . NetAdapterInterfaceDescription - eq $ adapter . InterfaceDescription }
if ( $ switch - ne $ null ) {
$ switch . Name
break
}
}
`
var ps powershell . PowerShellCmd
cmdOut , err := ps . Output ( script )
if err != nil {
return "" , err
}
var switchName = strings . TrimSpace ( cmdOut )
return switchName , nil
}
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 ) {
2015-06-27 17:36:39 -04:00
Get - VMNetworkAdapter - VMName $ vmName | Connect - VMNetworkAdapter - VMSwitch $ switch
2015-06-21 07:36:07 -04:00
} else {
Write - Error ' No internet adapters found '
}
`
var ps powershell . PowerShellCmd
err := ps . Run ( script , vmName , switchName )
return err
}
func GetVirtualMachineSwitchName ( vmName string ) ( string , error ) {
var script = `
param ( [ string ] $ vmName )
( Get - VMNetworkAdapter - VMName $ vmName ) . SwitchName
`
var ps powershell . PowerShellCmd
cmdOut , err := ps . Output ( script , vmName )
if err != nil {
return "" , err
}
return strings . TrimSpace ( cmdOut ) , nil
}
func ConnectVirtualMachineNetworkAdapterToSwitch ( vmName string , switchName string ) error {
var script = `
param ( [ string ] $ vmName , [ string ] $ switchName )
2015-06-27 17:36:39 -04:00
Get - VMNetworkAdapter - VMName $ vmName | Connect - VMNetworkAdapter - SwitchName $ switchName
2015-06-21 07:36:07 -04:00
`
var ps powershell . PowerShellCmd
err := ps . Run ( script , vmName , switchName )
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 IsRunning ( vmName string ) ( bool , error ) {
var script = `
param ( [ string ] $ vmName )
$ vm = Get - VM - Name $ vmName - ErrorAction SilentlyContinue
$ vm . State - eq [ Microsoft . HyperV . PowerShell . VMState ] : : Running
`
var ps powershell . PowerShellCmd
cmdOut , err := ps . Output ( script , vmName )
2015-10-30 04:23:30 -04:00
if err != nil {
return false , err
}
2015-06-21 07:36:07 -04:00
var isRunning = strings . TrimSpace ( cmdOut ) == "True"
return isRunning , err
}
2015-10-30 04:23:30 -04:00
func IsOff ( vmName string ) ( bool , error ) {
var script = `
param ( [ string ] $ vmName )
$ vm = Get - VM - Name $ vmName - ErrorAction SilentlyContinue
$ vm . State - eq [ Microsoft . HyperV . PowerShell . VMState ] : : Off
`
var ps powershell . PowerShellCmd
cmdOut , err := ps . Output ( script , vmName )
if err != nil {
return false , err
}
var isRunning = strings . TrimSpace ( cmdOut ) == "True"
return isRunning , err
}
func Uptime ( vmName string ) ( uint64 , error ) {
var script = `
param ( [ string ] $ vmName )
$ vm = Get - VM - Name $ vmName - ErrorAction SilentlyContinue
$ vm . Uptime . TotalSeconds
`
var ps powershell . PowerShellCmd
cmdOut , err := ps . Output ( script , vmName )
if err != nil {
return 0 , err
}
uptime , err := strconv . ParseUint ( strings . TrimSpace ( string ( cmdOut ) ) , 10 , 64 )
return uptime , err
}
2015-06-21 07:36:07 -04:00
func Mac ( vmName string ) ( string , error ) {
var script = `
2015-06-22 17:26:06 -04:00
param ( [ string ] $ vmName , [ int ] $ adapterIndex )
2015-06-21 07:36:07 -04:00
try {
$ adapter = Get - VMNetworkAdapter - VMName $ vmName - ErrorAction SilentlyContinue
2015-06-22 17:26:06 -04:00
$ mac = $ adapter [ $ adapterIndex ] . MacAddress
2015-06-21 07:36:07 -04:00
if ( $ mac - eq $ null ) {
2015-06-22 17:26:06 -04:00
return ""
2015-06-21 07:36:07 -04:00
}
} catch {
2015-06-22 17:26:06 -04:00
return ""
2015-06-21 07:36:07 -04:00
}
$ mac
`
var ps powershell . PowerShellCmd
cmdOut , err := ps . Output ( script , vmName , "0" )
return cmdOut , err
}
func IpAddress ( mac string ) ( string , error ) {
var script = `
param ( [ string ] $ mac , [ int ] $ addressIndex )
try {
$ ip = Get - Vm | % { $ _ . NetworkAdapters } | ? { $ _ . MacAddress - eq $ mac } | % { $ _ . IpAddresses [ $ addressIndex ] }
if ( $ ip - eq $ null ) {
2015-06-22 17:26:06 -04:00
return ""
2015-06-21 07:36:07 -04:00
}
} catch {
2015-06-22 17:26:06 -04:00
return ""
2015-06-21 07:36:07 -04:00
}
$ ip
`
var ps powershell . PowerShellCmd
cmdOut , err := ps . Output ( script , mac , "0" )
return cmdOut , err
}
2015-06-27 17:36:39 -04:00
func TurnOff ( vmName string ) error {
2015-06-21 07:36:07 -04:00
var script = `
param ( [ string ] $ vmName )
$ vm = Get - VM - Name $ vmName - ErrorAction SilentlyContinue
2015-06-27 17:36:39 -04:00
if ( $ vm . State - eq [ Microsoft . HyperV . PowerShell . VMState ] : : Running ) {
2015-10-26 20:12:41 -04:00
Stop - VM - Name $ vmName - TurnOff - Force - Confirm : $ false
2015-06-21 07:36:07 -04:00
}
`
var ps powershell . PowerShellCmd
err := ps . Run ( script , vmName )
return err
}
2015-06-27 17:36:39 -04:00
func ShutDown ( vmName string ) error {
2015-06-21 07:36:07 -04:00
var script = `
param ( [ string ] $ vmName )
$ vm = Get - VM - Name $ vmName - ErrorAction SilentlyContinue
if ( $ vm . State - eq [ Microsoft . HyperV . PowerShell . VMState ] : : Running ) {
2015-10-26 20:12:41 -04:00
Stop - VM - Name $ vmName - Force - Confirm : $ false
2015-06-21 07:36:07 -04:00
}
`
var ps powershell . PowerShellCmd
err := ps . Run ( script , vmName )
return err
}
2015-06-27 17:36:39 -04:00
func TypeScanCodes ( vmName string , scanCodes string ) error {
2015-12-01 02:26:15 -05:00
if len ( scanCodes ) == 0 {
return nil
}
2015-06-21 07:36:07 -04:00
var script = `
2015-06-27 17:36:39 -04:00
param ( [ string ] $ vmName , [ string ] $ scanCodes )
# Requires - Version 3
# Requires - RunAsAdministrator
function Get - VMConsole
{
[ CmdletBinding ( ) ]
param (
[ Parameter ( Mandatory ) ]
[ string ] $ VMName
)
$ ErrorActionPreference = "Stop"
2015-12-01 02:26:15 -05:00
$ vm = Get - CimInstance - Namespace "root\virtualization\v2" - ClassName Msvm_ComputerSystem - ErrorAction Ignore - Verbose : $ false | where ElementName - eq $ VMName | select - first 1
2015-06-27 17:36:39 -04:00
if ( $ vm - eq $ null ) {
Write - Error ( "VirtualMachine({0}) is not found!" - f $ VMName )
}
2015-12-05 05:31:28 -05:00
2015-06-27 17:36:39 -04:00
$ vmKeyboard = $ vm | Get - CimAssociatedInstance - ResultClassName "Msvm_Keyboard" - ErrorAction Ignore - Verbose : $ false
2015-12-05 05:31:28 -05:00
if ( $ vmKeyboard - eq $ null ) {
$ vmKeyboard = Get - CimInstance - Namespace "root\virtualization\v2" - ClassName Msvm_Keyboard - ErrorAction Ignore - Verbose : $ false | where SystemName - eq $ vm . Name | select - first 1
}
if ( $ vmKeyboard - eq $ null ) {
$ vmKeyboard = Get - CimInstance - Namespace "root\virtualization" - ClassName Msvm_Keyboard - ErrorAction Ignore - Verbose : $ false | where SystemName - eq $ vm . Name | select - first 1
}
2015-06-27 17:36:39 -04:00
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 ) {
2015-11-04 16:45:37 -05:00
$ timeToWait = "1"
2015-06-27 17:36:39 -04:00
}
2015-11-07 18:33:47 -05:00
2015-06-27 17:36:39 -04:00
if ( $ scanCodesToSend ) {
$ scanCodesToSendByteArray = [ byte [ ] ] @ ( $ scanCodesToSend . Split ( ' ' ) | % { "0x$_" } )
$ scanCodesToSendByteArray | % {
$ vmConsole . TypeScancodes ( $ _ )
}
}
2015-11-07 18:33:47 -05:00
write - host "Special code <wait> found, will sleep $timeToWait second(s) at this point."
Start - Sleep - s $ timeToWait
2015-06-27 17:36:39 -04:00
$ scanCodesToSend = ' '
} else {
if ( $ scanCodesToSend ) {
2015-11-07 12:07:40 -05:00
write - host "Sending special code '$scanCodesToSend' '$scanCode'"
2015-06-27 17:36:39 -04:00
$ scanCodesToSend = "$scanCodesToSend $scanCode"
} else {
2015-11-07 12:07:40 -05:00
write - host "Sending char '$scanCode'"
2015-06-27 17:36:39 -04:00
$ scanCodesToSend = "$scanCode"
}
}
}
if ( $ scanCodesToSend ) {
$ scanCodesToSendByteArray = [ byte [ ] ] @ ( $ scanCodesToSend . Split ( ' ' ) | % { "0x$_" } )
$ scanCodesToSendByteArray | % {
$ vmConsole . TypeScancodes ( $ _ )
}
}
2015-06-21 07:36:07 -04:00
`
var ps powershell . PowerShellCmd
2015-06-27 17:36:39 -04:00
err := ps . Run ( script , vmName , scanCodes )
2015-06-21 07:36:07 -04:00
return err
}