VMware Cloud Community
Sureshadmin
Contributor
Contributor
Jump to solution

Need Powershell script for VM inventory

Hi,

Need a powershell script to collect the below given info from virtual center.

vmname | ESX Name | memory(GB) | vCPU count | vNIC Count | IP address(all) | vmdk(s) size(GB) | Total vmdk size(GB) | Datastore name | Tools version | tools update | shares | reservations(MB) | limit(MB) | snapshot count | Guest OS

vmdk(s) size(GB) ---> Need all vmdk size of the vm seperated by "". EX: for a vm of 3 vmdk's of size 20,20,10GB each the output would be 2020+10

Datastore Name ---> Name of the datastore where VMX is located.

Tools update ---> Need status like old or updated

85 Replies
MichaelJ1
Contributor
Contributor
Jump to solution

Hi LucD,

Thanks for this script, it's really useful.


I was wondering if it was possible to add something? I'm trying to figure it out in the inventory script below. I was wondering if you could help figure out a way to add a few columns in the script for drivepath, disk space and disk usage? I know it's possible based on this post:

http://communities.vmware.com/thread/292032

For example, (similar to the IP address and DatastoreURL), I was hoping to add a few fields where the number of drives are separated by commas for each VM?

VMname,   drivepath,   diskspace,   diskusage,   disk%

+++++++++++++++++++++++++++++++++++++++++

SomeVM,  C:\,D:\,   50GB, 30GB,   40GB, 20GB,   80%,66.66%

Another(linux),   /         ,    100GB,      75GB,    75%         

So if you were reading the above, you could easily tell that the C: drive is 50GB in size, it's using 40GB and is 80% full.

I know it's possible based on the thread above but if I could incorporate it in this script, that would be perfect.

Keep up the great work!

Mike

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

Here you go, I hope that's what you were looking for.

The new lines are added at the end and all the properties start with GuestDisk

