diff --git a/locksmithctl/daemon.go b/locksmithctl/daemon.go index ed344fb..0426998 100644 --- a/locksmithctl/daemon.go +++ b/locksmithctl/daemon.go @@ -20,6 +20,7 @@ package main import "C" import ( + "errors" "fmt" "os" "os/signal" @@ -116,6 +117,53 @@ func expBackoff(interval time.Duration) time.Duration { return interval } +// waitForRebootWindow get the REBOOT_WINDOW_START, REBOOT_WINDOW_LENGTH +// and check if everything is ok and the get then Periodic. Check if +// it is outside of the reboot window and If yes then sleep and return true. +func waitForRebootWindow() (bool, error) { + var period *timeutil.Periodic + + startw := os.Getenv("LOCKSMITHD_REBOOT_WINDOW_START") + if startw == "" { + startw = os.Getenv("REBOOT_WINDOW_START") + } + + lengthw := os.Getenv("LOCKSMITHD_REBOOT_WINDOW_LENGTH") + if lengthw == "" { + lengthw = os.Getenv("REBOOT_WINDOW_LENGTH") + } + + if (startw == "") != (lengthw == "") { + return false, errors.New("Either both or neither $REBOOT_WINDOW_START and $REBOOT_WINDOW_LENGTH must be set") + } + + if startw != "" && lengthw != "" { + p, err := timeutil.ParsePeriodic(startw, lengthw) + if err != nil { + return false, fmt.Errorf("unable to parse periodic: %w", err) + } + + period = p + } + + if period != nil { + now := time.Now() + sleeptime := period.DurationToStart(now) + if sleeptime > 0 { + dlog.Infof("Reboot window start is %q and length is %q", startw, lengthw) + next := period.Next(time.Now()) + dlog.Infof("Next window begins at %s and ends at %s", next.Start, next.End) + dlog.Infof("Waiting for %s to reboot.", sleeptime) + time.Sleep(sleeptime) + return true, nil + } + } else { + dlog.Info("No configured reboot window") + } + + return false, nil +} + func (r rebooter) rebootAndSleep() { // Broadcast a notice, if broadcast found lines to notify, delay the reboot. delaymins := loginsRebootDelay / time.Minute @@ -138,8 +186,6 @@ func (r rebooter) rebootAndSleep() { // infinite loop if it is in the reboot window. // Returns if the reboot failed. func (r rebooter) lockAndReboot(lck *lock.Lock) { - var period *timeutil.Periodic - interval := initialInterval for { err := lck.Lock() @@ -148,47 +194,15 @@ func (r rebooter) lockAndReboot(lck *lock.Lock) { dlog.Warningf("Failed to acquire lock: %v. Retrying in %v.", err, interval) time.Sleep(interval) - continue - } - - startw := os.Getenv("LOCKSMITHD_REBOOT_WINDOW_START") - if startw == "" { - startw = os.Getenv("REBOOT_WINDOW_START") - } - - lengthw := os.Getenv("LOCKSMITHD_REBOOT_WINDOW_LENGTH") - if lengthw == "" { - lengthw = os.Getenv("REBOOT_WINDOW_LENGTH") - } - - if (startw == "") != (lengthw == "") { - dlog.Fatal("Either both or neither $REBOOT_WINDOW_START and $REBOOT_WINDOW_LENGTH must be set") - } - - if startw != "" && lengthw != "" { - p, err := timeutil.ParsePeriodic(startw, lengthw) + hasSleep, err := waitForRebootWindow() if err != nil { - dlog.Fatalf("Error parsing reboot window: %s", err) + dlog.Fatalf("unable to check reboot window period: %v", err) } - - period = p - } - - if period != nil { - dlog.Infof("Reboot window start is %q and length is %q", startw, lengthw) - next := period.Next(time.Now()) - dlog.Infof("Next window begins at %s and ends at %s", next.Start, next.End) - } else { - dlog.Info("No configured reboot window") - } - - if period != nil { - now := time.Now() - sleeptime := period.DurationToStart(now) - if sleeptime > 0 { - dlog.Infof("Waiting for %s to reboot.", sleeptime) - time.Sleep(sleeptime) + if hasSleep { + interval = initialInterval } + + continue } r.rebootAndSleep() @@ -304,8 +318,6 @@ func unlockHeldLocks(strategy string, stop chan struct{}, wg *sync.WaitGroup) { // attempts to acquire the reboot lock. If the reboot lock is acquired then the // machine will reboot. func runDaemon() int { - var period *timeutil.Periodic - strategy := os.Getenv("REBOOT_STRATEGY") if strategy == "" { @@ -317,39 +329,6 @@ func runDaemon() int { return 0 } - // XXX: REBOOT_WINDOW_* are deprecated in favor of variables with LOCKSMITHD_ prefix, - // but the old ones are read for compatibility. - startw := os.Getenv("LOCKSMITHD_REBOOT_WINDOW_START") - if startw == "" { - startw = os.Getenv("REBOOT_WINDOW_START") - } - - lengthw := os.Getenv("LOCKSMITHD_REBOOT_WINDOW_LENGTH") - if lengthw == "" { - lengthw = os.Getenv("REBOOT_WINDOW_LENGTH") - } - - if (startw == "") != (lengthw == "") { - dlog.Fatal("Either both or neither $REBOOT_WINDOW_START and $REBOOT_WINDOW_LENGTH must be set") - } - - if startw != "" && lengthw != "" { - p, err := timeutil.ParsePeriodic(startw, lengthw) - if err != nil { - dlog.Fatalf("Error parsing reboot window: %s", err) - } - - period = p - } - - if period != nil { - dlog.Infof("Reboot window start is %q and length is %q", startw, lengthw) - next := period.Next(time.Now()) - dlog.Infof("Next window begins at %s and ends at %s", next.Start, next.End) - } else { - dlog.Info("No configured reboot window") - } - coordinatorConf, err := coordinatorconf.New(coordinatorName, strategy) if err != nil { dlog.Fatalf("unable to become 'update coordinator': %v", err) @@ -407,13 +386,8 @@ func runDaemon() int { close(stop) wg.Wait() - if period != nil { - now := time.Now() - sleeptime := period.DurationToStart(now) - if sleeptime > 0 { - dlog.Infof("Waiting for %s to reboot.", sleeptime) - time.Sleep(sleeptime) - } + if _, err := waitForRebootWindow(); err != nil { + dlog.Fatalf("unable to check reboot window period: %v", err) } return r.reboot()