sureshadmin2011
Enthusiast
Enthusiast

Need VM portgroup inventory

Jump to solution

Hi,

I'm looking for VM portgroup inventory script that will list out the following,

VMname  VMX location |  NIC name  |  NIC type  | NIC MAC  |  Portgroup Name  |  Switch type  |  Switch name

Where,

NIC name ..... Name of the nic like "Network adapter 1"

NIC type........ Type like vmxnet3

Switch type.... Type of the switch either a dvSwitch or StandardSwitch

Please note this will be run in a vCenter 4 where a mix of ESX 3.5 and ESX(i) 4.1u1 are hosted.

Thanks in advance!

1 Solution

Accepted Solutions
mattboren
Expert
Expert

Alright-

Below is the updated code that considers dvSwitches as well as the standard vSwitches on which the previous code reported.  It's a bit of work to make the connection between the NIC on the VM and the actual dvSwitch and dvPortGroup, but, the comments in the code should explain it:

#requires -PsSnapin VMware.VimAutomation.Core -Version 5
#
# get the View objects for the dvSwitches in the environment, to be used for dvSwitch/dvPortgroup identification later
$arrDVSwitchViews = @(Get-View -ViewType DistributedVirtualSwitch -Property Name,Uuid)
## get the Key and Name values for the LinkedView items
$arrDVSwitchViews | %{$_.UpdateViewData("Portgroup.Key","Portgroup.Name")}

&{
Get-View -ViewType VirtualMachine -Property Name,Config.Files.VmPathName,Config.Hardware.Device | %{
   
$viewThisVM = $_
   
## updated a bit of View data (to be used in the LinkedView properties later -- this is faster than using multiple Get-View calls for properties that are MoRefs themselves)
    $viewThisVM.UpdateViewData("Runtime.Host.ConfigManager.NetworkSystem.NetworkInfo.Vswitch","Runtime.Host.ConfigManager.NetworkSystem.NetworkInfo.ProxySwitch","Runtime.Host.ConfigManager.NetworkSystem.NetworkInfo.PortGroup")
   
## for each VirtualEthernetCard on this VM, get some info
    $viewThisVM.Config.Hardware.Device | ?{$_ -is [VMware.Vim.VirtualEthernetCard]} | %{
       
## this VirtualEthernetCard
        $oEthCard = $_
       
## init some variables, so that there is no "value leaking" if there is an instance where a variable does not get set
        $strPortgroupName = $strVSwitchType = $strVSwitchName = $null
       
Switch ($oEthCard.Backing.GetType().Name) {
           
## if this NIC is on a standard vSwitch
            "VirtualEthernetCardNetworkBackingInfo" {
               
## the portgroup name for this VirtualEthernetCard
                $strPortgroupName = $oEthCard.Backing.DeviceName
               
## the portgroup for this VirtualEthernetCard
                $oPortGroup = $viewThisVM.Runtime.LinkedView.Host.ConfigManager.LinkedView.NetworkSystem.NetworkInfo.Portgroup | ?{$_.Spec.Name -eq $oEthCard.Backing.DeviceName}
               
## the name of the vSwitch for this portgroup
                $strVSwitchName = $oPortGroup.Spec.VswitchName
               
## the type of the vSwitch for this portgroup
                $oVSwitch = $viewThisVM.Runtime.LinkedView.Host.ConfigManager.LinkedView.NetworkSystem.NetworkInfo.Vswitch | ?{$_.Key -eq $oPortGroup.Vswitch}
               
$strVSwitchType = if ($oVSwitch) {$oVSwitch.GetType().Name} else {"vSwitch type not found"}
               
break;
            }
## end this case
            ## if this NIC is on a dvSwitch
            "VirtualEthernetCardDistributedVirtualPortBackingInfo" {
               
## find the View object of the dvSwitch for this NIC from the array of dvSwitches, by Uuid
                $oDVSwitch = $arrDVSwitchViews | ?{$_.Uuid -eq $oEthCard.Backing.Port.SwitchUuid}
               
$oDVPortgroup = $oDVSwitch.LinkedView.Portgroup | ?{$_.Key -eq $oEthCard.Backing.Port.PortgroupKey}
               
## the portgroup name for this VirtualEthernetCard
                $strPortgroupName = $oDVPortgroup.Name
               
## the name of the dvSwitch for this portgroup
                $strVSwitchName = $oDVSwitch.Name
               
## the type of the dvSwitch for this portgroup
                $strVSwitchType = if ($oDVSwitch) {$oDVSwitch.GetType().Name} else {"dvSwitch type not found"}
               
break;
            }
## end this case
        } ## end switch

       
## create an object with the info about this VirtualEthernetCard
        New-Object -TypeName PSobject -Property @{
            VMName
= $viewThisVM.Name
            VMXLocation
= $viewThisVM.Config.Files.VmPathName
            NICName
= $_.DeviceInfo.Label
            NICType
= $_.GetType().Name
            MACAddress
= $_.MacAddress
            PortgroupName
= $strPortgroupName
            vSwitchType
= $strVSwitchType
            vSwitchName
= $strVSwitchName
        }
## end new-object
    } ## end foreach-object
} ## end foreach-object
} | Select VMName, VMXLocation, NICName, NICType, MACAddress, PortgroupName, vSwitchType, vSwitchName

