Hyper-V – Using a UPS with Hyper-V Server, graceful shutdown and email alerts

So the situation is that you want to add a UPS to your dev server but don’t want to go to the expense of a enterprise grade UPS.  You can buy “personal” UPS from about £100 and these are often more than up to the job of providing UPS backup but the cavate is that you don’t get the enterprise software and the consumer software that comes with the UPS don’t support Windows Server let alone the core version found with Hyper-V server.

I did a lot of digging around the internet to find this information, I can’t take credit for the scripts which can be found here however I have tweaked the PowerShell script to support authentication onto a email server using SSL.  This blog basically brings everything together in some simple to follow steps.

When you connect a UPS to Windows via a USB the OS will detect the device and the power options change to include the battery options, these are the options you normally find if you’re using a laptop.  The options that control when a PC should shutdown when a particular battery level is reached.  These scripts basically monitor these conditions via WMI to either shutdown the server at a predetermined battery percentage and send alert emails that the server is on battery power.

Create VBS script to gracefully shutdown the server before the battery expires.

So what normally happens in a power cut is the VMs are basically powered off with no shutdown, this isn’t a good thing particularly with servers like Domain controllers or databases.  This script monitors the battery state via WMI and when it hits 15% the server is shutdown gracefully.  Hyper-V will handle the shutdown of the VMs depending on what settings you have configured against the VM i.e. save state or shutdown.

set wmi = GetObject(“winmgmts:{impersonationLevel=impersonate,(Shutdown)}!\\.\root\cimv2”)
set batteryColl = wmi.ExecQuery(“select * from Win32_Battery”)
set osColl = wmi.ExecQuery(“select * from Win32_OperatingSystem”)
while true
for each battery in batteryColl
battery.Refresh_
if battery.batteryStatus = 1 and battery.EstimatedChargeRemaining <= 15 then
for each os in osColl
os.Win32Shutdown 1
next
end if
next
wscript.Sleep 15000
wend

To ensure that this script is running all the time we need to configure a scheduled task for it.  This task is configured to run under a high privilege account and is configured if the user is logged in or not.

Action:

IT Geek Rambling - Hyper-V and UPS configuration

Conditions:

IT Geek Rambling - Hyper-V and UPS configuration

Ensure that the “Start the task only if the computer is on AC power” is unticked

Settings:

IT Geek Rambling - Hyper-V and UPS configuration

You want the task to run forever so ensure that “Stop the task if it runs longer than” is also unticked.

Creating email alerts of UPS status

Like the VBS script above this monitors the power condition on the server and then sends alerts when this condition changes.  It will also send an alert when the power is returned to the server.

PowerShell Script

# Initialize Variables
# Shutdown threshold at 50% of remaining UPS capacity
$threshhold = 50
$interval = 60
$OnBattery = 0
$Event = 0
$hostname = “SERVER NAME”  # Enter the server name here

# Create SMTP client
$from = “server@domain.com”  # Enter the from email address here
$to = “alerts@domain.com” # Enter the email address of where you want the alerts to go
$smtp = “smtp.domain.com” # SMTP server address
$secpasswd = ConvertTo-SecureString “PASSWORD” -AsPlainText -Force # Add the password of the sending account
$mycreds = New-Object System.Management.Automation.PSCredential($from, $secpasswd)

# Loop on Battery Query
while (1)
{
$bat = get-wmiobject -class CIM_Battery -namespace “root\CIMV2”
$batstatus = $bat.batterystatus
$batcapacity = $bat.estimatedchargeremaining
$timetoshutdown = $bat.estimatedruntime/2

if ($batstatus -eq 1)
{
$Event = 1
$OnBattery = 1
# “On Battery”

$Subject = “Utility Power Failure: {0} is running On UPS Battery” -f $hostname
$Body   = “UPS at {0} % remaining capacity, approximately {1} minutes before {2} shutdown.” -f $batcapacity, $timetoshutdown, $hostname

if ($batcapacity -lt ($threshhold +5) )
{
$Body = “Shutdown imminent at {0} %, with ” -f $threshhold + $Body
}

}

elseif (($batstatus -eq 2) -and ($OnBattery -eq 1))
{
$Event = 1
$OnBattery = 0
# “Power Restored”

$Subject = “Utility Power Restored to {0}.” -f $hostname
$Body   = “Battery at {0} % capacity. UPS charging… ” -f $batcapacity
}

if ($Event -eq 1) # Create mail message
{
$Event = 0
Send-MailMessage -To $to -From $from -Subject $subject -Body $body -Credential $mycreds -SmtpServer $smtp -DeliveryNotificationOption Never -BodyAsHtml -usessl
}

sleep $interval
}

Again, as above this is run as a scheduled task that starts at server start up and runs forever under a high privileged user weather they are logged in or not.

Actions:

IT Geek Rambling - Hyper-V and UPS configuration

 

Leave a Reply

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