If you've read my post on adding disks to a Virtual machine, the techniques here should already feel familiar. We create a NIC , and we create a switch port. And then we tell the NIC it is connected to the switch port. Hyper-V creates VM switches which are either bound to a NIC, internal (visible to the Parent partition) or private (visible only to the child VMs). So one of the first things to do when setting up a NIC is to choose the switch, and the first function I'm going to create is Choose-VMSwitch using the choose-list function I've already shown: getting the Switches to pass to choose-List is easy enough, just query WMI for MSVM_VirtualSwitch Objects.
Function Choose-VMSwitch {choose-list (Get-WmiObject -NameSpace "root\virtualization" -Class "MsVM_VirtualSwitch") ` @(@{Label="Switch Name"; Expression={$_.ElementName}} ) }
So now I can have a command Add-VMNic $VM (Choose-VmSwitch) . Since Hyper-V supports Legacy and VMBus NICs, I have given the option for a -Legacy switch, and to support giving the NIC a fixed MAC address I've added a -MAC switch too. The PowerShell Filter is much the same as I've shown previously
So here's the code in full.
Filter Add-VMNIC {Param ($VM , $Virtualswitch, $mac, [switch]$legacy ) if ($VM -eq $null) {$VM=$_} if ($VM -is [Array]) {if ($legacy) {$VM | ForEach-Object {add-VmNic -VM $_ -Virtualswitch $Virtualswitch -legacy} } else {$VM | ForEach-Object {add-VmNic -VM $_ -Virtualswitch $Virtualswitch} } } if ($VM -is [String]) {$VM=(Get-VM -Machinename $VM ) } if ($VM -is [System.Management.ManagementObject]) { if ($Legacy) {$NicRASD = Get-VMRASD -resType 10 -resSubType 'Microsoft Emulated Ethernet Port' $NicRASD.ElementName= "Legacy Network Adapter"} else {$NicRASD = Get-VMRASD -resType 10 -resSubType 'Microsoft Synthetic Ethernet Port' $NicRASD.VirtualSystemIdentifiers=@("{"+[System.GUID]::NewGUID().ToString()+"}") $NicRASD.ElementName= "VMBus Network Adapter"} if ($virtualSwitch -ne $null) {$Newport = new-VmSwitchport $virtualSwitch if ($Newport -eq $null) {$Newport= ""} $NicRASD.Connection= $newPort} if ($mac -ne $null) {$nicRasD.address = $mac $nicRasD.StaticMacAddress = $true } $arguments = @($VM.__Path, @( $nicRASD.psbase.GetText([System.Management.TextFormat]::WmiDtd20) ), $null, $null ) $result = $VSMgtSvc.psbase.invokeMethod("AddVirtualSystemResources", $arguments) if ($result -eq 0) {"Added NIC to '$($VM.elementname)'."} else {"Failed to add NIC to '$($VM.elementname)', return code: $Result" }} $vm = $null }
In this function I call "New-VmSwitchPort", which is a wrapper for a method provided by the Virtual Switch Management Service. Like the the image management service, and the Virtual System Management Service, this is just a WMI Object which we query for. The process goes
Function New-VMSwitchPort {Param ($virtualSwitch , $Server=".") if ($Virtualswitch -is [String]) {$Virtualswitch=(Get-WmiObject -computerName $server -NameSpace "root\virtualization" -Query "Select * From MsVM_VirtualSwitch Where elementname = '$Virtualswitch' ")} if ($Virtualswitch -is [System.Management.ManagementObject]) { $SwitchMgtSvc=(Get-WmiObject -computerName $Virtualswitch.__server -NameSpace "root\virtualization" -Query "Select * From MsVM_VirtualSwitchManagementService") [String]$GUID=[System.GUID]::NewGUID().ToString() $arguments=@($Virtualswitch.__Path, $GUID, $GUID, $null, $null) $result = $SwitchMgtSvc.psbase.invokeMethod("CreateSwitchPort",$arguments) if ($result -eq 0) {"Created VirtualSwitchPort on '$($virtualSwitch.elementName)' " | out-host @($arguments[4]) } else {"Failed to create VirtualSwitchPort on '$($virtualSwitch.elementName)': return code: $Result" | out-host} } }
There are some extra functions that I won't show here - I've got a "Remove-Port" function and a Set-VMNICPort function - which removes an existing port and adds a newly created one. I've got a Set-VMNICMacAddress function which changes the MAC address after the NIC is created, and Get-VMNIC and Get-VMNICSwitch which build up to give a Get-VMNICList function along the same lines as the Get-VMDiskList I showed before
Bonus link Over on the Virtualization Team blog, Taylor has posted the code to connect the Host machines Network card to a VM switch. I'm going to rework that code slightly for the library I'm building - I'll have a "Choose-ExternalEthernetPort" and so on.