How does that do for you?

View solution in original post

18 Replies
RvdNieuwendijk
Leadership
Leadership

The following PowerCLI script will give you the desired VM network information. The script will only work for VM's that have one networkadapter. If you want the script to work for VM's with more than one networkadapters also, then let me know and I can expand the script.

Get-VM | ForEach-Object {
  if ($_) {
    $VM = $_
    $Report = "" | Select-Object -Property "VM Name","VMX Location","NIC Name","NIC Type","NIC MAC","Portgroup Name","Switch Type","Switch Name"
    $Report."VM name" = $VM.Name
    $Report."VMX Location" = $VM.ExtensionData.Config.Files.VmPathName
    $NetworkAdapter = $VM | Get-NetworkAdapter
    $Report."NIC Name" = $NetworkAdapter.Name
    $Report."NIC Type" = $NetworkAdapter.Type
    $Report."NIC MAC"  = $NetworkAdapter.MacAddress
    $Report."Portgroup Name" = $NetworkAdapter.Networkname
    $VirtualSwitch = $VM | Get-VirtualSwitch
    $Report."Switch Type" = $VirtualSwitch.GetType().Name
    $Report."Switch Name" = $VirtualSwitch.Name
    $Report
  }
}

Regards, Robert

Blog: https://rvdnieuwendijk.com/ | Twitter: @rvdnieuwendijk | Author of: https://www.packtpub.com/virtualization-and-cloud/learning-powercli-second-edition
0 Kudos
sureshadmin2011
Enthusiast
Enthusiast

Thanks Robert. Yes sure, i need it for multiple adapters in a VM.

Also is there a way to fetch info faster like doing it via a get-view?

0 Kudos
RvdNieuwendijk
Leadership
Leadership

I modified my first script to handle VM's with multiple NIC's and multiple switches. It is not trivial how I can make the script run faster. I will have to think about that question.

Get-VM | ForEach-Object {
  if ($_) {
    $VM = $_
    $Report = "" | Select-Object -Property "VM Name","VMX Location","NIC Name","NIC Type","NIC MAC","Portgroup Name","Switch Type","Switch Name"
    $Report."VM name" = $VM.Name
    $Report."VMX Location" = $VM.ExtensionData.Config.Files.VmPathName
    $NetworkAdapter = $VM | Get-NetworkAdapter
    if ($NetworkAdapter) {
      $Report."NIC Name" = ($NetworkAdapter | ForEach-Object {$_.Name}) -join ","
      $Report."NIC Type" = ($NetworkAdapter | ForEach-Object {$_.Type}) -join ","
      $Report."NIC MAC"  = ($NetworkAdapter | ForEach-Object {$_.MacAddress}) -join ","
      $Report."Portgroup Name" = ($NetworkAdapter | ForEach-Object {$_.NetworkName}) -join ","
    } 
    $VirtualSwitch = $VM | Get-VirtualSwitch
    if ($VirtualSwitch) {
      $Report."Switch Type" = ($VirtualSwitch | ForEach-Object {$_.GetType().Name}) -join ","
      $Report."Switch Name" = ($VirtualSwitch | ForEach-Object {$_.Name}) -join ","
    }
    $Report
  }
}

