TDRoy
Enthusiast
Enthusiast

Multiple Virtual Network Adapters on VM - How to Map to Corresponding Windows Network Adapters?

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

34 Replies
LucD
Leadership
Leadership

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

TDRoy
Enthusiast
Enthusiast

Thanks Luc, Ill check this out and report back

Much appreciated

0 Kudos
TDRoy
Enthusiast
Enthusiast

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

0 Kudos
LucD
Leadership
Leadership

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

TDRoy
Enthusiast
Enthusiast

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

0 Kudos
LucD
Leadership
Leadership

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

TDRoy
Enthusiast
Enthusiast

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?

0 Kudos
LucD
Leadership
Leadership

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

TDRoy
Enthusiast
Enthusiast

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

0 Kudos
TDRoy
Enthusiast
Enthusiast

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.

0 Kudos
LucD
Leadership
Leadership

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

TDRoy
Enthusiast
Enthusiast

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?

0 Kudos
LucD
Leadership
Leadership

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

0 Kudos
TDRoy
Enthusiast
Enthusiast

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

0 Kudos
LucD
Leadership
Leadership

That should definitely work on PS v4.

Show us the error messages you are getting.


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

0 Kudos
TDRoy
Enthusiast
Enthusiast

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.

0 Kudos
LucD
Leadership
Leadership

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

0 Kudos
TDRoy
Enthusiast
Enthusiast

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

0 Kudos
TDRoy
Enthusiast
Enthusiast

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.

0 Kudos