$allLines = @() # Line added  
$null
| Out-File "C:\vmnotfound.txt" Get-Content -Path "C:\vmnames.txt" | %{     $vm = Get-VM -Name $_ -ErrorAction SilentlyContinue    if(!$vm){         $_ | Out-File "C:\vmnotfound.txt" -Append }     else{         $VMResourceConfiguration = $VM | Get-VMResourceConfiguration
       
$VMHardDisks = $VM | Get-HardDisk
       
$HardDisksSizesGB = @()         $Temp = $VMHardDisks | ForEach-Object { $HardDisksSizesGB += [Math]::Round($_.CapacityKB/1MB) }         $VmdkSizeGB = ""
       
$Temp = $HardDisksSizesGB | ForEach-Object { $VmdkSizeGB += "$_+" }         $VmdkSizeGB = $VmdkSizeGB.TrimEnd("+")         $TotalHardDisksSizeGB = 0
        $Temp = $HardDisksSizesGB | ForEach-Object { $TotalHardDisksSizeGB += $_ }         $VMDKnames = @()         $Temp = $VMHardDisks | ForEach-Object { $VMDKnames += $_.Filename.Split("/")[1] }         $Snapshots = $VM | Get-Snapshot
        $Report = "" | Select-Object VMname,vmCreatedByUser,vmCreatedDate,ESXname,ClusterName,MemoryGB,vCPUcount,vNICcount,vNICType,         IPaddresses,VMXname,VMDKname,VmdkSizeGB,TotalVmdkSizeGB,DatastoreName,ToolsVersion,ToolsUpdate,NumCpuShares,         CpuLimitMHZ,CpuReservationMHZ,NumMemShares,ReservationsMB,LimitMB,SnapshotCount,GuestOS,VLANid,Portgroup,         RDMPath,GuestDisks,GuestDiskspaceGB,GuestDiskspaceUsedGB,GuestDiskspaceUsed         $Report.VMName = $VM.name         $Report.vmCreatedByUser = $VM.CustomFields["CreatedBy"]         $Report.vmCreatedDate = $VM.CustomFields["CreatedOn"]         $Report.ESXname = $VM.Host         $Report.ClusterName = ($VM | Get-Cluster).Name         $Report.MemoryGB = $VM.MemoryMB/1KB         $Report.vCPUcount = $VM.NumCpu         $Report.vNICcount = $VM.Guest.Nics.Count         $report.vNicType = [string]::Join(',',($vm.NetworkAdapters | %{$_.Type}))         $Report.IPaddresses = [string]::Join(',',$VM.Guest.IPAddress)         $Report.VMXname = $vm.Extensiondata.Config.Files.VmPathName.Split("/")[1]         $Report.VMDKname = [string]::Join(',',$VMDKnames)         $Report.VmdkSizeGB = $VmdkSizeGB
        $Report.TotalVmdkSizeGB = $TotalHardDisksSizeGB
        $Report.DatastoreName = [string]::Join(',',($vm.Extensiondata.Config.DatastoreUrl | %{$_.Name}))         $Report.ToolsVersion = $vm.Extensiondata.Config.Tools.ToolsVersion         $Report.ToolsUpdate = $vm.Extensiondata.Guest.ToolsStatus         $Report.NumCpuShares = $VMResourceConfiguration.NumCPUShares         $Report.CpuLimitMHZ = &{if($VMResourceConfiguration.CpuLimitMhz -eq -1){"No Limit"}else{$VMResourceConfiguration.CpuLimitMhz}}         $Report.CpuReservationMHZ = $VMResourceConfiguration.CpuReservationMhz         $Report.NumMemShares = $VMResourceConfiguration.NumMemShares         $Report.ReservationsMB = $VMResourceConfiguration.MemReservationMB         $Report.LimitMB = &{if($VMResourceConfiguration.MemLimitMB -eq -1){"No Limit"}else{$VMResourceConfiguration.MemLimitMB}}         $Report.SnapshotCount = (@($VM | Get-Snapshot)).Count         $Report.GuestOS = $VM.Guest.OSFullName         $Report.VLANid = [string]::Join(',',(Get-VirtualPortgroup -VM $vm | %{$_.VlanId}))         $Report.Portgroup = [string]::Join(',',(Get-VirtualPortgroup -VM $vm | %{$_.Name}))         $RDMPaths = $vm | Get-HardDisk | where {$_.DiskType -like "Raw*"}         $Report.RDMPath = &{if($RDMPaths){[string]::Join(',',($RDMPaths | %{$_.ScsiCanonicalName}))}else{"No RDM"} }         $Report.GuestDisks = [string]::Join(',',($VM.Guest.Disks | %{$_.Path}))         $Report.GuestDiskspaceGB = [string]::Join(',',($VM.Guest.Disks | %{"{0:f0}" -f ($_.Capacity/1GB)}))         $Report.GuestDiskspaceUsedGB = [string]::Join(',',($VM.Guest.Disks | %{"{0:f0}" -f (($_.Capacity - $_.FreeSpace)/1GB)}))         $Report.GuestDiskspaceUsed = [string]::Join(',',($VM.Guest.Disks | %{"{0:p0}" -f (($_.Capacity - $_.FreeSpace)/$_.Capacity)}))         $allLines += $Report # Line changed                 } } $allLines | Export-Csv "C:\VMreport.csv" -NoTypeInformation -UseCulture


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

Reply
0 Kudos
MichaelJ1
Contributor
Contributor
Jump to solution

Great! That's it. Thanks LucD!

One quick comment. If Tools are not running there will be errors like this:

Attempted to divide by zero.
At C:\scripts\PowerShell\vaughan_esx_inventory.ps1:99 char:120
+         $Report.GuestDiskspaceUsed = [string]::Join(',',($VM.Guest.Disks | %{
"{0:p0}" -f (($_.Capacity - $_.FreeSpace)/ <<<< $_.Capacity)}))
    + CategoryInfo          : NotSpecified: (:) [], RuntimeException
    + FullyQualifiedErrorId : RuntimeException
Exception calling "Join" with "2" argument(s): "Value cannot be null.
Parameter name: value"
At C:\scripts\PowerShell\vaughan_esx_inventory.ps1:99 char:52
+         $Report.GuestDiskspaceUsed = [string]::Join <<<< (',',($VM.Guest.Disk
s | %{"{0:p0}" -f (($_.Capacity - $_.FreeSpace)/$_.Capacity)}))
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : DotNetMethodException

It's not really a big deal as I'm aware that VMware Tools should be installed on VMs so their supported. Is there a way we could add an if clause to this? Maybe if Toolsversion = 0, do not look for disk info?

Again, not a big deal at all because the export still succeeds and just leaves those values as 0 for guest.disk.

Thanks again!

Mike

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

Yes, you easily can add a test.

Something like this for example

$Report.GuestDiskspaceUsedGB = &{if($VM.Guest){[string]::Join(',',($VM.Guest.Disks | %{"{0:f0}" -f (($_.Capacity - $_.FreeSpace)/1GB)}))}}

When $VM.Guest is not $null, the expression will be calculated. Otherwise the property will be left empty.

You will have to do something similar for the other property that involves a division.


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

Reply
0 Kudos
MichaelJ1
Contributor
Contributor
Jump to solution

Great! Thanks again, LucD.

I have one more question regarding this excellent script. Say I wanted to run the script in a loop, i can do something like this (which I found elsewhere on this forum):

$viservers = "192.168.0.100", "192.168.0.200", "192.168.0.230", "192.168.0.240"

foreach ($singleViserver in $viservers)

{
Connect-VIServer $singleViserver -user $username -password $password
###script goes here###
Disconnect-viserver
}

$VMObject | Export-csv "$filelocation" -NoTypeInformation

The for loop works (it connects and disconnects to each of the 4 hosts). But when the $VMObject is exported to the CSV file, it only exports the last one (the 192.168.0.240 host).

Is there a way I can modify the loop so that it will export the data from all four hosts into one CSV file? That would be ideal.

Thanks again for your help.


Mike

Reply
0 Kudos
avlieshout
VMware Employee
VMware Employee
Jump to solution

That's probably because the script overwrites $VMObject everytime it goes trough the loop.

PowerCLI supports multiple connections

Just remove the complete loop and just provide the array of viservers to the connect-viserver cmdlet

$viservers = "192.168.0.100", "192.168.0.200", "192.168.0.230", "192.168.0.240"

Connect-VIServer $Viservers -user $username -password $password

###script goes here###

Disconnect-viserver

Arnim van Lieshout Blogging: http://www.van-lieshout.com Twitter: http://www.twitter.com/avlieshout If you find this information useful, please award points for "correct" or "helpful".
Reply
0 Kudos
MichaelJ1
Contributor
Contributor
Jump to solution

Hi Avlieshout,

Thanks for the speedy reply. I think I jumped the gun in posting my question because I tried one more thing after i posted and it worked!

Here's my solution:

$viservers = "192.168.0.100", "192.168.0.200", "192.168.0.230", "192.168.0.240"

foreach ($singleViserver in $viservers)

{
Connect-VIServer $singleViserver -user $username -password $password
###script goes here###
$VMObject += $Report
Disconnect-viserver -Confirm:$False
$FullReport += $VMObject
}

$FullReport | Export-csv "$filelocation" -NoTypeInformation

I simply added a new variable for FullReport and made it increment off VMObject. Then I exported the 'full report' instead of VMobject. Worked like a charm!

Thanks again for your quick reply.

Mike

Reply
0 Kudos
avlieshout
VMware Employee
VMware Employee
Jump to solution

Glad to hear that you've got it working!

You should definitely try my suggestion if you find the time. It will make your scripts a lot easier.

Arnim van Lieshout Blogging: http://www.van-lieshout.com Twitter: http://www.twitter.com/avlieshout If you find this information useful, please award points for "correct" or "helpful".
Reply
0 Kudos
pmeqix
Contributor
Contributor
Jump to solution

Hi LucD

Could you help in explaining what am I doing wrong here to replace the  input vmnames.txt with the Get-VM command but am getting the errors attached in the error.txt file.

Unfortunately could not trace it to the exact reason why this would be happening. Any help is highly appreciated.

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

The first lines should be

$allLines = @() # Line added 
Get-VM
| ForEach-Object {     $VMview = Get-View $_
...

The $VM variable you had in your version would only have a content at the end of the Foreach loop.

The lines above get the guests and place them in the pipeline.

The Foreach-Object will take the objects one-by-one, make the object accessible through the $_ variable and execute the Foreach-Object code block for each object.


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

Reply
0 Kudos
actixsupport
Contributor
Contributor
Jump to solution

Hi,

Could you add support for think provisioned disks with the same totaling as you've done for the current disks stats?

ie: list each disk thin provisioned size and total?

Thanks

Ray

Reply
0 Kudos
vmhyperv
Contributor
Contributor
Jump to solution

Hi LucD,

     Need your help for your good script for VM inventory.Its shows error and i need IP address too

[vSphere PowerCLI] C:\tmp> .\VM-inventory.ps1
Missing closing '}' in statement block.
At C:\tmp\VM-inventory.ps1:62 char:1
+  <<<<
    + CategoryInfo          : ParserError: (CloseBraceToken:TokenId) [], ParseException
    + FullyQualifiedErrorId : MissingEndCurlyBrace

Thanks

Kumar

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

There was a curly brace missing.

Try the attached version.


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

Reply
0 Kudos
pmeqix
Contributor
Contributor
Jump to solution

Kumar,

it could be a simple copy paste error..

I was planning ot upload this latest version anyways for others to use.. try downloading this new file and see if it runs without errors for you.

Details:

  • Line 6 -- you need to define the VCserver you are connecting to
  • Line 12 is the current default filename for the output
    • You can use Line 11 if you want date/timestamp in your file name (comment out if using line 11)
    • Comment Line 12 if you plan to use Line 11
  • Line 34 - Is commented and is there as a debug option to provide the VM name to ensure the script is running in your environment
  • Line 40 - Do not enable this line as it will give errors.. this function has been split to lines 41-43
  • Line 60 - 69 --> These are for custom fields .. adjust them based on your environment and adjust line 30 accordingly and comment out and appened it to Line 29 else you will get errors
Reply
0 Kudos
vmhyperv
Contributor
Contributor
Jump to solution

Thanks for prompt response.Is it possible that script should prompt for my credential becuase while executing  its taking default credential

for windows while VC having diffirent id and diffrent passwd with more previlge.

Thanks

Kumar

Reply
0 Kudos
cjcurts
Contributor
Contributor
Jump to solution

I need some assistance with grabbing just the MAC address of a given VM's Network Adapter 1 using powershell and then redirecting that output to a CSV file. I don't think I can use the scripts that have been posted on this thread because they involve getting the entire VM. I tried running the following:

Get-NetworkAdapter -VM <VM>

But this command spits out all of the NICs (I have 4 NICs) and a bunch of information I do not want. All I need is the MAC address of the first nic and to throw that information into a CSV file.

Thanks in advance for the help.

CJ

Reply
0 Kudos
pmeqix
Contributor
Contributor
Jump to solution

Hi LucD

Needed some help. with the attached script I am getting some errors and the macaddress being collected in the output is getting prefixed as follows. any help is highly appreciated.

Macaddress -->

Line 92 of the script.

output is:

VMMac == @{MacAddress=00:50:56:93:46:10}

errors i am getting

Exception calling "Join" with "2" argument(s): "Value cannot be null.

Parameter name: value"

At U:\Scripts\VMInventory-v4.ps1:47 char:50

+     $Report.vNicType = &{if($_.Guest){[string]::Join <<<< (',',($vm.NetworkAd

apters | %{$_.Type}))}}

    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException

    + FullyQualifiedErrorId : DotNetMethodException

Exception calling "Join" with "2" argument(s): "Value cannot be null.

Parameter name: value"

At U:\Scripts\VMInventory-v4.ps1:58 char:52

+     $Report.GuestDisks = &{if($_.Guest){[string]::Join <<<< (',',($_.Guest.Di

sks | %{$_.Path}))}}

    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException

    + FullyQualifiedErrorId : DotNetMethodException

Attempted to divide by zero.

At U:\Scripts\VMInventory-v4.ps1:62 char:130

+     $Report.GuestDiskspaceUsed = &{if($_.Guest){[string]::Join(',',($_.Guest.

Disks | %{"{0:p0}" -f (($_.Capacity - $_.FreeSpace)/ <<<< $_.Capacity)}))}}

    + CategoryInfo          : NotSpecified: (:) [], RuntimeException

    + FullyQualifiedErrorId : RuntimeException

Exception calling "Join" with "2" argument(s): "Value cannot be null.

Parameter name: value"

At U:\Scripts\VMInventory-v4.ps1:62 char:63

+     $Report.GuestDiskspaceUsed = &{if($_.Guest){[string]::Join <<<< (',',($_.

Guest.Disks | %{"{0:p0}" -f (($_.Capacity - $_.FreeSpace)/$_.Capacity)}))}}

    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException

    + FullyQualifiedErrorId : DotNetMethodException

Exception calling "Join" with "2" argument(s): "Value cannot be null.
Parameter name: value"
At U:\Scripts\VMInventory-v4.ps1:47 char:35
+     $Report.vNicType = [string]::Join <<<< (',',($vm.NetworkAdapters | %{$_.T
ype}))
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : DotNetMethodException
Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

For the Join error, you should change this line

$Report.vNicType = &{if($_.Guest){[string]::Join(',',($vm.NetworkAdapters | %{$_.Type}))}}

into this

$Report.vNicType = &{if($_.Guest){[string]::Join(',',($_.NetworkAdapters | %{$_.Type}))}}

For the zero-divide error, it looks as if you have some VMs that zero-capacity harddisks.

Is that possible ?

You can try changing this line

$Report.GuestDiskspaceUsed = &{if($_.Guest){[string]::Join(',',($_.Guest.Disks | %{"{0:p0}" -f (($_.Capacity - $_.FreeSpace)/$_.Capacity)}))}}

into this

$Report.GuestDiskspaceUsed = &{if($_.Guest){[string]::Join(',',($_.Guest.Disks | where {$_.Capacity -ne 0} | %{"{0:p0}" -f (($_.Capacity - $_.FreeSpace)/$_.Capacity)}))}}


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

Reply
0 Kudos
clockvm
Contributor
Contributor
Jump to solution

How about above script to HTML? Thank you.

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

Basically when you replace the Export-CSV by a ConvertTo-Html | Set-Content, you should have a HTML file.

But the fancy formatting will require playing with style sheets and using the Body and Head parameters.

There are numerous examples in this community.

Alan's vCheck is a good example how far you can go in producing HTML reports.

Anything specific you're after ?


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

Reply
0 Kudos