Matt Boren pointed me to a flaw in my script from this post. So I modified it according to his suggestions. Thanks Matt!

Message was edited by: RvdNieuwendijk

Blog: https://rvdnieuwendijk.com/ | Twitter: @rvdnieuwendijk | Author of: https://www.packtpub.com/virtualization-and-cloud/learning-powercli-second-edition
0 Kudos
mattboren
Expert
Expert

Hello, sureshadmin20…-

Like Robert said, making this script faster is no trivial task.  I gave it a shot using Get-View, and came up with the following, which should run a bit faster:

&{Get-View -ViewType VirtualMachine -Property Name,Config.Files.VmPathName,Config.Hardware.Device | %{
   
$viewThisVM = $_
   
## updated a bit of View data (to be used in the LinkedView properties later -- this is faster than using multiple Get-View calls for properties that are MoRefs themselves)
    $viewThisVM.UpdateViewData("Runtime.Host.ConfigManager.NetworkSystem.NetworkInfo.Vswitch","Runtime.Host.ConfigManager.NetworkSystem.NetworkInfo.PortGroup")
   
## for each VirtualEthernetCard on this VM, get some info
    $viewThisVM.Config.Hardware.Device | ?{$_ -is [VMware.Vim.VirtualEthernetCard]} | %{
       
## this VirtualEthernetCard
        $oEthCard = $_;
       
## the portgroup for this VirtualEthernetCard
        $oPortGroup = $viewThisVM.Runtime.LinkedView.Host.ConfigManager.LinkedView.NetworkSystem.NetworkInfo.Portgroup | ?{$_.Spec.Name -eq $oEthCard.Backing.DeviceName}
       
## the name of the vSwitch for this portgroup
        $strVSwitchName = $oPortGroup.Spec.VswitchName
       
## the type of the vSwitch for this portgroup
        $strVSwitchType = ($viewThisVM.Runtime.LinkedView.Host.ConfigManager.LinkedView.NetworkSystem.NetworkInfo.Vswitch | ?{$_.Key -eq $oPortGroup.Vswitch}).GetType().Name
       
## create an object with the info about this VirtualEthernetCard
        New-Object -TypeName PSobject -Property @{
            VMName
= $viewThisVM.Name
            VMXLocation
= $viewThisVM.Config.Files.VmPathName
            NICName
= $_.DeviceInfo.Label
            NICType
= $_.GetType().Name
            MACAddress
= $_.MacAddress
            PortgroupName
= $_.Backing.DeviceName
            vSwitchType
= $strVSwitchType
            vSwitchName
= $strVSwitchName
        }
## end new-object
    } ## end foreach-object
} ## end foreach-object
} | Select VMName, VMXLocation, NICName, NICType, MACAddress, PortgroupName, vSwitchType, vSwitchName

In my testing this gave about a 9x- to 10x speed increase -- quite considerable.  The cost, of course, is the additional time up-front to write it.

Also, I went the route of returning one info object per NIC, instead of one item per VM with comma-separated values in some properties.

How does that do for you?

0 Kudos
fredlock
Contributor
Contributor

Hi Matt,

When i run your script i get an error on each vm entry  (except for the VM´s that have portgroups from a standard switch)

You cannot call a method on a null-valued expression.

At line:14 char:167

+         $strVSwitchType = ($viewThisVM.Runtime.LinkedView.Host.ConfigManager.LinkedView.NetworkSystem.NetworkInfo.Vswitch | ?{$_.Key

-eq $oPortGroup.Vswitch}).GetType <<<< ().Name

    + CategoryInfo          : InvalidOperation: (GetType:String) [], RuntimeException

    + FullyQualifiedErrorId : InvokeMethodOnNull

