Hi All,
(ESXi 6.0. standlone)
I have a Windows Server 2012 VM that Im trying to setup via script.
This VM has 4 Network Adapters: VM Network, Something0, Something1, Application.
The OVA is deployed and then the VM is sysprepped before initial login.
Once logged in, I look at the network adapters in Windows and see 4 adapters, each with a name "Ethernet #". The placement of the Virtual NIC -> Windows NIC seems to be different each time, presumably because of sysprep.
Via script, Im can rename and enable the VMware Virtual Adapters to their specific portgroup and StartConnected,
but Im not sure how to map the corresponding VMware Adapters that I rename with the default "Ethernet #" Windows adapters
Any help would be greatly appreciated
Thank you
Afaik Windows assigns names to the Adapters in the order it sees the NICs on the PCI bus.
So if you look at the PciSlot numbers for the vNICs, it should be a matter of placing the numbers in ascending order, to be able to link the vNIC to the Windows OS adapter.
You can retrieve the PCI slot numbers of the vNICs like this
Get-VM | Get-NetworkAdapter |
Select @{N='VM';E={$_.Parent.Name}},
Name,
@{N='PciSlot';E={$_.ExtensionData.SlotINfo.PciSlotNumber}}
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Thanks Luc, Ill check this out and report back
Much appreciated
This is what I see when I run the above command:
Its showing me the virtual network adapters on the VM but nothing about the PCISlot.
All NICs are connected.
PowerCLI C:\Program Files (x86)\VMware\Infrastructure\vSphere PowerCLI> Get-VM | Get-NetworkAdapter |
>> Select @{N='VM';E={$_.Parent.Name}},
>> Name,
>> @{N='PciSlot';E={$_.ExtensionData.SlotINfo.PciSlotNumber}}
>>
VM Name
-- ----
VM Network adapter 1
VM Network adapter 2
VM Network adapter 3
VM Network adapter 4
VM3 Network adapter 1
VM3 Network adapter 2
VM3 Network adapter 3
Thank you, Luc
Just tried it again, for me it works.
Try storing the output in a CSV file, just to avoid that this might be a output formatting to screen thing.
Get-VM | Get-NetworkAdapter |
Select @{N='VM';E={$_.Parent.Name}},
Name,
@{N='PciSlot';E={$_.ExtensionData.SlotINfo.PciSlotNumber}} |
Export-Csv C:\Temp\report.csv -NoTypeInformation -UseCulture
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Awesome, that outputs it correctly. Thank you for that. And I was able to sort by PciSlot.
BUT, still what Im seeing is that the slot numbers align with the Network Adapter 1,2,3.
So for example I have this
VM NetworkAdapter1 123
VM NetworkAdapter2 125
VM NetworkAdapter3 244
The NetworkAdapter to Slot number matches.
When I look in Windows hoever at the NIC numbering:
NetworkAdapter1 Ethernet1
NetworkAdapter2 Ethernet3
NetworkAdapter3 Ethernet2
How can I match the networkadapter number to the correct ethernet NIC in Windows
When you run the following inside the Windows guest OS, do the PCI slot numbers correspond?
Get-NetAdapterHardwareInfo | select name,slot
If that mapping works, we could use Invoke-VMScript to retrieve that info from the guest OS
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Yes, this shows the correct network naming to Slot ID mapping.
Im wondering if Im looking at it the wrong way:
When Windows is sysprepped, the default NIC names are Ethernet,Ethernet2, Ethernet3 etc.
I was looking to order the NICs correct via that default name, and then assign and rename them accordingly.
Maybe this doesnt matter as long as I can map the Name to Slot to Virtual Network Adapter?
Im still seeing that Ethernet is mapped to the lowest slot ID.
Then Ethernet 3 is mapped to the next lowest.
And Ethernet 2 to the highest.
Shouldnt Ethernet2 be mapped to the middle slot and 3 to the highest slot number?
It looks like Windows has it's own algorithm to pick network cards and label them.
I was of the assumption that was based on the PCI slots, but obviously that is not the case (anymore ?).
But if we can indeed map the two through the PCI slots numbers, we can map the VM's vNIC to the adapters inside the Windows guest OS.
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Yes! I was able to cobble something together with this great help:
$get_info = GetNetAdapterHardwareInfo | Select Name,Slot | Sort-Oject Slot
$get_info[0] | Rename-NetAdapter -Name $get_info[0].Name -NewName "Name1"
$get_info returns 3 object:
Net1 100
Net2 170
Net3 200
I then call each array object item (info[0].Name) and Rename it.
Im hoping this will always correspond to the VM Network Adapter as they are set in a template as always being Net1 as the first, Net2 as the second etc.
Will have to test some more but I believe this gives me the results I want
Thank you Luc for brainstorming with me
Ok, its not infact the case on all Windows VMs.
I ran a couple of tests on other Windows Server 2012 VMs and while the slot numbers are matching up on the command, when I set the name for a given NIC, it doesnt correspond correctly.
How could I go about linking what the VMs show and what Windows shows?
Here is what Im seeing currently:
In the Windows VM - Get-NetAdapHardInfo
Name Slot VM Network Association
Ethernet 4 100 Net Adap 4
Ethernet 2 101 Net Adap 1
Ethernet 3 102 Net Adap 2
Ethernet 103 Net Adap 3
On the VM > Edit Settings I would assume that the lowest PCI slot would be Network Adapter 1, the next Network Adapter 2 etc etc
Its not the case.
How can we map this correctly? Its driving me crazy after looking at this all day.
Indeed, you can assume that the vNIC label order corresponds with the PCI slot numbers order.
This can/could be caused by additions/removals of vNICs.
For example a vNIC that is never "connected" will not be "known" by the guest OS.
I now use the following to create the mapping between vNICs and adapters in the (Windows) guest OS.
$code = @'
Get-NetAdapterHardwareInfo |
select name,slot,@{N='mac';E={Get-NetAdapter -Name $_.Name | select -ExpandProperty MacAddress}} |
ConvertTo-Csv -UseCulture -NoTypeInformation
'@
Get-VM |
where{$_.PowerState -eq 'PoweredOn' -and $_.ExtensionData.COnfig.GuestFullName -match 'Windows'} | %{
$osPCI = Invoke-VMScript -VM $_ -ScriptText $code -ScriptType Powershell |
Select -ExpandProperty ScriptOutput | ConvertFrom-Csv
foreach($vnic in Get-NetworkAdapter -VM $_){
$osNic = $osPCI | where{$_.slot -eq $vnic.ExtensionData.SlotINfo.PciSlotNumber}
New-Object PSObject -Property ([ordered]@{
VM = $_.Name
Portgroup = $vnic.NetworkName
vMAC = $vnic.MacAddress
osMAC = $osNic.mac
vNIC = $vnic.Name
osNIC = $osNic.name
vSlot = $vnic.ExtensionData.SlotINfo.PciSlotNumber
osSlot = $osNic.Slot
})
}
}
I also made a short script that will change the guest OS adapter name to correspond with the PortGroup the vNIC is connected to.
That code could easily be changed to change the adapter name to whatever you desire.
Something like this.
$code = @'
Get-NetAdapterHardwareInfo |
select name,slot,@{N='mac';E={Get-NetAdapter -Name $_.Name | select -ExpandProperty MacAddress}} |
ConvertTo-Csv -UseCulture -NoTypeInformation
'@
$changeAdapterName = @'
Rename-NetAdapter -Name '#oldname#' -NewName '#newname#' -Confirm:$false
'@
Get-VM |
where{$_.PowerState -eq 'PoweredOn' -and $_.ExtensionData.COnfig.GuestFullName -match 'Windows'} | %{
$osPCI = Invoke-VMScript -VM $_ -ScriptText $code -ScriptType Powershell |
Select -ExpandProperty ScriptOutput | ConvertFrom-Csv
foreach($vnic in Get-NetworkAdapter -VM $_){
$osNic = $osPCI | where{$_.slot -eq $vnic.ExtensionData.SlotINfo.PciSlotNumber}
if($osNic){
if($osNic.Name -ne $vnic.NetworkName){
$codeAdapter = $changeAdapterName.Replace('#oldname#',$osNic.Name).Replace('#newname#',$vnic.NetworkName)
Invoke-VMScript -VM $_ -ScriptText $codeAdapter -ScriptType Powershell
}
}
}
}
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Luc, thanks a lot for this.
Im going to try to implement this in my existing script.
For multiple adapters on the same VM, would I create multiple 'Rename-NetAdapter' lines in the $changeadaptername variable?
Also, what is the [ordered] property? Im hitting errors on this. Do I need to load a certain module for this?
No, I would loop through all the vNICs, like I did in the second script.
The Invoke-VMScript is changed for each invocation.
The [ordered] is a construct that allows to create ordered hash tables.
That was introduced in PowerShell v3.
Check your PowerShell version, what is in $PSVersionTable?
And which errors exactly are you getting for [ordered]?
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Im testing this on a dev server right now, using PS v4. Ill give it a go on the actual server in a little while.
I ask about the RenameAdapter function, because its specifically asking for OldName / NewName. How do I specificy each NICs old and new names?
Thank you
That should definitely work on PS v4.
Show us the error messages you are getting.
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Woops, test server is not v4. My bad. Will test it in a while on v4 at home.
Also, see the edit from my previous comment.
I used placeholders for the parameter values (#oldname# and #newname#).
Inside the foreach loop I use the Replace method to change these placeholders with the actual values.
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Ah crap, ok. I must have glossed over that. Let me stop spamming this thread and instead just give it a shot when I get back in
Thanks again
Ok, so Im running both of the scripts and they work amazingly well.
Im noticing that one of my network adapters is not getting set at all. Network Adapter 4.
When I look at the first script, all other network adapters are mapping an osMAC,osNIC and a corresponding vSlot and osSlot. The last adapter shows the name, vNIC, MAC, and vSlot but not the others.
Any ideas as to why this may occur? Its deployed with our template just as the other adapters. Its connected via script just like the other adapters.
Thank you again Luc for all of the assistance.