Advertisement
Guest User

Untitled

a guest
Oct 15th, 2013
322
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. # Watch-UPS.ps1
  2. # powershell v2 CP3
  3. # Version: 1.5
  4. # Date jan 2011
  5. # Latest version: mar 2013
  6. # Author:  Paul Weterings
  7. # www.servercare.nl
  8.  
  9. # Description:
  10. <#
  11. This script monitors the UPS or Battery connected to the system in the
  12. $computer variable. As soon as it detects that the system is going offline
  13. (hence starts using the UPS/Battery it will compare the percentage
  14. power left to a a list of system names provided in the 'watch-ups.csv' file.
  15.  
  16. Each system in the .csv list has an associated percentage listed; if the
  17. battery level has dropped below the percentage listed for that system, the
  18. script will send a shutdown request to that system.
  19.  
  20. The idea is to shut down the least critical systems first, providing them
  21. a 'clean shutdown' rather then an abrupt power off when the UPS is empty.
  22. Additionally; shutting down the least critical systems first will allow
  23. other, possibly more critical systems (such as a NAS or SQL server for
  24. example) to remain on the UPS longer, since it now has to cater to less
  25. systems.
  26.  
  27. example contents of the .csv file:
  28.  
  29. systemname, percentage, status
  30. game1, 80, 0
  31. scom1, 80, 0
  32. mail1, 50, 0
  33. sql1, 10, 0
  34. nas1, 5, 0
  35.  
  36. This means the game and scom servers will be shut down first, when the UPS
  37. is at 80% power left. Since the UPS now has 2 less servers to support, there's
  38. more power for the other servers to remain running during a power failure.
  39. At 50% we stop the mail server, since typically an Exchange server needs some
  40. time to shut down, we sent it the shutdown command fairly soon. We wait until
  41. the very last drops of power left (resp 10% and 5%) to sent the sql and nas
  42. server the shutdown command.
  43.  
  44. -systemname = needs to be a (network reachable) name of a system on the network.
  45.  
  46. -percentage = the percentage of power left in the UPS at which we need to send
  47. a shutdown command to this system.
  48.  
  49. -status = 0 means the system should be shut down,
  50. 1 means ' no action' (for test situations for example) BE CAREFUL; after the power
  51. goes off, and then on again the script will 're-arm' and status will be 0
  52. for all servers. This means they will shut down at a second 'power failure'.
  53.  
  54. actions of this script are logged on screen and to the application eventlog of
  55. the system running it as well as mailed.
  56. #>
  57.  
  58. # the computer system that we will be measuring; the UPS is connected here.
  59. # CHANGE THIS TO YOUR SYSTEM NAME THAT HAS THE UPS CONNECTED.
  60. # or leave it '.' which is the local system
  61. $computer = "mon1.DOMAIN"
  62.  
  63. $namespace = "root\CIMV2"
  64. $batstat= @{"1"="battery is discharging";"2"="On AC";"3"="Fully Charged";"4"=`
  65. "Low";"5"="Critical";"6"="Charging";"7"="Charging and High";"8"="Charging and`
  66. Low";"9"="Charging and Critical";"10"="Undefined";"11"="Partially Charged";}
  67.  
  68. # We will be sending a mail at each shutdown
  69. # Change this to what you want
  70. $emailFrom = "REMOVED"
  71. # Make this your E-Mail address
  72. $emailTo = "REMOVED"
  73. $subject = "Watch-UPS action"
  74. #Make this your SMTP mail server
  75. $smtpServer = "REMOVED"
  76. $smtp = new-object Net.Mail.SmtpClient($smtpServer)
  77.  
  78. # for eventlogging purposes:
  79. # we simply want to know if our script was registered with the eventlog already
  80. Get-EventLog -source Watch-UPS -LogName Application -ErrorAction silentlycontinue | Out-Null
  81.  
  82. if (-not$?)
  83. {
  84.     # there's an error, so we must not be listed yet, lets see to it we exist
  85.     # for eventlogging
  86.     New-EventLog -source Watch-UPS -LogName Application -ErrorAction silentlycontinue | Out-Null
  87. }
  88.  
  89.  
  90. # note that any error for Get-WMI object would not be a 'terminating error',
  91. # since the script won't stop # you can't use try/catch or trap to catch any
  92. # errors. I choose to be silent about the error and # handle the result to see
  93. # if an error occurred.
  94. $batinfo = Get-WmiObject -class Win32_Battery -computername $computer -ErrorAction silentlycontinue -namespace $namespace
  95.  
  96. # we want to check if we could reach a system, and if we did; did it return
  97. # battery info?
  98. # powershell is so great with stuff like this!
  99. if ($? -and $batinfo)
  100. {
  101.      "Battery status on    : " + $computer +" status: "+ $batstat.Get_Item([string]$batinfo.BatteryStatus)
  102.      "Percentage left      : " + $batinfo.EstimatedChargeRemaining
  103.  
  104.     # Read an interpret the configuration comma seperated values file
  105.     # Note this is a hardcoded path, you could also use the 'Get-Location' cmdlet
  106.     $path = "C:\netshutdown\watch-ups\"#Get-Location
  107.     $lines = Import-Csv "$path\watch-ups.csv"
  108.    
  109.     # Report to screen what servers we are looking after
  110.     "`nWatch-UPS will manage:"
  111.     $lines
  112.     # And lets show in the eventlog we started (nice to know if you start this script as a task)
  113.     write-eventlog -logname Application -source Watch-UPS -eventID 3001 -entrytype Information -message "Watch-UPS 1.5 started"
  114.     "-------------------------------"
  115. }
  116. else
  117. {
  118.     if ($error)
  119.     {
  120.         "Could not find any battery/UPS information on system: " + $computer
  121.         throw $error[0].Exception
  122.     }
  123. }
  124. $wewereonbattery = $false
  125. $powerstatus = $true
  126.  
  127. # Never ending story, we keep looping. Don't worry, we're not using much resources. (hardly any)
  128. while($true)
  129. {
  130.     $batinfo = Get-WmiObject -class Win32_Battery -computername $computer -ErrorAction silentlycontinue -namespace $namespace
  131.     if ($?) # No error?
  132.     {    
  133.         # Only check if we need to take action (BatteryStatus = 2 is not on AC)    
  134.         if ($batinfo.BatteryStatus -ne 2)
  135.         {
  136.             $date = Get-Date
  137.             if ($powerstatus)
  138.             {
  139.                 write-eventlog -logname Application -source Watch-UPS -eventID 3003 -entrytype Warning -message "$date : power failure detected" -category 1
  140.                 $powerstatus = $false
  141.             }
  142.             $wewereonbattery = $true
  143.             # Iterate through all the systems we have found in the config file
  144.             # and check their reboot-percentages against our UPS percentage
  145.             foreach ($system in $lines)
  146.             {
  147.                 # Do we have a winner?
  148.                 if ($batinfo.EstimatedChargeRemaining -le $system.percentage -and $system.status -eq 0)
  149.                 {
  150.                     # We are shutting down the system, lets log it in the
  151.                     # eventlog and put it on screen
  152.                     $date = Get-Date
  153.                     $report = "$date : shutting down " + $system.systemname + " at " + $system.percentage +"% power left."
  154.                     write-eventlog -logname Application -source Watch-UPS -eventID 3002 -entrytype Information -message $report -category 1
  155.                     $report
  156.                     # This assumes the script is being run with credentials
  157.                     # that allow shutting down the remote system.
  158.                     # Use a service account with the correct rights to run this if you start this script as a task.
  159.                     #
  160.                     # If you really want credentials:
  161.                     # (gwmi win32_operatingsystem -ComputerName MyServer
  162.                     # -cred (get-credential)
  163.                     # where (get-credential) can be replaced with credentials
  164.                     # (not a good idea to put credentials in a script!)
  165.                    
  166.                     # msdn.microsoft.com/en-us/library/aa394058(VS.85).aspx
  167.                     $shutsys = gwmi win32_operatingsystem -ComputerName $system.systemname -ErrorAction silentlycontinue
  168.                     if($?) # Did the WMI operation go OK?
  169.                     {
  170.                         # WMI has found the system, so we should be able to
  171.                         # send it a shutdown command
  172.                         $shutsys.Win32Shutdown(12)
  173.                         # remember that we have sent this system a shutdown
  174.                         # command, so we only do it once for each powerloss,
  175.                         # we store this status (1) with the system info.
  176.                         $system.status =1
  177.                        
  178.                         # Lets notify the user by sending an E-Mail
  179.                         $body = $system.systemname + " was sent the shutdown command."
  180.                         $smtp.Send($emailFrom, $emailTo, $subject, $body)
  181.                     }
  182.                     else
  183.                     {
  184.                         $body = $system.systemname + ": The system to shut down was not reached"
  185.                         # it wasn't there, so we ignore it from now on
  186.                         $system.status =-1
  187.                         $smtp.Send($emailFrom, $emailTo, $subject, $body)
  188.                         write-eventlog -logname Application -source Watch-UPS -eventID 3003 -entrytype Warning -message $body -category 1
  189.                     }
  190.                 }            
  191.             }
  192.         }
  193.         else
  194.         {   # Since the UPS is appearantly on AC, all systems need to
  195.             # be "shutdownable".
  196.             # we basically " re-arm" the status after a potental powerloss
  197.             # may have previously shut down systems but the script kept running
  198.             # as power was restored.
  199.             # We only do this after we initially lost power once...
  200.             if ($wewereonbattery)
  201.             {
  202.                 $date = Get-Date
  203.                 if ($powerstatus -eq $false)
  204.                 {
  205.                     write-eventlog -logname Application -source Watch-UPS -eventID 3003 -entrytype Information -message "$date : AC power detected" -category 1
  206.                     $powerstatus = $true
  207.                 }
  208.                 foreach ($system in $lines)
  209.                 {
  210.                     $system.status = 0  
  211.                 }
  212.             }
  213.         }
  214.     }
  215.     else
  216.     {
  217.         $date = Get-Date
  218.         "$date : No UPS system found - was it shut down?"
  219.     }
  220.    
  221.     # Lets wait a second
  222.     Start-Sleep -Seconds 1
  223. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement