107 lines
3 KiB
Go
107 lines
3 KiB
Go
package main
|
|
|
|
import (
|
|
"flag"
|
|
"log"
|
|
|
|
"github.com/golang/glog"
|
|
"github.com/nightlyone/lockfile"
|
|
)
|
|
|
|
const upsMinutesRemainingThreshold = 20
|
|
|
|
type idracCredentials = struct {
|
|
url string
|
|
username string
|
|
password string
|
|
}
|
|
|
|
func main() {
|
|
idracUsername := flag.String("idracUsername", "root", "iDRAC username")
|
|
idracPassword := flag.String("idracPassword", "calvin", "iDRAC password")
|
|
idracHost := flag.String("idracHost", "192.168.1.4", "iDRAC host")
|
|
flag.Parse()
|
|
defer glog.Flush()
|
|
// lock, err := tryGetLock()
|
|
// if err != nil {
|
|
// glog.Fatalf("Failed to acquire lock: %v", err)
|
|
// }
|
|
// defer lock.Unlock()
|
|
|
|
glog.Info("Checking server power state")
|
|
idracCredentials := idracCredentials{
|
|
url: "https://" + *idracHost,
|
|
username: *idracUsername,
|
|
password: *idracPassword,
|
|
}
|
|
powerState, err := checkPowerState(idracCredentials)
|
|
if err != nil {
|
|
glog.Fatalf("Failed to check power state: %v", err)
|
|
}
|
|
glog.Infof("Server power state: %s", powerState)
|
|
|
|
glog.Info("Checking UPS state")
|
|
snmp := getSNMPClient()
|
|
// Connect to the SNMP agent
|
|
err = snmp.Connect()
|
|
if err != nil {
|
|
log.Fatalf("Failed to connect to UPS SNMP agent: %v", err)
|
|
}
|
|
defer snmp.Conn.Close()
|
|
|
|
upsState, err := getPowerState(snmp)
|
|
if err != nil {
|
|
glog.Fatalf("Failed to get UPS power state: %v", err)
|
|
}
|
|
|
|
if powerState == "On" {
|
|
handleWhenServerOn(upsState, idracCredentials)
|
|
} else if powerState == "Off" {
|
|
handleWhenServerOff(upsState, idracCredentials)
|
|
} else {
|
|
glog.Fatalf("Unknown server state %s", powerState)
|
|
}
|
|
}
|
|
func handleWhenServerOn(upsState UPSPowerState, idracCredentials idracCredentials) {
|
|
if upsState.inputVoltage > 0 {
|
|
glog.Infof("UPS is on AC power: %d. Nothing to do.\n", upsState.inputVoltage)
|
|
return
|
|
} else {
|
|
glog.Warningln("UPS is on Battery power")
|
|
if upsState.minutesRemaining < upsMinutesRemainingThreshold {
|
|
glog.Warningf("Minutes remaining is too low - %d Turning off server.", upsState.minutesRemaining)
|
|
// Perform a graceful shutdown of the server
|
|
performGracefulShutdown(idracCredentials)
|
|
} else {
|
|
glog.Warningf("Minutes remaining is %d. Server will not be shutdown yet.", upsState.minutesRemaining)
|
|
return
|
|
}
|
|
}
|
|
}
|
|
|
|
func handleWhenServerOff(upsState UPSPowerState, idracCredentials idracCredentials) {
|
|
if upsState.inputVoltage > 0 {
|
|
glog.Infof("UPS is on AC power: %d\n", upsState.inputVoltage)
|
|
if upsState.minutesRemaining < upsMinutesRemainingThreshold {
|
|
glog.Infof("UPS battery is still too low - %d minutes remaining. Not turning on server yet.\n", upsState.minutesRemaining)
|
|
} else {
|
|
glog.Infof("UPS is on AC power and battery has charged - %d minutes remaining. Turning on server...\n", upsState.minutesRemaining)
|
|
// Perform startup of the server
|
|
performPowerOn(idracCredentials)
|
|
}
|
|
} else {
|
|
glog.Warningln("UPS is still on battery power")
|
|
return
|
|
}
|
|
}
|
|
func tryGetLock() (*lockfile.Lockfile, error) {
|
|
lock, err := lockfile.New("/tmp/server_safe_poweroff.pid")
|
|
if err != nil {
|
|
log.Fatalf("Failed to create lock file: %v", err)
|
|
}
|
|
err = lock.TryLock()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &lock, nil
|
|
}
|