I set up Hyper-V replica between two clusters in two offices, and needed a way of keeping track of replica health. I used a PowerShell script running from a utility server on a scheduled task to accomplish this.
This script runs a “get-vmreplication” command on each cluster node, and sends an email if any is found in warning or critical state.
One issue I needed to solve was the permissions required to run this from a utility server. I’m sure there are many other (and better) ways to accomplish this such as group managed service accounts, but there are certain limitations in my environment.
First I created an account in AD to act as a service account, as a standard user. I used the “ConvertFrom-SecureString” cmdlet as demonstrated in this article, as the SYSTEM account on my utility server, to produce a file for building a credential object in my PowerShell script. To run this as SYSTEM I used “psexec -s -i powershell.exe”.
Then I created a scheduled task, set to run as SYSTEM when not logged on, at 12 hour intervals, with the action of running the script below:
$password = Get-Content C:\scripts\MaintenanceChecks\SecureString.txt | ConvertTo-SecureString
$Credential = New-Object System.Management.Automation.PSCredential("svc.clusterhealth@domain.com",$password)
$Servers = @("ClusterHost1","ClusterHost2","ClusterHost3","ClusterHost4")
Foreach ($server in $Servers)
{
Invoke-Command -credential $credential -computername $server -scriptblock {
$resultsWarn = get-vmreplication | where-object {$_.Health -like "Warning"}
if ($resultsWarn)
{
$smtpServer = "relay.domain.com"
$port = "25"
$message = New-Object System.Net.Mail.MailMessage
$message.From = "fromaddress@domain.com"
$message.Sender = "fromaddress@domain.com"
$message.To.Add( "toaddress@domain.com" )
$message.Subject = "Replication Health Warning - $($Using:server)"
$message.IsBodyHtml = $true
$message.Body = "Replication health was found to be in warning state for the following VMs: $($resultsWarn.Name)"
$Client = New-Object System.Net.Mail.SmtpClient( $smtpServer , $port )
$Client.Send( $message )
}
$resultsCrit = get-vmreplication | where-object {$_.Health -like "Critical"}
if ($resultsCrit)
{
$smtpServer = "relay.domain.com"
$port = "25"
$message = New-Object System.Net.Mail.MailMessage
$message.From = "fromaddress@domain.com"
$message.Sender = "fromaddress@domain.com"
$message.To.Add( "toaddress@domain.com" )
$message.Subject = "Replication Health Critical - $($Using:server)"
$message.IsBodyHtml = $true
$message.Body = "Replication health was found to be in CRITICAL state for the following VMs: $($resultsCrit.Name)"
$Client = New-Object System.Net.Mail.SmtpClient( $smtpServer , $port )
$Client.Send( $message )
}
}
}