Receiving alerts from Nutanix Prism / Prism Central using REST with PowerShell

Today i wanted to add another section to my health check scripts, i wanted to get all unresolved, not acknowledged alerts from Nutanix Prism Central.
Nutanix has a nice REST explorer , you can check / test everything from your Nutnix Prism website and then transfer that to a script. Since i have already Prism Central, i don’t need to connect to each cluster Prism, you can do it though with this script. Just give the prism ip/url instead of prism central.
So below is a dirty script that does the work:

#to generate the password use:
#read-host -assecurestring | convertfrom-securestring | out-file C:\password.txt
$username = 'admin'
$PasswordFilePath = 'c:\password.txt'
$passwd= get-content $PasswordFilePath| convertto-securestring
$Password=[System.Runtime.InteropServices.marshal]::PtrToStringAuto([System.Runtime.InteropServices.marshal]::SecureStringToBSTR($passwd))
$Header = @{"Authorization" = "Basic "+[System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($username+":"+$password ))}
$PrismNode = 'prismcentral.company.com'
$uri= "https://${PrismNode}:9440/PrismGateway/services/rest/v1/alerts/?resolved=false&acknowledged=false"

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

$myTimeZone=[System.TimeZoneInfo]::FindSystemTimeZoneById("Central European Standard Time")

#We can check TimeZones with: [system.timezoneinfo]::GetSystemTimeZones()
#[System.TimeZoneInfo]::ConvertTimeFromUtc( date , timezone )  -> converts time to given timezone
#(New-Object -Type DateTime -ArgumentList 1970, 1, 1, 0, 0, 0, 0).AddSeconds([math]::Floor(1430056923792344/1000000)) -> Converts time from timestamp , time was in Useconds hence /1000000

$Context=$null
$response=Invoke-RestMethod -Uri $uri -Header $Header
Foreach($alarm in $response.entities)
{
#Create context hash for each alarm Binding ContextTypes with ContextValues
$Context=@{}
$i=0
foreach ($name in $alarm.ContextTypes) 
{
#Watch out for empty entries ( no idea why there are null entries for Type that correspond to a value )
	if($name)
	{
		$Context.Add($name,$alarm.ContextValues[$i])
	}
	$i++
}
#Swap the {var} with value from our $context hash
	Foreach ($ContextType in ([regex]::Matches($alarm.message,'{(.*?)}')).Value )
	{
		$ContextTypeName=$ContextType.Substring(1,$ContextType.Length-2)
		$alarm.message = $alarm.message -replace $ContextType,$context[$ContextTypeName]
	}
$createdTime = ([System.TimeZoneInfo]::ConvertTimeFromUtc((New-Object -Type DateTime -ArgumentList 1970, 1, 1, 0, 0, 0, 0).AddSeconds([math]::Floor($alarm.createdTimeStampInUsecs/1000000)),$myTimeZone)).ToString()
$alarm | select-object -property @{n='CreatedTime';e={$createdTime}}, severity, alertType, message
}

In response we should get all the alerts like on the screenshot below:
ntpr1

Or even from out-gridview:

ntpr2

I am not 100% sure if i am doing it correct though, but i compared the text from prism, and that looks ok what i generate. I should spend more time on googling about the Nutanix REST API first i suppose 😉 but i had only few hours to do that. In the response we receive alert entities with a property ‘message’ , as you can see it keeps a placeholders for data like {ip_address} or {reboot_timestamp_str}, which we need to translate in order to see full message.

ntpr3

I might be wrong here or doing something in weird way but i guess outcome is accurate:
We take the {var} and replace it with value.
We have property contextTypes and contextValues, each entry from Type has its value in corresponding row from contextValues. I saw that sometimes contextType row is null, but the corresponding value has some string though. Looks like a duplicate text of another Type that is covered there, so i assumed that is safe not to take it with me to context hash.
That’s how example hash for an alert looks like that i am building:
ntpr4
So regex looks for {xxx} then replaces it with the corresponding value from context hash. For each alert i am building the context hash as alerts can be different and they have different contextTypes.
The time is also not exactly clear for me as ‘timestamp_str’ is way different than the createdTimeStampInUsecs. Anyway i have output done in the same way as Prism shows on the website.
Time in createdTimeStampInUsecs is an unix timestamp and has to be converted to ‘windows datetime’, this timestamp is written in microseconds hence we are dividing it by 1000000. After this is done , i am converting that date to my timezone.
All alerts that i am getting are those which are not acknowledged neither resolved. Authentication for Nutanix REST is described here for example:
http://prismdevkit.com/lesson-3-authenticating-to-prism-api-over-ssl-with-http-headers/
So that concludes my first attempt to connect to Nutanix PRISM via REST using Powershell 😉
I hope it will help to start with other projects.