Home » Nutanix » Capturing Nutanix Infra details using PowerShell and Prism Element(PE)

In this post I will use Nutanix REST API and PowerShell to capture the details for inventory creation purpose of Nutanix Infra.

Prism is the management component of Nutanix distributed architecture. Prism service runs on every Nutanix Controller VMs (CVM) that each Nutanix Node needs to host. Among the CVMs in a cluster, one is elected as leader to serve the HTTP based management requests. This component is called Prism Element (PE) and is responsible for cluster wide management. A multi-cluster environment can host the optional Prism Central (PC) to management the clusters from a single interface.

This picture from Nutanix bible https://nutanixbible.com/#anchor-book-of-prism-architecture gives the overview of Prism Element and Central. While each node hosts the CVM and hence the prism element, prism central is a virtual appliance that needs to be host separately as a VM.

While providing a HTML5 UI for browser-based management, Prism also provides the functionalities through REST API for customized interface, automation and orchestration creation purpose. PRISM v3 is available with Prism Central and v2.0 with prism element. These are well documented at Nutanix developer portal https://www.nutanix.dev/api-reference/. In addition, the REST API explore within prism element gives a quick overview of data points and methods available with them. In this post I will be using v2.0 API.

# Define the bellow three variables 
$NutanixclusterName = "Hostname or FQDN of Prism Element"
$reportFolder =  "Forlder Path where the reports will be created"
$NXCredential = "username:password"


# Bellow required if using self-signed or untrusted certificate on Prism Element
Add-type @"
    using System.Net;
    using System.Security.Cryptography.X509Certificates;
    public class TrustAllCertsPolicy : ICertificatePolicy {
        public bool CheckValidationResult(
            ServicePoint srvPoint, X509Certificate certificate,
            WebRequest request, int certificateProblem) {
            return true;
        }
    }
