From f70d888abc6368f7fa4009650a86de687f2e92f4 Mon Sep 17 00:00:00 2001 From: Aniruddha Basak Date: Mon, 19 Jul 2021 22:55:33 +0530 Subject: [PATCH] Add waitForRebootWindow to sleep till next window waitForRebootWindow get the environment variable REBOOT_WINDOW_START and REBOOT_WINDOW_LENGTH and check if everything is ok or not. If not then return error. If ok then get the next periodic by the ParsePeriodic function. Then check if we are inside the reboot window or not. If we are inside the reboot window then it will sleep until the next window and return a true. If outside the window then it just return the false. In the lockAndReboot function we check if it has sleep or not and handle the error. --- locksmithctl/daemon.go | 138 +++++++++++++++++------------------------ 1 file changed, 56 insertions(+), 82 deletions(-) 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()