Thursday, February 28, 2013

How to retrieve ESX and local datastores with Powershell

I have been asked to individuate all the ESX that need being remediated as well as retrieve the capacity of their local storage to see if some of them might need larger disks to be bought.

There are a few hundreds ESX in that server farm, so I am going to show you how I used Powershell and PowerCLI cmdlets to retrieve exactly what I wanted.

The aim of my script is to return a custom Powershell object (aka PSObject) that contains all the needed properties for later analysis.

These properties are: the ESX name, model, version, build and all of its local datastores with their capacity. This last one in particular I retrieve it using the MultipleHostAccess property.

Here's the script I wrote:
  1. function Get-Esxinfo {  
  2. <#  
  3.   .SYNOPSIS  
  4.     This script returns information on one or more ESX.  
  5.    
  6.   .DESCRIPTION  
  7.     This script returns information on one or more ESX.  
  8.     You can run the script against one or more ESX.  
  9.     This script can display the information in a spreadsheet.  
  10.    
  11.   .PARAMETER Server  
  12.     Specify the vSphere servers on which you want to run this function.  
  13.    
  14.   .PARAMETER Name  
  15.     Specify the names of the hosts you want to retrieve.  
  16.     By default this script will retrieve all the ESX hosts connected to the current vCenter.  
  17.    
  18.   .PARAMETER Filepath  
  19.     Specifies the path to the CSV output file. The default is 'esxinfo.csv'. This file will be saved in the local temp folder.  
  20.       
  21.   .PARAMETER OpenFile  
  22.         Opens the output file with the program associated with CSV files.  
  23.            
  24.   .PARAMETER PassThru  
  25.         Returns the object.  
  26.    
  27.   .EXAMPLE  
  28.         Get-Esxinfo -server virtualcenter  
  29.         Gets information for all the ESX connected to VIserver named 'virtualcenter'.  
  30.           
  31.   .EXAMPLE  
  32.         Get-Esxinfo -server virtualcenter -name esx00*  
  33.         Gets information for all the ESX whose name starts with esx00* connected to VIserver named 'virtualcenter'.  
  34.   
  35.   .EXAMPLE  
  36.         $EsxServers = Get-Content ESXServers.txt  
  37.         $EsxServers | Get-Esxinfo -server virtualcenter -openfile -passthru  
  38.         Gets the information from all the ESX listed in ESXServers.txt  
  39.         Opens the output file with the program associated with CSV files.  
  40.         Returns the object.  
  41.   
  42.   .EXAMPLE  
  43.         Get-Esxinfo -server virtualcenter -verbose | format-table  
  44.         Gets information for all the ESX connected to VIserver named 'virtualcenter' and show the output in a table.  
  45.         Show verbose information.  
  46.   
  47.    .INPUTS  
  48.     System.String  
  49.     
  50.   .OUTPUTS  
  51.     PSObject  
  52.            
  53.   .NOTES  
  54.     Author: happysysadm.com  
  55.     Created: 27Avril2013  
  56.   
  57. #>  
  58.   
  59. #requires -version 2.0  
  60.   
  61. [CmdletBinding()]  
  62.   
  63. param(  
  64.     [Parameter(Mandatory=$true)]  
  65.     [string[]]$server,  
  66.       
  67.     [Parameter(Mandatory=$false,ValueFromPipeline=$True,ValueFromPipeLineByPropertyName=$True)]  
  68.     [string[]]$name="*",  
  69.       
  70.     [Parameter()]  
  71.     [ValidateScript({  
  72.         if((Test-Path -LiteralPath $_ -IsValid) -and ($_ -like '*.CSV'))  
  73.             {  
  74.             $true  
  75.             }  
  76.         else  
  77.             {  
  78.             throw ('The specified path "{0}" is invalid. Valid arguments include a path to a CSV file. Exiting.' -f $_)  
  79.         }  
  80.     })]  
  81.     [string]$filepath = (Join-Path -Path ([System.IO.Path]::GetTempPath()) -ChildPath "esxinfo.csv"),  
  82.   
  83.     [Parameter()]  
  84.     [switch]$OpenFile,  
  85.            
  86.     [Parameter()]  
  87.     [switch]$PassThru  
  88. )  
  89.   
  90. write-verbose "Adding VMware Powershell Snapin"  
  91. IF (-not (Get-PSSnapin VMware.VimAutomation.Core -ErrorAction SilentlyContinue)) {  
  92. Add-PSSnapin VMware.VimAutomation.Core  
  93. }  
  94.   
  95. write-verbose "Connecting to vCenter"  
  96. try  
  97.     {  
  98.     Connect-VIServer $server  
  99.     }  
  100. catch  
  101.     {  
  102.     Write-Warning "An error occured.`n$_`nExiting..."  
  103.     break  
  104.     }  
  105.   
  106. write-verbose "Preparing the wrapper for the returned psobjects"  
  107. $esxarray = @()  
  108.   
  109. write-verbose  "Retrieving the ESX information and storing it in an array (can take a bit...)"  
  110. try  
  111.     {  
  112.     $esxsource = @(Get-VMHost -Name $name)  
  113.     }  
  114. catch  
  115.     {  
  116.     Write-Warning "An error occured.`n$_`nExiting..."  
  117.     break  
  118.     }  
  119.   
  120. write-verbose "Counting the number of ESX to show a progress bar"  
  121. $totalesx = ($esxsource).count  
  122.   
  123. write-verbose "Initialiasing a counter"  
  124. $a = 0  
  125.   
  126. foreach($esx in $esxsource)  
  127.     {  
  128.     write-verbose  "Creating a psobject and adding members to it"  
  129.     $esxobject = New-Object -typename psobject   
  130.     $esxobject | add-member -membertype noteproperty -name 'ESX Name' -Value $esx.name  
  131.     $esxobject | add-member -membertype noteproperty -name 'ESX Model' -value $esx.model  
  132.     $esxobject | add-member -membertype noteproperty -name 'ESX Version' -value $esx.version  
  133.     $esxobject | add-member -membertype noteproperty -name 'ESX Build' -value $esx.build  
  134.       
  135.     write-verbose  "Retrieving local datastores only, LUNs are excluded because they are not local hardware"  
  136.     $datastores = Get-Datastore -VMHost $esx | Get-View | ?{$_.Summary.MultipleHostAccess -match 'false'}  
  137.     $i = 1  
  138.     foreach($datastore in $datastores)  
  139.         {  
  140.         $esxobject | add-member -membertype noteproperty -name "ESX $i datastore name" -value $datastore.summary.name  
  141.         $esxobject | add-member -membertype noteproperty -Name "ESX $i datastore capacity GB" -value ($datastore.summary.capacity /1GB)  
  142.         $i++  
  143.         }  
  144.     write-verbose "Adding PSObject to array"  
  145.     $esxarray += $esxobject  
  146.       
  147.     write-verbose "Removing psobject to be reused"  
  148.     $esxobject = $null  
  149.     $a++  
  150.       
  151.     write-verbose "Writing a progress bar"  
  152.     Write-Progress -Id 1 -Activity ("Querying ESX") -PercentComplete ($a / $totalesx * 100) -Status ("Queried {0} ESX of {1}" -f $a$totalesx)  
  153.     }  
  154.   
  155. write-verbose "Going to write array content to $filepath"  
  156. try  
  157.     {  
  158.     $esxarray | Export-Csv -UseCulture -NoTypeInformation $filepath  
  159.     }  
  160. catch [System.IO.IOException]  
  161.     {  
  162.     Write-Warning "Unable to write to $filepath. File could be in use.`n$_`nExiting..."  
  163.     break  
  164.     }  
  165. catch  
  166.     {  
  167.     Write-Warning "An error occured.`n$_`nExiting..."  
  168.     }  
  169.       
  170. write-verbose "Opening file if asked so"  
  171. if ($OpenFile)  
  172.         {  
  173.         Invoke-Item -Path $FilePath  
  174.         }  
  175.   
  176. write-verbose "Returning psobject if asked so"  
  177. if ($PassThru)  
  178.     {  
  179.     $esxarray  
  180.     }  
  181.               
  182. }  
  183.   
  184. Get-Esxinfo -server virtualcenter -name myesx* -verbose -PassThru -OpenFile | ft  
The only mandatory parameter is the name of your vCenter, which is used for initial connection. Other optional parameters are the name of the ESX to retrieve (* is used in case you specify none), the name of the logfile (which will be saved in your temp folder), and the possibility to invoke the program associated with CSV files (-openfile).

As you can see I create two hashtables:
  • one for containing the output of the get-vmhost command, so that later queries can quickly be done against this object instead of waiting for powershell to query the vCenter database again and again;
  • one for containing every ESX object with its properties.

Interesting articles that explain the use of PSObject and that I suggest you to read are:

I would also like to point out the use I made of a progress bar. This is a nice Powershell feature which is often overlooked by scripters. I like the idea of having this pop-up bar, so I deeply suggest getting used to it because its syntax is not so diffcult.

Note that the appearance of the progress bar varies when it is used at the Powershell prompt or within the PowerGUI:

Powershell write-progress as it appears at the prompt

Powershell write-progress as it appears in PowerGUI
Be sociable, share!

No comments:

Post a Comment

Related Posts Plugin for WordPress, Blogger...