Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- # Watch-UPS.ps1
- # powershell v2 CP3
- # Version: 1.5
- # Date jan 2011
- # Latest version: mar 2013
- # Author: Paul Weterings
- # www.servercare.nl
- # Description:
- <#
- This script monitors the UPS or Battery connected to the system in the
- $computer variable. As soon as it detects that the system is going offline
- (hence starts using the UPS/Battery it will compare the percentage
- power left to a a list of system names provided in the 'watch-ups.csv' file.
- Each system in the .csv list has an associated percentage listed; if the
- battery level has dropped below the percentage listed for that system, the
- script will send a shutdown request to that system.
- The idea is to shut down the least critical systems first, providing them
- a 'clean shutdown' rather then an abrupt power off when the UPS is empty.
- Additionally; shutting down the least critical systems first will allow
- other, possibly more critical systems (such as a NAS or SQL server for
- example) to remain on the UPS longer, since it now has to cater to less
- systems.
- example contents of the .csv file:
- systemname, percentage, status
- game1, 80, 0
- scom1, 80, 0
- mail1, 50, 0
- sql1, 10, 0
- nas1, 5, 0
- This means the game and scom servers will be shut down first, when the UPS
- is at 80% power left. Since the UPS now has 2 less servers to support, there's
- more power for the other servers to remain running during a power failure.
- At 50% we stop the mail server, since typically an Exchange server needs some
- time to shut down, we sent it the shutdown command fairly soon. We wait until
- the very last drops of power left (resp 10% and 5%) to sent the sql and nas
- server the shutdown command.
- -systemname = needs to be a (network reachable) name of a system on the network.
- -percentage = the percentage of power left in the UPS at which we need to send
- a shutdown command to this system.
- -status = 0 means the system should be shut down,
- 1 means ' no action' (for test situations for example) BE CAREFUL; after the power
- goes off, and then on again the script will 're-arm' and status will be 0
- for all servers. This means they will shut down at a second 'power failure'.
- actions of this script are logged on screen and to the application eventlog of
- the system running it as well as mailed.
- #>
- # the computer system that we will be measuring; the UPS is connected here.
- # CHANGE THIS TO YOUR SYSTEM NAME THAT HAS THE UPS CONNECTED.
- # or leave it '.' which is the local system
- $computer = "mon1.DOMAIN"
- $namespace = "root\CIMV2"
- $batstat= @{"1"="battery is discharging";"2"="On AC";"3"="Fully Charged";"4"=`
- "Low";"5"="Critical";"6"="Charging";"7"="Charging and High";"8"="Charging and`
- Low";"9"="Charging and Critical";"10"="Undefined";"11"="Partially Charged";}
- # We will be sending a mail at each shutdown
- # Change this to what you want
- $emailFrom = "REMOVED"
- # Make this your E-Mail address
- $emailTo = "REMOVED"
- $subject = "Watch-UPS action"
- #Make this your SMTP mail server
- $smtpServer = "REMOVED"
- $smtp = new-object Net.Mail.SmtpClient($smtpServer)
- # for eventlogging purposes:
- # we simply want to know if our script was registered with the eventlog already
- Get-EventLog -source Watch-UPS -LogName Application -ErrorAction silentlycontinue | Out-Null
- if (-not$?)
- {
- # there's an error, so we must not be listed yet, lets see to it we exist
- # for eventlogging
- New-EventLog -source Watch-UPS -LogName Application -ErrorAction silentlycontinue | Out-Null
- }
- # note that any error for Get-WMI object would not be a 'terminating error',
- # since the script won't stop # you can't use try/catch or trap to catch any
- # errors. I choose to be silent about the error and # handle the result to see
- # if an error occurred.
- $batinfo = Get-WmiObject -class Win32_Battery -computername $computer -ErrorAction silentlycontinue -namespace $namespace
- # we want to check if we could reach a system, and if we did; did it return
- # battery info?
- # powershell is so great with stuff like this!
- if ($? -and $batinfo)
- {
- "Battery status on : " + $computer +" status: "+ $batstat.Get_Item([string]$batinfo.BatteryStatus)
- "Percentage left : " + $batinfo.EstimatedChargeRemaining
- # Read an interpret the configuration comma seperated values file
- # Note this is a hardcoded path, you could also use the 'Get-Location' cmdlet
- $path = "C:\netshutdown\watch-ups\"#Get-Location
- $lines = Import-Csv "$path\watch-ups.csv"
- # Report to screen what servers we are looking after
- "`nWatch-UPS will manage:"
- $lines
- # And lets show in the eventlog we started (nice to know if you start this script as a task)
- write-eventlog -logname Application -source Watch-UPS -eventID 3001 -entrytype Information -message "Watch-UPS 1.5 started"
- "-------------------------------"
- }
- else
- {
- if ($error)
- {
- "Could not find any battery/UPS information on system: " + $computer
- throw $error[0].Exception
- }
- }
- $wewereonbattery = $false
- $powerstatus = $true
- # Never ending story, we keep looping. Don't worry, we're not using much resources. (hardly any)
- while($true)
- {
- $batinfo = Get-WmiObject -class Win32_Battery -computername $computer -ErrorAction silentlycontinue -namespace $namespace
- if ($?) # No error?
- {
- # Only check if we need to take action (BatteryStatus = 2 is not on AC)
- if ($batinfo.BatteryStatus -ne 2)
- {
- $date = Get-Date
- if ($powerstatus)
- {
- write-eventlog -logname Application -source Watch-UPS -eventID 3003 -entrytype Warning -message "$date : power failure detected" -category 1
- $powerstatus = $false
- }
- $wewereonbattery = $true
- # Iterate through all the systems we have found in the config file
- # and check their reboot-percentages against our UPS percentage
- foreach ($system in $lines)
- {
- # Do we have a winner?
- if ($batinfo.EstimatedChargeRemaining -le $system.percentage -and $system.status -eq 0)
- {
- # We are shutting down the system, lets log it in the
- # eventlog and put it on screen
- $date = Get-Date
- $report = "$date : shutting down " + $system.systemname + " at " + $system.percentage +"% power left."
- write-eventlog -logname Application -source Watch-UPS -eventID 3002 -entrytype Information -message $report -category 1
- $report
- # This assumes the script is being run with credentials
- # that allow shutting down the remote system.
- # Use a service account with the correct rights to run this if you start this script as a task.
- #
- # If you really want credentials:
- # (gwmi win32_operatingsystem -ComputerName MyServer
- # -cred (get-credential)
- # where (get-credential) can be replaced with credentials
- # (not a good idea to put credentials in a script!)
- # msdn.microsoft.com/en-us/library/aa394058(VS.85).aspx
- $shutsys = gwmi win32_operatingsystem -ComputerName $system.systemname -ErrorAction silentlycontinue
- if($?) # Did the WMI operation go OK?
- {
- # WMI has found the system, so we should be able to
- # send it a shutdown command
- $shutsys.Win32Shutdown(12)
- # remember that we have sent this system a shutdown
- # command, so we only do it once for each powerloss,
- # we store this status (1) with the system info.
- $system.status =1
- # Lets notify the user by sending an E-Mail
- $body = $system.systemname + " was sent the shutdown command."
- $smtp.Send($emailFrom, $emailTo, $subject, $body)
- }
- else
- {
- $body = $system.systemname + ": The system to shut down was not reached"
- # it wasn't there, so we ignore it from now on
- $system.status =-1
- $smtp.Send($emailFrom, $emailTo, $subject, $body)
- write-eventlog -logname Application -source Watch-UPS -eventID 3003 -entrytype Warning -message $body -category 1
- }
- }
- }
- }
- else
- { # Since the UPS is appearantly on AC, all systems need to
- # be "shutdownable".
- # we basically " re-arm" the status after a potental powerloss
- # may have previously shut down systems but the script kept running
- # as power was restored.
- # We only do this after we initially lost power once...
- if ($wewereonbattery)
- {
- $date = Get-Date
- if ($powerstatus -eq $false)
- {
- write-eventlog -logname Application -source Watch-UPS -eventID 3003 -entrytype Information -message "$date : AC power detected" -category 1
- $powerstatus = $true
- }
- foreach ($system in $lines)
- {
- $system.status = 0
- }
- }
- }
- }
- else
- {
- $date = Get-Date
- "$date : No UPS system found - was it shut down?"
- }
- # Lets wait a second
- Start-Sleep -Seconds 1
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement