Now that Windows 8 and Windows Server 2012 are readily available , we all want to do some exploring. But if you want to automate the creation of some test VMs for this, you are in for a surprise.
The current PowerCLI 5.1 Release 1 doesn’t accept the E1000E NIC as a Type on the New-NetworkAdapter cmdlet. Users start hitting this limitation, as can be seen on this PowerCLI Community thread. You can go for the E1000, but why settle for less if you can easily script the use of the E1000E NIC from PowerCLI?
So even though Eric “the Scoop Meister” Sloof debunked the myth that the E1000/E1000E is faster than the VmxNet3, the E1000E is the default NIC type that vSphere gives you when you create a VM for a Windows Server 2012 or Windows 8 VM. Note that the E1000 apparently uses slightly more CPU resources than the E1000E. With the function in this post you can now automate this behavior.
Update November 17th 2012: In KB2006859 it seems to say that the VMXNET3 NIC doesn’t work with Windows Server 2012 or Windows 8. And there have been several blogs (including mine) that picked up this info. But after you apply the September 2012 patch to your ESXi servers, you can also use a VMXNET3 NIC for both Windows OS. See here and here for more info.
Thanks to reader alcapapower for drawing my attention to this (see his remark in the comments below).
The Script
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 |
function New-E1000ENic { <# .SYNOPSIS Add an E1000E NIC to one or more VMs .DESCRIPTION The function will add an E1000E NIC card to each VM that is passed. .NOTES Author: Luc Dekens .PARAMETER VM One or more virtual machines. This parameter accepts pipeline input. .PARAMETER StartConnected Wether or not the device is connected when the VM starts .PARAMETER MacAddress MAC address from the allowed range .PARAMETER WakeOnLan Wether or not WOL is enabled on the NIC .PARAMETER NetworkName Name of the network. This can be a portgroup name from a VirtualSwitch or from a DistributedSwitch .PARAMETER DistributedSwitch Can only be used in combination with the PortKey. .PARAMETER PortKey The port on the DistributedSwitch where the NIC shall connect to. .EXAMPLE PS> New-E1000ENic -VM MyVM -NetworkName pg1 .EXAMPLE PS> Get-VM VM | New-E1000ENic -NetworkName pg1 .EXAMPLE PS> New-E1000ENic -VM MyVM -DistributedSwitch sw1 -PortKey 100 #> param( [CmdletBinding(DefaultParametersetName='VirtualSwitch')] [Parameter(Mandatory=$true,ValueFromPipeline=$true)] [PSObject[]]$VM, [Switch]$StartConnected = $false, [String]$MacAddress, [Switch]$WakeOnLan = $false, [Parameter(ParameterSetName='NetworkName')] [String]$NetworkName, [Parameter(ParameterSetName='DistributedSwitch'Mandatory=$true,)] [PSObject]$DistributedSwitch, [Parameter(ParameterSetName='DistributedSwitch'Mandatory=$true,)] [PSObject]$PortKey ) begin{ $spec = New-Object VMware.Vim.VirtualMachineConfigSpec $dev = New-Object VMware.Vim.VirtualDeviceConfigSpec $dev.Operation = "add" $dev.Device = New-Object VMware.Vim.VirtualE1000e $dev.Device.Connectable = New-Object VMware.Vim.VirtualDeviceConnectInfo $dev.Device.Connectable.StartConnected = $StartConnected $dev.Device.WakeOnLanEnabled = $WakeOnLan switch ($PsCmdlet.ParameterSetName){ "NetworkName" { $pg = Get-VirtualPortGroup -Name $networkName if($pg.ExtensionData -is [VMware.Vim.DistributedVirtualPortgroup]){ $dvPort = New-Object VMware.Vim.VirtualEthernetCardDistributedVirtualPortBackingInfo $dvPort.port = New-Object VMware.Vim.DistributedVirtualSwitchPortConnection $dvPort.port.switchUuid = $pg.VirtualSwitch.ExtensionData.Uuid $dvPort.port.portgroupKey = $pg.Extensiondata.Key $dev.Device.Backing = $dvPort } else{ $dev.Device.Backing = New-Object VMware.Vim.VirtualEthernetCardNetworkBackingInfo $dev.Device.Backing.DeviceName = $NetworkName } } "DistributedSwitch" { if($DistributedSwitch.GetType().Name -eq "string"){ $DistributedSwitch = Get-VirtualSwitch -Distributed -Name $DistributedSwitch } $pg = Get-VirtualPortGroup -Distributed -VirtualSwitch $DistributedSwitch | where {$_.ExtensionData.Portkeys -contains $PortKey} if(!$pg){ Write-Warning "Portkey $PortKey not found on $DistributedSwitch.Name" exit } $dvPort = New-Object VMware.Vim.VirtualEthernetCardDistributedVirtualPortBackingInfo $dvPort.port = New-Object VMware.Vim.DistributedVirtualSwitchPortConnection $dvPort.port.switchUuid = $dvSw.ExtensionData.Uuid $dvPort.port.portgroupKey = $pg.Extensiondata.Key $dvPort.port.portKey = $PortKey $dev.Device.Backing = $dvPort } } if($MacAddress){ $dev.Device.MacAddress = $MacAddress } $spec.deviceChange += $dev } process{ foreach($client in $VM){ if($client.GetType().Name -eq "string"){ $client = Get-VM -Name $client } if($client.Version -eq "v8"){ $client.ExtensionData.ReconfigVM($spec) if($PortKey){ $spec.DeviceChange[0].Device.Backing.port.PortKey = [int]$spec.DeviceChange[0].Device.Backing.port.PortKey + 1 } } else{ Write-Warning "$client.Name is not HW version 8" } } } } |
Annotation
Line 39-44: The function supports two parametersets, NetworkName and DistributedSwitch. The parameters NetworkName and DistributedSwitch/PortKey belong to different parametersets and can not be used together.
Line 47-91: The VirtualMachineConfigSpec parameter for the ReconfigVM_Task method is the same for each call, except for the PortKey property (if it is used). For this reason the object is created and configured in the Begin section of the function.
Line 55: Depending on the parameterset used, different properties need to be set.
Line 58: If the NetworkName is for a portgroup on a DistributedSwitch other pproperties need to be set.
Line 71-73, 95-97: A simple implementation of Object By Name
Line 76-79: If the function gets a PortKey that can not be mapped to a PortGroup, the function will exit.
Line 99: The use of an E1000E NIC requires that the VM is at least on hardware version 8.
Line 101-104: If the function is used to add an E1000E NIC on multiple VMs, and if the PortKey parameter is used, the function will automatically take the next portnumber. Make sure that there are enough free ports available to accommodate all the VMs you pass to the function.
Sample run
The function can be used in several ways.
You can call it by passing a NetworkName parameter.
1 2 |
$vm = Get-VM -Name W2K12 New-E1000ENic -VM $vm -NetworkName Net1 -StartConnected |
1 |
And you can also use the function in a pipeline construct.
1 2 |
Get-VM -Name W2K12* | New-E1000ENic -NetworkName Net1 -StartConnected |
The NetworkName parameter can also point to a portgroup on a DistributedSwitch
1 2 3 |
$vm = Get-VM -Name W2K12 New-E1000ENic -VM $vm -NetworkName dvPg1 -WakeOnLan -StartConnected |
1 |
You can specify a specific port with the PortKey parameter. Note that this parameter always needs to be used together with the DistributedSwitch parameter.
1 2 3 4 |
$vm = Get-VM -Name W2K12 $dvSw = Get-VirtualSwitch -Distributed -Name dvSw1 New-E1000ENic -VM $vm -DistributedSwitch $dvSw -PortKey 101 -StartConnected |
The function increments the PortKey by 1 if you call the function for more than 1 VM. Make sure there are enough free ports, starting from the port you pass in PortKey, to accommodate all the VM for which you call the function.
My dvSwitch scripting – Part 12 – Find free ports post might come in handy here
Enjoy !
Derek Seaman
I wrote a blog post about how to integrate VMXNET3 and PVSCSI drivers directly into the WS2012 and Windows 8 ISOs:
https://derek858.blogspot.com/2012/10/inject-vsphere-drivers-into-windows.html
Works like a charm on our ESXi 821926 servers.
LucD
Thanks for sharing Derek, great post and very useful info.
junkydoll
Hi Luc, great site.
Not wanting to be picky, but your function name seems to be missing a zero …
Cheers
LucD
@Junkydoll, thanks for spotting that.
The name has been updated.
alpacapowered
Great script, but I have to disagree about the statement that the vmxnet3 vNIC doesn’t work with Windows Server 2012/Windows 8 even though that KB article suggests otherwise.
I have a couple of Windows Server 2012 VMs with vmxnet3 which are running fine on ESXi 5.0 U1 and latest patches.
Using vmxnet3 is also explicitly supported on 5.1 and 5.0 according to the official HCL:
https://www.vmware.com/resources/compatibility/detail.php?deviceCategory=software&testConfig=16&productid=19174&releaseid=171&supRel=171,168
https://www.vmware.com/resources/compatibility/detail.php?deviceCategory=software&testConfig=16&productid=13500&releaseid=168&supRel=171,168
Btw the line number annotations seem a bit off – I can only see 88 lines of code in your script.
LucD
@alpacapowered, thanks for the feedback.
The inline function help lines were missing, that should be corrected now.
I just did another test;
I patched my server to the latest build, ESXi 5.0.0 build 821926.
I created a VM with a vmxnet3 card and installed Windows Server 2012 on there.
This time the VM with Windows Server 2012 comes up without a problem.
So it looks as if there is a fix in one of the September patches for the problem that existed with VMXNET3 and Windows Server 2012. Unfortunately the patch documentation doesn’t seem to list any specifics for these new Windows OS.
In any case, I’ll update my post with this new information.
Then