"@
[System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy
[Net.ServicePointManager]::SecurityProtocol = "tls12, tls11, tls" 

#Creating authorization Header for REST API call
$Header = @{"Authorization" = "Basic "+[System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($NXCredential))}
 
#Define the Report file to save the inventory data
$NtnxNodeReportName = "NX_Node-" + (Get-Date -Format dd-MMM-yyyy) + ".csv"
$NtnxNodeReportFile = Join-Path $reportFolder $NtnxNodeReportName
$NtnxClusReportName = "NX_Cluster-" + (Get-Date -Format dd-MMM-yyyy) + ".csv"
$NtnxClusReportFile = Join-Path $reportFolder $NtnxClusReportName
$NtnxstcnReportName = "NX_Container-" + (Get-Date -Format dd-MMM-yyyy) + ".csv"
$NtnxstcnReportFile = Join-Path $reportFolder $NtnxstcnReportName

# Let's get Node details of the cluster 
$NtnxRestData=Invoke-RestMethod -Method Get -Uri "https://$($NutanixclusterName):9440/api/nutanix/v2.0/hosts/" -Headers $Header

for ($i = 0; $i -lt $NtnxRestData.metadata.end_index; $i++) {

# NX cluster and Hostname, followed by IP address of NX, IPMI and hypervisor
# Node and Block serial Number, Block Model, CPU, CPU Cores and number of CPUs, memory 
# Hypervisor, its version, Number of VMs. Model and version detail of BIOS, BMC, HBA
# Disk model, SN and FW version. Up to 6 disks. Increase or Decrease as required.
# Storage capacity, physical and logical usage of the Node


$Report1 = ""|select NxCluster,NXHost,NXIP,OOBIP,HPVIP,NSN,BSN,Bmodel,CPU,Cores,Sockets,RAMGB,HPV,HPVVer,VMs, `
BIOSm,BIOSv,BMCm,BMCv,HBA1m,HBA1v,HBA2m,HBA2v,Disk1m,Disk1sn,Disk1fw,Disk2m,Disk2sn,Disk2fw, `
Disk3m,Disk3sn,Disk3fw,Disk4m,Disk4sn,Disk4fw,Disk5m,Disk5sn,Disk5fw,Disk6m,Disk6sn,Disk6fw, `
StorageCapGB,StorageUseGB,StorageUseLogical,StorageFree,StorageSSDCap,StorageHDDCap

$Report1.NxCluster = $ntnxclus
$Report1.NXHost = $NtnxRestData.entities[$i].name
$Report1.NXIP = $NtnxRestData.entities[$i].service_vmexternal_ip
$Report1.OOBIP = $NtnxRestData.entities[$i].ipmi_address
$Report1.HPVIP = $NtnxRestData.entities[$i].hypervisor_address
$Report1.NSN = $NtnxRestData.entities[$i].serial
$Report1.BSN = $NtnxRestData.entities[$i].block_serial
$Report1.Bmodel = $NtnxRestData.entities[$i].block_model_name
$Report1.CPU = $NtnxRestData.entities[$i].cpu_model.Split(" ")[3,4,6] -join " "
$Report1.Cores = $NtnxRestData.entities[$i].num_cpu_cores
$Report1.Sockets = $NtnxRestData.entities[$i].num_cpu_sockets
$Report1.RAMGB = ($NtnxRestData.entities[$i].memory_capacity_in_bytes / 1GB).ToString("#")
$Report1.HPV = $NtnxRestData.entities[$i].hypervisor_type
$Report1.HPVVer = $NtnxRestData.entities[$i].hypervisor_full_name
$Report1.VMs = $NtnxRestData.entities[$i].num_vms
$Report1.BIOSm = $NtnxRestData.entities[$i].bios_model
$Report1.BIOSv = $NtnxRestData.entities[$i].bios_version
$Report1.BMCm = $NtnxRestData.entities[$i].bmc_model
$Report1.BMCv = $NtnxRestData.entities[$i].bmc_version
$Report1.HBA1m = $NtnxRestData.entities[$i].hba_firmwares_list[0].hba_model
$Report1.HBA1v = $NtnxRestData.entities[$i].hba_firmwares_list[0].hba_version
$Report1.HBA2m = $NtnxRestData.entities[$i].hba_firmwares_list[1].hba_model
$Report1.HBA2v = $NtnxRestData.entities[$i].hba_firmwares_list[1].hba_version
1..6 |% {
    $disknumber = $_ 
    $diskmodel = "disk"+$disknumber+"m";$disksn = "disk"+$disknumber+"sn";$diskfw = "disk"+$disknumber+"fw"
    $Report1.$diskmodel = $NtnxRestData.entities[$i].disk_hardware_configs.$disknumber.model
    $Report1.$disksn = $NtnxRestData.entities[$i].disk_hardware_configs.$disknumber.serial_number
    $Report1.$diskfw = $NtnxRestData.entities[$i].disk_hardware_configs.$disknumber.current_firmware_version
    
    }
$Report1.StorageCapGB = ($NtnxRestData.entities[$i].usage_stats.'storage.capacity_bytes' / 1GB).ToString("#")
$Report1.StorageUseGB = ($NtnxRestData.entities[$i].usage_stats.'storage.usage_bytes' / 1GB).ToString("#")
$Report1.StorageUseLogical = ($NtnxRestData.entities[$i].usage_stats.'storage.logical_usage_bytes' / 1GB).ToString("#")
$Report1.StorageFree = ($NtnxRestData.entities[$i].usage_stats.'storage.free_bytes' / 1GB).ToString("#")
$Report1.StorageFree = ($NtnxRestData.entities[$i].usage_stats.'storage.free_bytes' / 1GB).ToString("#")
$Report1.StorageSSDCap = ($NtnxRestData.entities[$i].usage_stats.'storage_tier.ssd.capacity_bytes' / 1GB).ToString("#")
$Report1.StorageHDDCap = ($NtnxRestData.entities[$i].usage_stats.'storage_tier.das-sata.capacity_bytes' / 1GB).ToString("#")

# Let’s Save the data to the report File 
$Report1 | Export-Csv -Append $NtnxNodeReportName

}

#  Getting Cluster specific Details
$Report2 = "" | select Name,IP,StType,Nodes,NOSv,NCCv,ExtSeg,IntSeg,ShadowClone,DNS,NTP,MGMTSrvIP,MGMTSrv,MgmtSrvType, `
StorageCapGB,StorageUseGB,StorageUseLogical,StorageFree,StorageUsed,Provisioned,IntNets,ExtNets,PDomanCount,PDomains,PDRemoteSites
$NtnxclusData=Invoke-RestMethod -Method Get -Uri "https://$($NutanixclusterName):9440/api/nutanix/v2.0/cluster/" -Headers $Header

$Report2.Name =  $NtnxclusData.name
$Report2.IP = $NtnxclusData.cluster_external_ipaddress
$Report2.StType = $NtnxclusData.storage_type
$Report2.Nodes = $NtnxclusData.num_nodes
$Report2.NOSv = $NtnxclusData.version
$Report2.NCCv = $NtnxclusData.ncc_version.split("-")[1]
$Report2.ExtSeg = $NtnxclusData.external_subnet
$Report2.IntSeg = $NtnxclusData.internal_subnet 
$Report2.ShadowClone = $NtnxclusData.enable_shadow_clones
$Report2.DNS = $NtnxclusData.name_servers -join ","
$Report2.NTP = $NtnxclusData.ntp_servers -join ","
$Report2.MGMTSrvIP = $NtnxclusData.management_servers.ip_address
$Report2.MGMTSrv = (Resolve-DnsName $NtnxclusData.management_servers.ip_address).Server
$Report2.MgmtSrvType = $NtnxclusData.management_servers.management_server_type
$Report2.StorageCapGB = ($NtnxclusData.usage_stats.'storage.capacity_bytes' / 1GB).ToString("#")
$Report2.StorageUseGB = ($NtnxclusData.usage_stats.'storage.usage_bytes' / 1GB).ToString("#")
$Report2.StorageUseLogical = ($NtnxclusData.usage_stats.'storage.logical_usage_bytes' / 1GB).ToString("#")
$Report2.StorageFree = ($NtnxclusData.usage_stats.'storage.free_bytes' / 1GB).ToString("#")
$Report2.StorageUsed = ($NtnxclusData.usage_stats.'storage.usage_bytes' / $NtnxclusData.usage_stats.'storage.capacity_bytes').ToString("P")
$Report2.Provisioned = ($NtnxclusData.usage_stats.'storage.logical_usage_bytes' / $NtnxclusData.usage_stats.'storage.capacity_bytes').ToString("P")

#Network details 
$NtnxNetData=Invoke-RestMethod -Method Get -Uri "https://$($NutanixclusterName):9440/api/nutanix/v2.0/networks/" -Headers $Header
$Report2.IntNets = ($NtnxNetData.entities| ? network_type -eq internal).name -join ","
$Report2.ExtNets = ($NtnxNetData.entities| ? network_type -eq external).name -join ","

# Protection Domains
$NtnxPrtDData=Invoke-RestMethod -Method Get -Uri "https://$($NutanixclusterName):9440/api/nutanix/v2.0/protection_domains/" -Headers $Header
$Report2.PDomanCount = $NtnxPrtDData.entities.count
$Report2.PDomains = $NtnxPrtDData.entities.name -join ","
$Report2.PDRemoteSites = $NtnxPrtDData.entities.replication_links.remote_site_name |sort -Unique 

$Report2 | Export-Csv -Append $NtnxClusReportFile 

# Storage Containers details 
$NtnxStcntData=Invoke-RestMethod -Method Get -Uri "https://$($NutanixclusterName):9440/api/nutanix/v2.0/storage_containers/" -Headers $Header
foreach ( $stcontain in $NtnxStcntData.entities ) {
$Report3 = "" | select ClsName,StCntName,RF,NXManged,ErasC,dedup,comp,vsstore,StCntCapGB,StCntUseGB,StCntUseLogical,StCntFree, `
StCntCAPused,StCntProvisoned

$Report3.ClsName = $Report2.Name 
$Report3.StCntName = $stcontain.Name
$Report3.RF = $stcontain.replication_factor
$Report3.ErasC = $stcontain.erasure_code
$Report3.dedup = $stcontain.on_disk_dedup
$Report3.comp = $stcontain.compression_enabled
$Report3.NXManged = $stcontain.is_nutanix_managed
$Report3.vsstore = $stcontain.vstore_name_list -join ","
$Report3.StCntCapGB = ($stcontain.usage_stats.'storage.capacity_bytes' / 1GB).ToString("#")
$Report3.StCntUseGB = ($stcontain.usage_stats.'storage.usage_bytes' / 1GB).ToString("#")
$Report3.StCntUseLogical = ($stcontain.usage_stats.'storage.logical_usage_bytes' / 1GB).ToString("#")
$Report3.StCntFree = ($stcontain.usage_stats.'storage.free_bytes' / 1GB).ToString("#")
$Report3.StCntCAPused = ($stcontain.usage_stats.'storage.usage_bytes' / $stcontain.usage_stats.'storage.capacity_bytes').ToString("P")
$Report3.StCntProvisoned = ($stcontain.usage_stats.'storage.logical_usage_bytes' / $stcontain.usage_stats.'storage.capacity_bytes').ToString("P")

$Report3 | export-csv -Append $NtnxstcnReportFile 

In case of multiple prism Element and no prism central, this can be adjusted with a hash table containing the PE hostname and their credential

$NXClist = @{
"NCCLs01" = "username:password"
"NCCLs02" = "username:password"

} 

foreach ($ntnxclus in $NXClist.Keys) {
$Header = @{"Authorization" = "Basic "+[System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($NXClist.$ntnxclus))}
$NtnxRestData=Invoke-RestMethod -Method Get -Uri "https://$($ntnxclus):9440/api/nutanix/v2.0/hosts/" -Headers $Header 

<script block>
} 

I will cover using prism central way in the next post.

Leave a Reply

Your email address will not be published. Required fields are marked *

*
*