After a great meeting with a current Nutanix customer they asked if we had a tool that could provide them with some more background on their current cluster utilization and report on that. While Prism/Prism Pro will give you excellent reporting I try to automate as much as possible so I decided to alter the excisting Reporting Script I had written before to have working set size for read/write IO and potential CPU RDY times in the reporting as well.
From that older blog, the following interfaces are available:
- REST API
- HTML5 GUI
- CLI – ACLI & NCLI
- Scripting interfaces (PowerShell)
The following definitions are from the Nutanix Bible as Steve Poitras already explained this:
REST API The REST API exposes every capability and data point of the Prism UI and allows for orchestration or automation tools to easily drive Nutanix action. This enables tools like Saltstack, Puppet, vRealize Operations, System Center Orchestrator, Ansible, etc. to easily create custom workflows for Nutanix. Also, this means that any third-party developer could create their own custom UI and pull in Nutanix data via REST. HTML5 GUI (Prism UI) The HTML5 UI is a key part to Prism to provide a simple, easy to use management interface. However, another core ability are the APIs which are available for automation. All functionality exposed through the Prism UI is also exposed through a full set of REST APIs to allow for the ability to programmatically interface with the Nutanix platform. This allow customers and partners to enable automation, 3rd-party tools, or even create their own UI. CLI – ACLI & NCLI The Acropolis CLI (ACLI) is the CLI for managing the Acropolis portion of the Nutanix product. These capabilities were enabled in releases after 4.1.2. The Nutanix CLI is the CLI for managing the Nutanix product and is more heterogeneous across hypervisors. PowerShell Windows PowerShell is a powerful shell (hence the name ;P) and scripting language built on the .NET framework. It is a very simple to use language and is built to be intuitive and interactive. |
With this new version of the inventory script I’ve added working set sizes for both Read I/O, Write I/O and combined I/O besides the CPU RDY times. The I/O is measured on an average of 3600 seconds (1 hour) and the CPU RDY times are a point in time measurement.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 |
<# <# .SYNOPSIS Creates a complete inventory of a Nutanix environment. .DESCRIPTION Creates a complete inventory of a Nutanix Cluster configuration using CSV and PowerShell.If you want output to HTML (and be able to export to PDF/CSV from there, please do 'Install-Module PSWriteHTML -Force' in an elevated powershell session. Otherwise the default output will be CSV. .PARAMETER nxIP IP address of the Nutanix node you're making a connection too. .PARAMETER nxUser Username for the connection to the Nutanix node .PARAMETER nxPassword Password for the connection to the Nutanix node .EXAMPLE PS C:\PSScript > .\nutanix_inventory.ps1 -nxIP "99.99.99.99.99" -nxUser "admin" .INPUTS None. You cannot pipe objects to this script. .OUTPUTS No objects are output from this script. This script creates a CSV file. .NOTES NAME: Nutanix_Inventory_Script_v3.ps110. VERSION: 1.0 AUTHOR: Kees Baggerman with help from Andrew Morgan, Michell Grauwman and Dave Brett CREDITS: Using https://evotec.xyz/out-htmlview-html-alternative-to-out-gridview/ for HTML output. LASTEDIT: March 2019 #> # Setting parameters for the connection [CmdletBinding(SupportsShouldProcess = $False, ConfirmImpact = "None") ] Param( # Nutanix cluster IP address [Parameter(Mandatory = $true)] [Alias('IP')] [string] $nxIP, # Nutanix cluster username [Parameter(Mandatory = $true)] [Alias('User')] [string] $nxUser, # Nutanix cluster password [Parameter(Mandatory = $true)] [Alias('Password')] [String] $nxPassword ) # Converting the password to a secure string which isn't accepted for our API connectivity $nxPasswordSec = ConvertTo-SecureString $nxPassword -AsPlainText -Force Function write-log { <# .Synopsis Write logs for debugging purposes .Description This function writes logs based on the message including a time stamp for debugging purposes. #> param ( $message, $sev = "INFO" ) if ($sev -eq "INFO") { write-host "$(get-date -format "hh:mm:ss") | INFO | $message" } elseif ($sev -eq "WARN") { write-host "$(get-date -format "hh:mm:ss") | WARN | $message" } elseif ($sev -eq "ERROR") { write-host "$(get-date -format "hh:mm:ss") | ERROR | $message" } elseif ($sev -eq "CHAPTER") { write-host "`n`n### $message`n`n" } } # Adding PS cmdlets $loadedsnapins = (Get-PSSnapin -Registered | Select-Object name).name if (!($loadedsnapins.Contains("NutanixCmdletsPSSnapin"))) { Add-PSSnapin -Name NutanixCmdletsPSSnapin } if ($null -eq (Get-PSSnapin -Name NutanixCmdletsPSSnapin -ErrorAction SilentlyContinue)) { write-log -message "Nutanix CMDlets are not loaded, aborting the script" break } $debug = 2 Function Get-Hosts { <# .Synopsis This function will collect the hosts within the specified cluster. .Description This function will collect the hosts within the specified cluster using REST API call based on Invoke-RestMethod #> Param ( [string] $debug ) $credPair = "$($nxUser):$($nxPassword)" $encodedCredentials = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($credPair)) $headers = @{ Authorization = "Basic $encodedCredentials" } $URL = "https://$($nxIP):9440/api/nutanix/v3/hosts/list" $Payload = @{ kind = "host" offset = 0 length = 999 } $JSON = $Payload | convertto-json try { $task = Invoke-RestMethod -Uri $URL -method "post" -body $JSON -ContentType 'application/json' -headers $headers; } catch { Start-Sleep 10 write-log -message "Going once" $task = Invoke-RestMethod -Uri $URL -method "post" -body $JSON -ContentType 'application/json' -headers $headers; } write-log -message "We found $($task.entities.count) hosts in this cluster." Return $task } Function Get-VMs { <# .Synopsis This function will collect the VMs within the specified cluster. .Description This function will collect the VMs within the specified cluster using REST API call based on Invoke-RestMethod #> Param ( [string] $debug ) $credPair = "$($nxUser):$($nxPassword)" $encodedCredentials = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($credPair)) $headers = @{ Authorization = "Basic $encodedCredentials" } write-log -message "Executing VM List Query" $URL = "https://$($nxIP):9440/api/nutanix/v3/vms/list" $Payload = @{ kind = "vm" offset = 0 length = 999 } $JSON = $Payload | convertto-json try { $task = Invoke-RestMethod -Uri $URL -method "post" -body $JSON -ContentType 'application/json' -headers $headers; } catch { Start-Sleep 10 write-log -message "Going once" $task = Invoke-RestMethod -Uri $URL -method "post" -body $JSON -ContentType 'application/json' -headers $headers; } write-log -message "We found $($task.entities.count) VMs." Return $task } Function Get-DetailVM { <# .Synopsis This function will collect the speficics of the VM we've specified using the Get-VMs function as input. .Description This function will collect the speficics of the VM we've specified using the Get-VMs function as input using REST API call based on Invoke-RestMethod #> Param ( [string] $uuid, [string] $debug ) $credPair = "$($nxUser):$($nxPassword)" $encodedCredentials = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($credPair)) $headers = @{ Authorization = "Basic $encodedCredentials" } $URL = "https://$($nxIP):9440/api/nutanix/v3/vms/$($uuid)" try { $task = Invoke-RestMethod -Uri $URL -method "get" -headers $headers; } catch { Start-Sleep 10 write-log -message "Going once" } Return $task } Function Get-DetailHosts { Param ( [string] $uuid, [string] $debug ) $credPair = "$($nxUser):$($nxPassword)" $encodedCredentials = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($credPair)) $headers = @{ Authorization = "Basic $encodedCredentials" } $URL = "https://$($nxIP):9440/api/nutanix/v3/hosts/$($uuid)" try { $task = Invoke-RestMethod -Uri $URL -method "get" -headers $headers; } catch { Start-Sleep 10 $task = Invoke-RestMethod -Uri $URL -method "get" -headers $headers; write-log -message "Going once" } Return $task } # Selecting all the GPUs and their devices IDs in the cluster $GPU_List = $null $hosts = Get-Hosts -ClusterPC_IP $nxIP -nxPassword $nxPassword -clusername $nxUser -debug $debug Foreach ($Hypervisor in $hosts.entities) { $detail = Get-DetailHosts -ClusterPC_IP $nxIP -nxPassword $nxPassword -clusername $nxUser -debug $debug -uuid $Hypervisor.metadata.uuid [array]$GPU_List += $detail.status.resources.gpu_list } write-log -message "Collecting vGPU profiles and Device IDs" # Connecting to the Nutanix Cluster $nxServerObj = Connect-NTNXCluster -Server $nxIP -UserName $nxUser -Password $nxPasswordSec -AcceptInvalidSSLCerts -ForcedConnection write-log -Message "Connecting to cluster $nxIp" if ($null -eq (get-ntnxclusterinfo)) { write-log -message "Cluster connection isn't available, aborting the script" break } else { write-log -message "Connected to Nutanix cluster $nxIP" } # Fetching data and putting into CSV $vms = @(get-ntnxvm | Where-Object {$_.controllerVm -Match "false"}) write-log -message "Grabbing VM information" write-log -message "Currently grabbing information on $($vms.count) VMs" $FullReport = @() foreach ($vm in $vms) { $usedspace = 0 if (!($vm.nutanixvirtualdiskuuids.count -le $null)) { write-log -message "Grabbing information on $($vm.vmName)" foreach ($UUID in $VM.nutanixVirtualDiskUuids) { $usedspace += (Get-NTNXVirtualDiskStat -Id $UUID -Metrics controller_user_bytes).values[0] $workingset_read = (Get-NTNXVirtualDiskStat -Id $UUID -Metrics controller.wss_3600s_read_MB).values[0] $workingset_write = (Get-NTNXVirtualDiskStat -Id $UUID -Metrics controller.wss_3600s_write_MB).values[0] $workingset_union = (Get-NTNXVirtualDiskStat -Id $UUID -Metrics controller.wss_3600s_union_MB).values[0] } } if ($vm.gpusInUse -eq "true") { $myvmdetail = Get-DetailVM -ClusterPC_IP $nxIP -nxPassword $nxPassword -clusername $nxUser -debug $debug -uuid $vm.uuid $newVMObject = $MyVMdetail $devid = $newVMObject.spec.resources.gpu_list $GPUUsed = $GPU_List | Where-Object {$_.device_id -eq $devid.device_id} $VMGPU = $GPUUsed | select-object {$_.name} -unique $VMGPU1 = $VMGPU.'$_.name' } else { $VMGPU1 = $Null } if ($usedspace -gt 0) { $usedspace = [math]::round($usedspace / 1gb, 0) } $container = "NA" if (!($vm.vdiskFilePaths.count -le 0)) { $container = $vm.vdiskFilePaths[0].split('/')[1] } if ($vm.nutanixGuestTools.enabled -eq 'False') { $NGTstate = 'Installed'} else { $NGTstate = 'Not Installed' } $props = [ordered]@{ "VM Name" = $vm.vmName "Container" = $container "Protection Domain" = $vm.protectionDomainName "Host Placement" = $vm.hostName "Power State" = $vm.powerstate "Network Name" = $myvmdetail.status.resources.nic_list.subnet_reference.name "Network adapters" = $vm.numNetworkAdapters "IP Address(es)" = $vm.ipAddresses -join "," "vCPUs" = $vm.numVCpus "Number of Cores" = $myvmdetail.spec.resources.num_sockets "Number of vCPUs per core" = $myvmdetail.spec.resources.num_vcpus_per_socket "vRAM (GB)" = [math]::round($vm.memoryCapacityInBytes / 1GB, 0) "Disk Count" = $vm.nutanixVirtualDiskUuids.count "Provisioned Space (GB)" = [math]::round($vm.diskCapacityInBytes / 1GB, 0) "Used Space (GB)" = $usedspace "GPU Profile" = $VMGPU1 "VM description" = $vm.description "Guest Operating System" = $vm.guestOperatingSystem "VM Time Zone" = $myvmdetail.spec.resources.hardware_clock_timezone "Nutanix Guest Tools installed" = $NGTState "Working Set Read in MB" = $workingset_read "Working Set Write in MB" = $workingset_write "Union Working Set in MB" = $workingset_union "CPU RDY Time" = $vm.stats.'hypervisor.cpu_ready_time_ppm' } #End properties $Reportobject = New-Object PSObject -Property $props $fullreport += $Reportobject } #Import modules $loadedmodules=Get-module | Select-Object name if(!($loadedmodules.Contains("PSSharedGoods"))){ Import-Module PSWriteHTML write-log -message "Importing Module PSWriteHTML" $fullreport |Out-HtmlView write-log -message "Writing the information to HTML" } else { $fullreport | Export-Csv -Path ~\Desktop\NutanixVMInventory.csv -NoTypeInformation -UseCulture -verbose:$false write-log -message "Writing the information to the CSV" } # Disconnecting from the Nutanix Cluster Disconnect-NTNXCluster -Servers * write-log -message "Closing the connection to the Nutanix cluster $($nxIP)" |
Running the script is straight forward:
1 |
.\Nutanix_VM_Inventory_v8.ps1 -nxIP 10.68.68.40 -nxUser Admin -nxPassword *********** |
Kees Baggerman
Latest posts by Kees Baggerman (see all)
- Nutanix AHV and Citrix MCS: Adding a persistent disk via Powershell – v2 - November 19, 2019
- Recovering a Protection Domain snapshot to a VM - September 13, 2019
- Checking power settings on VMs using powershell - September 11, 2019
- Updated: VM Reporting Script for Nutanix with Powershell - July 3, 2019
- Updated (again!): VM Reporting Script for Nutanix AHV/vSphere with Powershell - June 17, 2019
[…] via Updated (again!): VM Reporting Script for Nutanix AHV/vSphere with Powershell — My Virtual Vision […]
Hi there,
I ran the script and input the ip?username and password,
it show “ Nutanix CMDlets are not loaded, aborting the script”.
[…] Kees’ PowerShell inventory script […]