VMName        : Win7-FC-Res-2

VMXLocation   : [iSCSI_T370001_02] Win7-FC-Res-2/Win7-FC-Res-2.vmx

NICName       : Network adapter 1

NICType       : VirtualE1000

MACAddress    : 00:50:56:96:3e:59

PortgroupName :

vSwitchType   : HostVirtualSwitch

vSwitchName   :

Any suggestions?

Fred

0 Kudos
sureshadmin2011
Enthusiast
Enthusiast

Sorry for late reply.

This script works perfect but when a VM has a network adapter with portgroup value as "blank" it breaks with null value. "blank" portgroup values are produced when a VM is added back to the inventory and we need to select the dvSwitch portgroup manually, till that time the value is blank.

Can you make this script to skip VM when it faces a null value?

0 Kudos
sureshadmin2011
Enthusiast
Enthusiast

Matt,

Thanks for the time spent on this script. The script produces a error mentioned below,

Exception calling "UpdateViewData" with "1" argument(s): ""

At :line:5 char:26

0 Kudos
mattboren
Expert
Expert

Hello, fredlock-

Alright, sounds like that is probably due to the way that dvSwitches are represented in the structure of the NetworkSystem object.  I will update the code to handle these, and post back here when done.

0 Kudos
mattboren
Expert
Expert

Hello, sureshadmin20…-

Hmm.  What version of PowerCLI are you using?  You can find out by running:

Get-PowerCLIVersion

The way that I used UpdateViewData() is new in PowerCLI 5.0, and I am wondering if you are using a bit older version.  Let us know.

0 Kudos
fredlock
Contributor
Contributor

Thanks Matt!

0 Kudos
mattboren
Expert
Expert

Alright-

Below is the updated code that considers dvSwitches as well as the standard vSwitches on which the previous code reported.  It's a bit of work to make the connection between the NIC on the VM and the actual dvSwitch and dvPortGroup, but, the comments in the code should explain it:

#requires -PsSnapin VMware.VimAutomation.Core -Version 5
#
# get the View objects for the dvSwitches in the environment, to be used for dvSwitch/dvPortgroup identification later
$arrDVSwitchViews = @(Get-View -ViewType DistributedVirtualSwitch -Property Name,Uuid)
## get the Key and Name values for the LinkedView items
$arrDVSwitchViews | %{$_.UpdateViewData("Portgroup.Key","Portgroup.Name")}

&{
Get-View -ViewType VirtualMachine -Property Name,Config.Files.VmPathName,Config.Hardware.Device | %{
   
$viewThisVM = $_
   
## updated a bit of View data (to be used in the LinkedView properties later -- this is faster than using multiple Get-View calls for properties that are MoRefs themselves)
    $viewThisVM.UpdateViewData("Runtime.Host.ConfigManager.NetworkSystem.NetworkInfo.Vswitch","Runtime.Host.ConfigManager.NetworkSystem.NetworkInfo.ProxySwitch","Runtime.Host.ConfigManager.NetworkSystem.NetworkInfo.PortGroup")
   
## for each VirtualEthernetCard on this VM, get some info
    $viewThisVM.Config.Hardware.Device | ?{$_ -is [VMware.Vim.VirtualEthernetCard]} | %{
       
## this VirtualEthernetCard
        $oEthCard = $_
       
## init some variables, so that there is no "value leaking" if there is an instance where a variable does not get set
        $strPortgroupName = $strVSwitchType = $strVSwitchName = $null
       
Switch ($oEthCard.Backing.GetType().Name) {
           
## if this NIC is on a standard vSwitch
            "VirtualEthernetCardNetworkBackingInfo" {
               
## the portgroup name for this VirtualEthernetCard
                $strPortgroupName = $oEthCard.Backing.DeviceName
               
## the portgroup for this VirtualEthernetCard
                $oPortGroup = $viewThisVM.Runtime.LinkedView.Host.ConfigManager.LinkedView.NetworkSystem.NetworkInfo.Portgroup | ?{$_.Spec.Name -eq $oEthCard.Backing.DeviceName}
               
## the name of the vSwitch for this portgroup
                $strVSwitchName = $oPortGroup.Spec.VswitchName
               
## the type of the vSwitch for this portgroup
                $oVSwitch = $viewThisVM.Runtime.LinkedView.Host.ConfigManager.LinkedView.NetworkSystem.NetworkInfo.Vswitch | ?{$_.Key -eq $oPortGroup.Vswitch}
               
$strVSwitchType = if ($oVSwitch) {$oVSwitch.GetType().Name} else {"vSwitch type not found"}
               
break;
            }
## end this case
            ## if this NIC is on a dvSwitch
            "VirtualEthernetCardDistributedVirtualPortBackingInfo" {
               
## find the View object of the dvSwitch for this NIC from the array of dvSwitches, by Uuid
                $oDVSwitch = $arrDVSwitchViews | ?{$_.Uuid -eq $oEthCard.Backing.Port.SwitchUuid}
               
$oDVPortgroup = $oDVSwitch.LinkedView.Portgroup | ?{$_.Key -eq $oEthCard.Backing.Port.PortgroupKey}
               
## the portgroup name for this VirtualEthernetCard
                $strPortgroupName = $oDVPortgroup.Name
               
## the name of the dvSwitch for this portgroup
                $strVSwitchName = $oDVSwitch.Name
               
## the type of the dvSwitch for this portgroup
                $strVSwitchType = if ($oDVSwitch) {$oDVSwitch.GetType().Name} else {"dvSwitch type not found"}
               
break;
            }
## end this case
        } ## end switch

       
## create an object with the info about this VirtualEthernetCard
        New-Object -TypeName PSobject -Property @{
            VMName
= $viewThisVM.Name
            VMXLocation
= $viewThisVM.Config.Files.VmPathName
            NICName
= $_.DeviceInfo.Label
            NICType
= $_.GetType().Name
            MACAddress
= $_.MacAddress
            PortgroupName
= $strPortgroupName
            vSwitchType
= $strVSwitchType
            vSwitchName
= $strVSwitchName
        }
## end new-object
    } ## end foreach-object
} ## end foreach-object
} | Select VMName, VMXLocation, NICName, NICType, MACAddress, PortgroupName, vSwitchType, vSwitchName

How does that do for you?

sureshadmin2011
Enthusiast
Enthusiast

Thanks Matt. Installed PowerCLI 5 and works perfect.

0 Kudos
cray326
Contributor
Contributor

Matt-

I am new to using PowerCLI but your script worked great.  Two newbie questions- 1. How can I get the same information broken out by cluster?

2. Can I get it exported to a .CSV format?

Thanks

0 Kudos
mattboren
Expert
Expert

Helo, cray326-

Welcome to the communities.

I see your questions, now.  Here are some answers:

1)  You could wrap another Get-View call around the entire body of code that does this by cluster, so then you could include a ClusterName property for each VM -- let me know if you want further info on that

2)  Yes, it is easy to export to <format of your choice>.  Just pipe the output to Export-Csv.  There are examples throughout the forums, elsewhere on the internet, etc.  Basically, something like:  <put all the code from the post here> | Export-Csv -Path c:\temp\myInfo.csv -UseCulture -NoTypeInformation

Enjoy

0 Kudos
TupleSpace
Contributor
Contributor

This is truly a beautiful piece of crafted code my friend Smiley Happy

0 Kudos
TupleSpace
Contributor
Contributor

Hi Matt,

I really liked your code example.

It is very clean and well put together.

After studying your example, I created script based on yours that maps the Network path of each VM virtual NIC

from VNic to Physical Switch Port.

(See attached)

I still need to modify it to work with a DVswitch.

Thanks again,

Frank 🙂

0 Kudos
psinha2911
Contributor
Contributor

Nice script..

I'm new to scripting.. Do we have any way to get the Virtual machine multiple IP address information with the same script?

arindamhazra
Contributor
Contributor

Hi Matt!

Great script! I followed your provided method and achieved tremendous performance boost while collecting inventory data from our VMware environment.

Thanks a lot!


--Arindam

0 Kudos